1.1 --- a/.hgtags Mon Nov 23 10:04:47 2009 +0000
1.2 +++ b/.hgtags Wed Nov 25 11:08:25 2009 -0800
1.3 @@ -50,3 +50,4 @@
1.4 f708138c9aca4b389872838fe6773872fce3609e jdk7-b73
1.5 eacb36e30327e7ae33baa068e82ddccbd91eaae2 jdk7-b74
1.6 8885b22565077236a927e824ef450742e434a230 jdk7-b75
1.7 +8fb602395be0f7d5af4e7e93b7df2d960faf9d17 jdk7-b76
2.1 --- a/make/docs/CORE_PKGS.gmk Mon Nov 23 10:04:47 2009 +0000
2.2 +++ b/make/docs/CORE_PKGS.gmk Wed Nov 25 11:08:25 2009 -0800
2.3 @@ -160,10 +160,8 @@
2.4 javax.lang.model.type \
2.5 javax.lang.model.util \
2.6 javax.management \
2.7 - javax.management.event \
2.8 javax.management.loading \
2.9 javax.management.monitor \
2.10 - javax.management.namespace \
2.11 javax.management.relation \
2.12 javax.management.openmbean \
2.13 javax.management.timer \
3.1 --- a/make/java/java/FILES_java.gmk Mon Nov 23 10:04:47 2009 +0000
3.2 +++ b/make/java/java/FILES_java.gmk Wed Nov 25 11:08:25 2009 -0800
3.3 @@ -251,6 +251,7 @@
3.4 java/util/IdentityHashMap.java \
3.5 java/util/EnumMap.java \
3.6 java/util/Arrays.java \
3.7 + java/util/DualPivotQuicksort.java \
3.8 java/util/TimSort.java \
3.9 java/util/ComparableTimSort.java \
3.10 java/util/ConcurrentModificationException.java \
4.1 --- a/make/java/net/Makefile Mon Nov 23 10:04:47 2009 +0000
4.2 +++ b/make/java/net/Makefile Wed Nov 25 11:08:25 2009 -0800
4.3 @@ -83,7 +83,7 @@
4.4 #
4.5 # Find platform specific native code
4.6 #
4.7 -vpath %.c $(PLATFORM_SRC)/native/sun/net/dns $(PLATFORM_SRC)/native/sun/net/www/protocol/http $(PLATFORM_SRC)/native/sun/net/spi
4.8 +vpath %.c $(PLATFORM_SRC)/native/sun/net/dns $(PLATFORM_SRC)/native/sun/net/www/protocol/http/ntlm $(PLATFORM_SRC)/native/sun/net/spi
4.9
4.10 #
4.11 # Include rules
5.1 --- a/make/jprt.properties Mon Nov 23 10:04:47 2009 +0000
5.2 +++ b/make/jprt.properties Wed Nov 25 11:08:25 2009 -0800
5.3 @@ -1,5 +1,5 @@
5.4 #
5.5 -# Copyright 2006-2008 Sun Microsystems, Inc. All Rights Reserved.
5.6 +# Copyright 2006-2009 Sun Microsystems, Inc. All Rights Reserved.
5.7 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
5.8 #
5.9 # This code is free software; you can redistribute it and/or modify it
5.10 @@ -34,8 +34,8 @@
5.11 solaris_x64_5.10,\
5.12 linux_i586_2.6,\
5.13 linux_x64_2.6,\
5.14 -windows_i586,\
5.15 -windows_x64
5.16 +windows_i586_5.0,\
5.17 +windows_x64_5.2
5.18
5.19 # The different build flavors we want
5.20 jprt.build.flavors=product,fastdebug
5.21 @@ -51,21 +51,37 @@
5.22 jprt.solaris_sparcv9.build.platform.match32=solaris_sparc_5.10
5.23 jprt.solaris_x64.build.platform.match32=solaris_i586_5.10
5.24
5.25 -# Standard list of jprt test targets for this workspace
5.26 +# Standard test target for everybody
5.27 jprt.test.targets=*-*-*-jvm98
5.28 -jprt.regression.test.targets= \
5.29 - *-product-*-java/lang, \
5.30 - *-product-*-java/security, \
5.31 - *-product-*-java/text, \
5.32 - *-product-*-java/util
5.33
5.34 -#jprt.regression.test.targets= \
5.35 -# *-product-*-java/awt, \
5.36 -# *-product-*-java/beans, \
5.37 -# *-product-*-java/io, \
5.38 -# *-product-*-java/net, \
5.39 -# *-product-*-java/nio, \
5.40 -# *-product-*-java/rmi, \
5.41 +# Test targets in test/Makefile (some longer running tests only test c2)
5.42 +jprt.make.rule.test.targets= \
5.43 + *-product-*-jdk_beans1, \
5.44 + *-product-*-jdk_beans2, \
5.45 + *-product-*-jdk_beans3, \
5.46 + *-product-*-jdk_io, \
5.47 + *-product-*-jdk_lang, \
5.48 + *-product-*-jdk_management1, \
5.49 + *-product-*-jdk_management2, \
5.50 + *-product-*-jdk_math, \
5.51 + *-product-*-jdk_misc, \
5.52 + *-product-*-jdk_net, \
5.53 + *-product-*-jdk_nio1, \
5.54 + *-product-*-jdk_nio2, \
5.55 + *-product-*-jdk_nio3, \
5.56 + *-product-*-jdk_security1, \
5.57 + *-product-*-jdk_security2, \
5.58 + *-product-*-jdk_security3, \
5.59 + *-product-*-jdk_text, \
5.60 + *-product-*-jdk_tools1, \
5.61 + *-product-*-jdk_tools2, \
5.62 + *-product-*-jdk_util
5.63 +
5.64 +# Some of these are crashing Xvfb or windows manager, need dedicated DISPLAY per test batch
5.65 +jprt2.make.rule.test.targets= \
5.66 + *-product-*-jdk_awt, \
5.67 + *-product-*-jdk_rmi, \
5.68 + *-product-*-jdk_swing, \
5.69
5.70 # Directories needed to build
5.71 jprt.bundle.exclude.src.dirs=build
6.1 --- a/make/sun/awt/mapfile-vers Mon Nov 23 10:04:47 2009 +0000
6.2 +++ b/make/sun/awt/mapfile-vers Wed Nov 25 11:08:25 2009 -0800
6.3 @@ -53,7 +53,6 @@
6.4 Java_sun_awt_image_GifImageDecoder_initIDs;
6.5 Java_sun_awt_image_GifImageDecoder_parseImage;
6.6 Java_sun_awt_image_ImageRepresentation_initIDs;
6.7 - Java_sun_awt_image_ImageRepresentation_setBytePixels;
6.8 Java_sun_awt_image_ImageRepresentation_setDiffICM;
6.9 Java_sun_awt_image_ImageRepresentation_setICMpixels;
6.10 Java_sun_awt_image_ImagingLib_convolveBI;
7.1 --- a/make/sun/awt/mapfile-vers-linux Mon Nov 23 10:04:47 2009 +0000
7.2 +++ b/make/sun/awt/mapfile-vers-linux Wed Nov 25 11:08:25 2009 -0800
7.3 @@ -55,7 +55,6 @@
7.4 Java_sun_awt_image_GifImageDecoder_parseImage;
7.5 Java_sun_awt_image_Image_initIDs;
7.6 Java_sun_awt_image_ImageRepresentation_initIDs;
7.7 - Java_sun_awt_image_ImageRepresentation_setBytePixels;
7.8 Java_sun_awt_image_ImageRepresentation_setDiffICM;
7.9 Java_sun_awt_image_ImageRepresentation_setICMpixels;
7.10 Java_sun_awt_image_ImagingLib_convolveBI;
8.1 --- a/make/sun/javazic/tzdata/VERSION Mon Nov 23 10:04:47 2009 +0000
8.2 +++ b/make/sun/javazic/tzdata/VERSION Wed Nov 25 11:08:25 2009 -0800
8.3 @@ -21,4 +21,4 @@
8.4 # CA 95054 USA or visit www.sun.com if you need additional information or
8.5 # have any questions.
8.6 #
8.7 -tzdata2009l
8.8 +tzdata2009r
9.1 --- a/make/sun/javazic/tzdata/antarctica Mon Nov 23 10:04:47 2009 +0000
9.2 +++ b/make/sun/javazic/tzdata/antarctica Wed Nov 25 11:08:25 2009 -0800
9.3 @@ -102,15 +102,38 @@
9.4 # Davis, Vestfold Hills, -6835+07759, since 1957-01-13
9.5 # (except 1964-11 - 1969-02)
9.6 # Mawson, Holme Bay, -6736+06253, since 1954-02-13
9.7 +
9.8 +# From Steffen Thorsen (2009-03-11):
9.9 +# Three Australian stations in Antarctica have changed their time zone:
9.10 +# Casey moved from UTC+8 to UTC+11
9.11 +# Davis moved from UTC+7 to UTC+5
9.12 +# Mawson moved from UTC+6 to UTC+5
9.13 +# The changes occurred on 2009-10-18 at 02:00 (local times).
9.14 +#
9.15 +# Government source: (Australian Antarctic Division)
9.16 +# <a href="http://www.aad.gov.au/default.asp?casid=37079">
9.17 +# http://www.aad.gov.au/default.asp?casid=37079
9.18 +# </a>
9.19 +#
9.20 +# We have more background information here:
9.21 +# <a href="http://www.timeanddate.com/news/time/antarctica-new-times.html">
9.22 +# http://www.timeanddate.com/news/time/antarctica-new-times.html
9.23 +# </a>
9.24 +
9.25 # Zone NAME GMTOFF RULES FORMAT [UNTIL]
9.26 Zone Antarctica/Casey 0 - zzz 1969
9.27 - 8:00 - WST # Western (Aus) Standard Time
9.28 + 8:00 - WST 2009 Oct 18 2:00
9.29 + # Western (Aus) Standard Time
9.30 + 11:00 - CAST # Casey Time
9.31 Zone Antarctica/Davis 0 - zzz 1957 Jan 13
9.32 7:00 - DAVT 1964 Nov # Davis Time
9.33 0 - zzz 1969 Feb
9.34 - 7:00 - DAVT
9.35 + 7:00 - DAVT 2009 Oct 18 2:0
9.36 + 5:00 - DAVT
9.37 Zone Antarctica/Mawson 0 - zzz 1954 Feb 13
9.38 - 6:00 - MAWT # Mawson Time
9.39 + 6:00 - MAWT 2009 Oct 18 2:00
9.40 + # Mawson Time
9.41 + 5:00 - MAWT
9.42 # References:
9.43 # <a href="http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html">
9.44 # Casey Weather (1998-02-26)
10.1 --- a/make/sun/javazic/tzdata/asia Mon Nov 23 10:04:47 2009 +0000
10.2 +++ b/make/sun/javazic/tzdata/asia Wed Nov 25 11:08:25 2009 -0800
10.3 @@ -21,7 +21,6 @@
10.4 # CA 95054 USA or visit www.sun.com if you need additional information or
10.5 # have any questions.
10.6 #
10.7 -# <pre>
10.8 # This file is in the public domain, so clarified as of
10.9 # 2009-05-17 by Arthur David Olson.
10.10
10.11 @@ -194,11 +193,30 @@
10.12 #
10.13 # No DST end date has been announced yet.
10.14
10.15 -# From Arthur David Olson (2009-07-11):
10.16 -# Arbitrarily end DST at the end of 2009 so that a POSIX-sytle time zone string
10.17 -# can appear in the Dhaka binary file and for the benefit of old glibc
10.18 -# reimplementations of the time zone software that mishandle permanent DST.
10.19 -# A change will be required once the end date is known.
10.20 +# From Alexander Krivenyshev (2009-09-25):
10.21 +# Bangladesh won't go back to Standard Time from October 1, 2009,
10.22 +# instead it will continue DST measure till the cabinet makes a fresh decision.
10.23 +#
10.24 +# Following report by same newspaper-"The Daily Star Friday":
10.25 +# "DST change awaits cabinet decision-Clock won't go back by 1-hr from Oct 1"
10.26 +# <a href="http://www.thedailystar.net/newDesign/news-details.php?nid=107021">
10.27 +# http://www.thedailystar.net/newDesign/news-details.php?nid=107021
10.28 +# </a>
10.29 +# or
10.30 +# <a href="http://www.worldtimezone.com/dst_news/dst_news_bangladesh04.html">
10.31 +# http://www.worldtimezone.com/dst_news/dst_news_bangladesh04.html
10.32 +# </a>
10.33 +
10.34 +# From Steffen Thorsen (2009-10-13):
10.35 +# IANS (Indo-Asian News Service) now reports:
10.36 +# Bangladesh has decided that the clock advanced by an hour to make
10.37 +# maximum use of daylight hours as an energy saving measure would
10.38 +# "continue for an indefinite period."
10.39 +#
10.40 +# One of many places where it is published:
10.41 +# <a href="http://www.thaindian.com/newsportal/business/bangladesh-to-continue-indefinitely-with-advanced-time_100259987.html">
10.42 +# http://www.thaindian.com/newsportal/business/bangladesh-to-continue-indefinitely-with-advanced-time_100259987.html
10.43 +# </a>
10.44
10.45 # Zone NAME GMTOFF RULES FORMAT [UNTIL]
10.46 Zone Asia/Dhaka 6:01:40 - LMT 1890
10.47 @@ -208,8 +226,7 @@
10.48 6:30 - BURT 1951 Sep 30
10.49 6:00 - DACT 1971 Mar 26 # Dacca Time
10.50 6:00 - BDT 2009 Jun 19 23:00 # Bangladesh Time
10.51 - 6:00 1:00 BDST 2010
10.52 - 6:00 - BDT
10.53 + 6:00 1:00 BDST
10.54
10.55 # Bhutan
10.56 # Zone NAME GMTOFF RULES FORMAT [UNTIL]
10.57 @@ -373,14 +390,84 @@
10.58 5:00 - KAST 1980 May
10.59 8:00 PRC C%sT
10.60
10.61 +
10.62 +# From Lee Yiu Chung (2009-10-24):
10.63 +# I found there are some mistakes for the historial DST rule for Hong
10.64 +# Kong. Accoring to the DST record from Hong Kong Observatory (actually,
10.65 +# it is not [an] observatory, but the official meteorological agency of HK,
10.66 +# and also serves as the official timing agency), there are some missing
10.67 +# and incorrect rules. Although the exact switch over time is missing, I
10.68 +# think 3:30 is correct. The official DST record for Hong Kong can be
10.69 +# obtained from
10.70 +# <a href="http://www.hko.gov.hk/gts/time/Summertime.htm">
10.71 +# http://www.hko.gov.hk/gts/time/Summertime.htm
10.72 +# </a>.
10.73 +
10.74 +# From Arthur David Olson (2009-10-28):
10.75 +# Here are the dates given at
10.76 +# <a href="http://www.hko.gov.hk/gts/time/Summertime.htm">
10.77 +# http://www.hko.gov.hk/gts/time/Summertime.htm
10.78 +# </a>
10.79 +# as of 2009-10-28:
10.80 +# Year Period
10.81 +# 1941 1 Apr to 30 Sep
10.82 +# 1942 Whole year
10.83 +# 1943 Whole year
10.84 +# 1944 Whole year
10.85 +# 1945 Whole year
10.86 +# 1946 20 Apr to 1 Dec
10.87 +# 1947 13 Apr to 30 Dec
10.88 +# 1948 2 May to 31 Oct
10.89 +# 1949 3 Apr to 30 Oct
10.90 +# 1950 2 Apr to 29 Oct
10.91 +# 1951 1 Apr to 28 Oct
10.92 +# 1952 6 Apr to 25 Oct
10.93 +# 1953 5 Apr to 1 Nov
10.94 +# 1954 21 Mar to 31 Oct
10.95 +# 1955 20 Mar to 6 Nov
10.96 +# 1956 18 Mar to 4 Nov
10.97 +# 1957 24 Mar to 3 Nov
10.98 +# 1958 23 Mar to 2 Nov
10.99 +# 1959 22 Mar to 1 Nov
10.100 +# 1960 20 Mar to 6 Nov
10.101 +# 1961 19 Mar to 5 Nov
10.102 +# 1962 18 Mar to 4 Nov
10.103 +# 1963 24 Mar to 3 Nov
10.104 +# 1964 22 Mar to 1 Nov
10.105 +# 1965 18 Apr to 17 Oct
10.106 +# 1966 17 Apr to 16 Oct
10.107 +# 1967 16 Apr to 22 Oct
10.108 +# 1968 21 Apr to 20 Oct
10.109 +# 1969 20 Apr to 19 Oct
10.110 +# 1970 19 Apr to 18 Oct
10.111 +# 1971 18 Apr to 17 Oct
10.112 +# 1972 16 Apr to 22 Oct
10.113 +# 1973 22 Apr to 21 Oct
10.114 +# 1973/74 30 Dec 73 to 20 Oct 74
10.115 +# 1975 20 Apr to 19 Oct
10.116 +# 1976 18 Apr to 17 Oct
10.117 +# 1977 Nil
10.118 +# 1978 Nil
10.119 +# 1979 13 May to 21 Oct
10.120 +# 1980 to Now Nil
10.121 +# The page does not give start or end times of day.
10.122 +# The page does not give a start date for 1942.
10.123 +# The page does not givw an end date for 1945.
10.124 +# The Japanese occupation of Hong Kong began on 1941-12-25.
10.125 +# The Japanese surrender of Hong Kong was signed 1945-09-15.
10.126 +# For lack of anything better, use start of those days as the transition times.
10.127 +
10.128 # Hong Kong (Xianggang)
10.129 # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
10.130 +Rule HK 1941 only - Apr 1 3:30 1:00 S
10.131 +Rule HK 1941 only - Sep 30 3:30 0 -
10.132 Rule HK 1946 only - Apr 20 3:30 1:00 S
10.133 Rule HK 1946 only - Dec 1 3:30 0 -
10.134 Rule HK 1947 only - Apr 13 3:30 1:00 S
10.135 Rule HK 1947 only - Dec 30 3:30 0 -
10.136 Rule HK 1948 only - May 2 3:30 1:00 S
10.137 -Rule HK 1948 1952 - Oct lastSun 3:30 0 -
10.138 +Rule HK 1948 1951 - Oct lastSun 3:30 0 -
10.139 +Rule HK 1952 only - Oct 25 3:30 0 -
10.140 Rule HK 1949 1953 - Apr Sun>=1 3:30 1:00 S
10.141 Rule HK 1953 only - Nov 1 3:30 0 -
10.142 Rule HK 1954 1964 - Mar Sun>=18 3:30 1:00 S
10.143 @@ -388,13 +475,15 @@
10.144 Rule HK 1955 1964 - Nov Sun>=1 3:30 0 -
10.145 Rule HK 1965 1977 - Apr Sun>=16 3:30 1:00 S
10.146 Rule HK 1965 1977 - Oct Sun>=16 3:30 0 -
10.147 -Rule HK 1979 1980 - May Sun>=8 3:30 1:00 S
10.148 -Rule HK 1979 1980 - Oct Sun>=16 3:30 0 -
10.149 +Rule HK 1973 only - Dec 30 3:30 1:00 S
10.150 +Rule HK 1979 only - May Sun>=8 3:30 1:00 S
10.151 +Rule HK 1979 only - Oct Sun>=16 3:30 0 -
10.152 # Zone NAME GMTOFF RULES FORMAT [UNTIL]
10.153 Zone Asia/Hong_Kong 7:36:36 - LMT 1904 Oct 30
10.154 + 8:00 HK HK%sT 1941 Dec 25
10.155 + 9:00 - JST 1945 Sep 15
10.156 8:00 HK HK%sT
10.157
10.158 -
10.159 ###############################################################################
10.160
10.161 # Taiwan
10.162 @@ -1696,16 +1785,66 @@
10.163 # advance clocks in the country by one hour from April 15 to
10.164 # conserve energy"
10.165
10.166 -# From Arthur David Olson (2009-04-10):
10.167 -# Assume for now that Pakistan will end DST in 2009 as it did in 2008.
10.168 +# From Steffen Thorsen (2009-09-17):
10.169 +# "The News International," Pakistan reports that: "The Federal
10.170 +# Government has decided to restore the previous time by moving the
10.171 +# clocks backward by one hour from October 1. A formal announcement to
10.172 +# this effect will be made after the Prime Minister grants approval in
10.173 +# this regard."
10.174 +# <a href="http://www.thenews.com.pk/updates.asp?id=87168">
10.175 +# http://www.thenews.com.pk/updates.asp?id=87168
10.176 +# </a>
10.177 +
10.178 +# From Alexander Krivenyshev (2009-09-28):
10.179 +# According to Associated Press Of Pakistan, it is confirmed that
10.180 +# Pakistan clocks across the country would be turned back by an hour from October
10.181 +# 1, 2009.
10.182 +#
10.183 +# "Clocks to go back one hour from 1 Oct"
10.184 +# <a href="http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=86715&Itemid=2">
10.185 +# http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=86715&Itemid=2
10.186 +# </a>
10.187 +# or
10.188 +# <a href="http://www.worldtimezone.com/dst_news/dst_news_pakistan07.htm">
10.189 +# http://www.worldtimezone.com/dst_news/dst_news_pakistan07.htm
10.190 +# </a>
10.191 +
10.192 +# From Steffen Thorsen (2009-09-29):
10.193 +# Alexander Krivenyshev wrote:
10.194 +# > According to Associated Press Of Pakistan, it is confirmed that
10.195 +# > Pakistan clocks across the country would be turned back by an hour from October
10.196 +# > 1, 2009.
10.197 +#
10.198 +# Now they seem to have changed their mind, November 1 is the new date:
10.199 +# <a href="http://www.thenews.com.pk/top_story_detail.asp?Id=24742">
10.200 +# http://www.thenews.com.pk/top_story_detail.asp?Id=24742
10.201 +# </a>
10.202 +# "The country's clocks will be reversed by one hour on November 1.
10.203 +# Officials of Federal Ministry for Interior told this to Geo News on
10.204 +# Monday."
10.205 +#
10.206 +# And more importantly, it seems that these dates will be kept every year:
10.207 +# "It has now been decided that clocks will be wound forward by one hour
10.208 +# on April 15 and reversed by an hour on November 1 every year without
10.209 +# obtaining prior approval, the officials added."
10.210 +#
10.211 +# We have confirmed this year's end date with both with the Ministry of
10.212 +# Water and Power and the Pakistan Electric Power Company:
10.213 +# <a href="http://www.timeanddate.com/news/time/pakistan-ends-dst09.html">
10.214 +# http://www.timeanddate.com/news/time/pakistan-ends-dst09.html
10.215 +# </a>
10.216 +
10.217 +# From Christoph Goehre (2009-10-01):
10.218 +# [T]he German Consulate General in Karachi reported me today that Pakistan
10.219 +# will go back to standard time on 1st of November.
10.220
10.221 # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
10.222 Rule Pakistan 2002 only - Apr Sun>=2 0:01 1:00 S
10.223 Rule Pakistan 2002 only - Oct Sun>=2 0:01 0 -
10.224 Rule Pakistan 2008 only - Jun 1 0:00 1:00 S
10.225 Rule Pakistan 2008 only - Nov 1 0:00 0 -
10.226 -Rule Pakistan 2009 only - Apr 15 0:00 1:00 S
10.227 -Rule Pakistan 2009 only - Nov 1 0:00 0 -
10.228 +Rule Pakistan 2009 max - Apr 15 0:00 1:00 S
10.229 +Rule Pakistan 2009 max - Nov 1 0:00 0 -
10.230 # Zone NAME GMTOFF RULES FORMAT [UNTIL]
10.231 Zone Asia/Karachi 4:28:12 - LMT 1907
10.232 5:30 - IST 1942 Sep
10.233 @@ -1858,6 +1997,42 @@
10.234 # http://www.worldtimezone.com/dst_news/dst_news_westbank01.html
10.235 # </a>
10.236
10.237 +# From Steffen Thorsen (2009-08-31):
10.238 +# Palestine's Council of Ministers announced that they will revert back to
10.239 +# winter time on Friday, 2009-09-04.
10.240 +#
10.241 +# One news source:
10.242 +# <a href="http://www.safa.ps/ara/?action=showdetail&seid=4158">
10.243 +# http://www.safa.ps/ara/?action=showdetail&seid=4158
10.244 +# </a>
10.245 +# (Palestinian press agency, Arabic),
10.246 +# Google translate: "Decided that the Palestinian government in Ramallah
10.247 +# headed by Salam Fayyad, the start of work in time for the winter of
10.248 +# 2009, starting on Friday approved the fourth delay Sept. clock sixty
10.249 +# minutes per hour as of Friday morning."
10.250 +#
10.251 +# We are not sure if Gaza will do the same, last year they had a different
10.252 +# end date, we will keep this page updated:
10.253 +# <a href="http://www.timeanddate.com/news/time/westbank-gaza-dst-2009.html">
10.254 +# http://www.timeanddate.com/news/time/westbank-gaza-dst-2009.html
10.255 +# </a>
10.256 +
10.257 +# From Alexander Krivenyshev (2009-09-02):
10.258 +# Seems that Gaza Strip will go back to Winter Time same date as West Bank.
10.259 +#
10.260 +# According to Palestinian Ministry Of Interior, West Bank and Gaza Strip plan
10.261 +# to change time back to Standard time on September 4, 2009.
10.262 +#
10.263 +# "Winter time unite the West Bank and Gaza"
10.264 +# (from Palestinian National Authority):
10.265 +# <a href="http://www.moi.gov.ps/en/?page=633167343250594025&nid=11505
10.266 +# http://www.moi.gov.ps/en/?page=633167343250594025&nid=11505
10.267 +# </a>
10.268 +# or
10.269 +# <a href="http://www.worldtimezone.com/dst_news/dst_news_gazastrip02.html>
10.270 +# http://www.worldtimezone.com/dst_news/dst_news_gazastrip02.html
10.271 +# </a>
10.272 +
10.273 # The rules for Egypt are stolen from the `africa' file.
10.274 # Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
10.275 Rule EgyptAsia 1957 only - May 10 0:00 1:00 S
10.276 @@ -1876,7 +2051,7 @@
10.277 Rule Palestine 2007 only - Sep Thu>=8 2:00 0 -
10.278 Rule Palestine 2008 only - Aug lastFri 2:00 0 -
10.279 Rule Palestine 2009 max - Mar lastFri 0:00 1:00 S
10.280 -Rule Palestine 2009 max - Sep lastMon 2:00 0 -
10.281 +Rule Palestine 2009 max - Sep Fri>=1 2:00 0 -
10.282
10.283 # Zone NAME GMTOFF RULES FORMAT [UNTIL]
10.284 Zone Asia/Gaza 2:17:52 - LMT 1900 Oct
10.285 @@ -2154,9 +2329,23 @@
10.286 # http://www.timeanddate.com/news/time/syria-dst-starts-march-27-2009.html
10.287 # </a>
10.288
10.289 +# From Steffen Thorsen (2009-10-27):
10.290 +# The Syrian Arab News Network on 2009-09-29 reported that Syria will
10.291 +# revert back to winter (standard) time on midnight between Thursday
10.292 +# 2009-10-29 and Friday 2009-10-30:
10.293 +# <a href="http://www.sana.sy/ara/2/2009/09/29/247012.htm">
10.294 +# http://www.sana.sy/ara/2/2009/09/29/247012.htm (Arabic)
10.295 +# </a>
10.296 +
10.297 +# From Arthur David Olson (2009-10-28):
10.298 +# We'll see if future DST switching times turn out to be end of the last
10.299 +# Thursday of the month or the start of the last Friday of the month or
10.300 +# something else. For now, use the start of the last Friday.
10.301 +
10.302 Rule Syria 2008 only - Apr Fri>=1 0:00 1:00 S
10.303 -Rule Syria 2008 max - Nov 1 0:00 0 -
10.304 +Rule Syria 2008 only - Nov 1 0:00 0 -
10.305 Rule Syria 2009 max - Mar lastFri 0:00 1:00 S
10.306 +Rule Syria 2009 max - Oct lastFri 0:00 0 -
10.307
10.308 # Zone NAME GMTOFF RULES FORMAT [UNTIL]
10.309 Zone Asia/Damascus 2:25:12 - LMT 1920 # Dimashq
11.1 --- a/make/sun/javazic/tzdata/australasia Mon Nov 23 10:04:47 2009 +0000
11.2 +++ b/make/sun/javazic/tzdata/australasia Wed Nov 25 11:08:25 2009 -0800
11.3 @@ -465,10 +465,56 @@
11.4 # http://www.worldtimezone.com/dst_news/dst_news_samoa01.html
11.5 # </a>
11.6
11.7 +# From Steffen Thorsen (2009-08-27):
11.8 +# Samoa's parliament passed the Daylight Saving Bill 2009, and will start
11.9 +# daylight saving time on the first Sunday of October 2009 and end on the
11.10 +# last Sunday of March 2010. We hope that the full text will be published
11.11 +# soon, but we believe that the bill is only valid for 2009-2010. Samoa's
11.12 +# Daylight Saving Act 2009 will be enforced as soon as the Head of State
11.13 +# executes a proclamation publicizing this Act.
11.14 +#
11.15 +# Some background information here, which will be updated once we have
11.16 +# more details:
11.17 +# <a href="http://www.timeanddate.com/news/time/samoa-dst-plan-2009.html">
11.18 +# http://www.timeanddate.com/news/time/samoa-dst-plan-2009.html
11.19 +# </a>
11.20 +
11.21 +# From Alexander Krivenyshev (2009-10-03):
11.22 +# First, my deepest condolences to people of Samoa islands and all families and
11.23 +# loved ones around the world who lost their lives in the earthquake and tsunami.
11.24 +#
11.25 +# Considering the recent devastation on Samoa by earthquake and tsunami and that
11.26 +# many government offices/ ministers are closed- not sure if "Daylight Saving
11.27 +# Bill 2009" will be implemented in next few days- on October 4, 2009.
11.28 +#
11.29 +# Here is reply from Consulate-General of Samoa in New Zealand
11.30 +# ---------------------------
11.31 +# Consul General
11.32 +# consulgeneral@samoaconsulate.org.nz
11.33 +#
11.34 +# Talofa Alexander,
11.35 +#
11.36 +# Thank you for your sympathy for our country but at this time we have not
11.37 +# been informed about the Daylight Savings Time Change. Most Ministries in
11.38 +# Apia are closed or relocating due to weather concerns.
11.39 +#
11.40 +# When we do find out if they are still proceeding with the time change we
11.41 +# will advise you soonest.
11.42 +#
11.43 +# Kind Regards,
11.44 +# Lana
11.45 +# for: Consul General
11.46 +
11.47 +# From Steffen Thorsen (2009-10-05):
11.48 +# We have called a hotel in Samoa and asked about local time there - they
11.49 +# are still on standard time.
11.50 +
11.51 Zone Pacific/Apia 12:33:04 - LMT 1879 Jul 5
11.52 -11:26:56 - LMT 1911
11.53 -11:30 - SAMT 1950 # Samoa Time
11.54 - -11:00 - WST # Samoa Time
11.55 + -11:00 - WST 2009 Oct 4
11.56 + -11:00 1:00 WSDT 2010 Mar 28
11.57 + -11:00 - WST
11.58
11.59 # Solomon Is
11.60 # excludes Bougainville, for which see Papua New Guinea
12.1 --- a/make/sun/javazic/tzdata/europe Mon Nov 23 10:04:47 2009 +0000
12.2 +++ b/make/sun/javazic/tzdata/europe Wed Nov 25 11:08:25 2009 -0800
12.3 @@ -2094,9 +2094,43 @@
12.4 6:00 Russia NOV%sT 1992 Jan 19 2:00s
12.5 7:00 Russia NOV%sT 1993 May 23 # say Shanks & P.
12.6 6:00 Russia NOV%sT
12.7 +
12.8 +# From Alexander Krivenyshev (2009-10-13):
12.9 +# Kemerovo oblast' (Kemerovo region) in Russia will change current time zone on
12.10 +# March 28, 2010:
12.11 +# from current Russia Zone 6 - Krasnoyarsk Time Zone (KRA) UTC +0700
12.12 +# to Russia Zone 5 - Novosibirsk Time Zone (NOV) UTC +0600
12.13 +#
12.14 +# This is according to Government of Russia decree # 740, on September
12.15 +# 14, 2009 "Application in the territory of the Kemerovo region the Fifth
12.16 +# time zone." ("Russia Zone 5" or old "USSR Zone 5" is GMT +0600)
12.17 +#
12.18 +# Russian Government web site (Russian language)
12.19 +# <a href="http://www.government.ru/content/governmentactivity/rfgovernmentdecisions/archiv">
12.20 +# http://www.government.ru/content/governmentactivity/rfgovernmentdecisions/archive/2009/09/14/991633.htm
12.21 +# </a>
12.22 +# or Russian-English translation by WorldTimeZone.com with reference
12.23 +# map to local region and new Russia Time Zone map after March 28, 2010
12.24 +# <a href="http://www.worldtimezone.com/dst_news/dst_news_russia03.html">
12.25 +# http://www.worldtimezone.com/dst_news/dst_news_russia03.html
12.26 +# </a>
12.27 +#
12.28 +# Thus, when Russia will switch to DST on the night of March 28, 2010
12.29 +# Kemerovo region (Kemerovo oblast') will not change the clock.
12.30 +#
12.31 +# As a result, Kemerovo oblast' will be in the same time zone as
12.32 +# Novosibirsk, Omsk, Tomsk, Barnaul and Altai Republic.
12.33 +
12.34 +Zone Asia/Novokuznetsk 5:48:48 - NMT 1920 Jan 6
12.35 + 6:00 - KRAT 1930 Jun 21 # Krasnoyarsk Time
12.36 + 7:00 Russia KRA%sT 1991 Mar 31 2:00s
12.37 + 6:00 Russia KRA%sT 1992 Jan 19 2:00s
12.38 + 7:00 Russia KRA%sT 2010 Mar 28 2:00s
12.39 + 6:00 Russia NOV%sT # Novosibirsk/Novokuznetsk Time
12.40 +
12.41 #
12.42 # From Oscar van Vlijmen (2001-08-25): [This region consists of]
12.43 -# Kemerovskaya oblast', Krasnoyarskij kraj,
12.44 +# Krasnoyarskij kraj,
12.45 # Tajmyrskij (Dolgano-Nenetskij) avtonomnyj okrug,
12.46 # Respublika Tuva, Respublika Khakasiya, Evenkijskij avtonomnyj okrug.
12.47 Zone Asia/Krasnoyarsk 6:11:20 - LMT 1920 Jan 6
13.1 --- a/make/sun/javazic/tzdata/southamerica Mon Nov 23 10:04:47 2009 +0000
13.2 +++ b/make/sun/javazic/tzdata/southamerica Wed Nov 25 11:08:25 2009 -0800
13.3 @@ -237,9 +237,23 @@
13.4 # http://www.jujuy.gov.ar/index2/partes_prensa/18_10_08/235-181008.doc
13.5 # </a>
13.6
13.7 +# From fullinet (2009-10-18):
13.8 +# As announced in
13.9 +# <a hef="http://www.argentina.gob.ar/argentina/portal/paginas.dhtml?pagina=356">
13.10 +# http://www.argentina.gob.ar/argentina/portal/paginas.dhtml?pagina=356
13.11 +# </a>
13.12 +# (an official .gob.ar) under title: "Sin Cambio de Hora" (english: "No hour change")
13.13 +#
13.14 +# "Por el momento, el Gobierno Nacional resolvio no modificar la hora
13.15 +# oficial, decision que estaba en estudio para su implementacion el
13.16 +# domingo 18 de octubre. Desde el Ministerio de Planificacion se anuncio
13.17 +# que la Argentina hoy, en estas condiciones meteorologicas, no necesita
13.18 +# la modificacion del huso horario, ya que 2009 nos encuentra con
13.19 +# crecimiento en la produccion y distribucion energetica."
13.20 +
13.21 Rule Arg 2007 only - Dec 30 0:00 1:00 S
13.22 -Rule Arg 2008 max - Mar Sun>=15 0:00 0 -
13.23 -Rule Arg 2008 max - Oct Sun>=15 0:00 1:00 S
13.24 +Rule Arg 2008 2009 - Mar Sun>=15 0:00 0 -
13.25 +Rule Arg 2008 only - Oct Sun>=15 0:00 1:00 S
13.26
13.27 # From Mariano Absatz (2004-05-21):
13.28 # Today it was officially published that the Province of Mendoza is changing
13.29 @@ -411,15 +425,40 @@
13.30 # during 2009, this timezone change will run from 00:00 the third Sunday
13.31 # in March until 24:00 of the second Saturday in October.
13.32
13.33 -# From Arthur David Olson (2009-03-16):
13.34 -# The unofficial claim at
13.35 -# <a href="http://www.timeanddate.com/news/time/san-luis-new-time-zone.html">
13.36 -# http://www.timeanddate.com/news/time/san-luis-new-time-zone.html
13.37 +# From Mariano Absatz (2009-10-16):
13.38 +# ...the Province of San Luis is a case in itself.
13.39 +#
13.40 +# The Law at
13.41 +# <a href="http://www.diputadossanluis.gov.ar/diputadosasp/paginas/verNorma.asp?NormaID=276>"
13.42 +# http://www.diputadossanluis.gov.ar/diputadosasp/paginas/verNorma.asp?NormaID=276
13.43 # </a>
13.44 -# is that "The province will most likely follow the next daylight saving schedule,
13.45 -# which is planned for the second Sunday in October."
13.46 +# is ambiguous because establishes a calendar from the 2nd Sunday in
13.47 +# October at 0:00 thru the 2nd Saturday in March at 24:00 and the
13.48 +# complement of that starting on the 2nd Sunday of March at 0:00 and
13.49 +# ending on the 2nd Saturday of March at 24:00.
13.50 +#
13.51 +# This clearly breaks every time the 1st of March or October is a Sunday.
13.52 +#
13.53 +# IMHO, the "spirit of the Law" is to make the changes at 0:00 on the 2nd
13.54 +# Sunday of October and March.
13.55 +#
13.56 +# The problem is that the changes in the rest of the Provinces that did
13.57 +# change in 2007/2008, were made according to the Federal Law and Decrees
13.58 +# that did so on the 3rd Sunday of October and March.
13.59 +#
13.60 +# In fact, San Luis actually switched from UTC-4 to UTC-3 last Sunday
13.61 +# (October 11th) at 0:00.
13.62 +#
13.63 +# So I guess a new set of rules, besides "Arg", must be made and the last
13.64 +# America/Argentina/San_Luis entries should change to use these...
13.65 +#
13.66 +# I'm enclosing a patch that does what I say... regretfully, the San Luis
13.67 +# timezone must be called "WART/WARST" even when most of the time (like,
13.68 +# right now) WARST == ART... that is, since last Sunday, all the country
13.69 +# is using UTC-3, but in my patch, San Luis calls it "WARST" and the rest
13.70 +# of the country calls it "ART".
13.71 +# ...
13.72
13.73 -#
13.74 # Zone NAME GMTOFF RULES FORMAT [UNTIL]
13.75 #
13.76 # Buenos Aires (BA), Capital Federal (CF),
13.77 @@ -552,6 +591,10 @@
13.78 -3:00 - ART
13.79 #
13.80 # San Luis (SL)
13.81 +
13.82 +Rule SanLuis 2008 max - Mar Sun>=8 0:00 0 -
13.83 +Rule SanLuis 2007 max - Oct Sun>=8 0:00 1:00 S
13.84 +
13.85 Zone America/Argentina/San_Luis -4:25:24 - LMT 1894 Oct 31
13.86 -4:16:48 - CMT 1920 May
13.87 -4:00 - ART 1930 Dec
13.88 @@ -566,8 +609,7 @@
13.89 -3:00 - ART 2004 May 31
13.90 -4:00 - WART 2004 Jul 25
13.91 -3:00 Arg AR%sT 2008 Jan 21
13.92 - -3:00 - ART 2009 Mar 15
13.93 - -4:00 Arg WAR%sT
13.94 + -4:00 SanLuis WAR%sT
13.95 #
13.96 # Santa Cruz (SC)
13.97 Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 Oct 31
14.1 --- a/make/sun/javazic/tzdata/zone.tab Mon Nov 23 10:04:47 2009 +0000
14.2 +++ b/make/sun/javazic/tzdata/zone.tab Wed Nov 25 11:08:25 2009 -0800
14.3 @@ -352,6 +352,7 @@
14.4 RU +5651+06036 Asia/Yekaterinburg Moscow+02 - Urals
14.5 RU +5500+07324 Asia/Omsk Moscow+03 - west Siberia
14.6 RU +5502+08255 Asia/Novosibirsk Moscow+03 - Novosibirsk
14.7 +RU +5345+08707 Asia/Novokuznetsk Moscow+03 - Novokuznetsk
14.8 RU +5601+09250 Asia/Krasnoyarsk Moscow+04 - Yenisei River
14.9 RU +5216+10420 Asia/Irkutsk Moscow+05 - Lake Baikal
14.10 RU +6200+12940 Asia/Yakutsk Moscow+06 - Lena River
15.1 --- a/make/sun/net/FILES_java.gmk Mon Nov 23 10:04:47 2009 +0000
15.2 +++ b/make/sun/net/FILES_java.gmk Wed Nov 25 11:08:25 2009 -0800
15.3 @@ -45,8 +45,14 @@
15.4 sun/net/dns/ResolverConfiguration.java \
15.5 sun/net/dns/ResolverConfigurationImpl.java \
15.6 sun/net/ftp/FtpClient.java \
15.7 + sun/net/ftp/FtpClientProvider.java \
15.8 + sun/net/ftp/FtpDirEntry.java \
15.9 + sun/net/ftp/FtpReplyCode.java \
15.10 + sun/net/ftp/FtpDirParser.java \
15.11 sun/net/ftp/FtpLoginException.java \
15.12 sun/net/ftp/FtpProtocolException.java \
15.13 + sun/net/ftp/impl/FtpClient.java \
15.14 + sun/net/ftp/impl/DefaultFtpClientProvider.java \
15.15 sun/net/spi/DefaultProxySelector.java \
15.16 sun/net/spi/nameservice/NameServiceDescriptor.java \
15.17 sun/net/spi/nameservice/NameService.java \
15.18 @@ -79,7 +85,6 @@
15.19 sun/net/www/http/Hurryable.java \
15.20 sun/net/www/protocol/http/Handler.java \
15.21 sun/net/www/protocol/http/HttpURLConnection.java \
15.22 - sun/net/www/protocol/http/HttpLogFormatter.java \
15.23 sun/net/www/protocol/http/HttpAuthenticator.java \
15.24 sun/net/www/protocol/http/AuthenticationHeader.java \
15.25 sun/net/www/protocol/http/AuthenticationInfo.java \
15.26 @@ -89,11 +94,13 @@
15.27 sun/net/www/protocol/http/AuthScheme.java \
15.28 sun/net/www/protocol/http/BasicAuthentication.java \
15.29 sun/net/www/protocol/http/DigestAuthentication.java \
15.30 - sun/net/www/protocol/http/NTLMAuthentication.java \
15.31 sun/net/www/protocol/http/NTLMAuthenticationProxy.java \
15.32 sun/net/www/protocol/http/NegotiateAuthentication.java \
15.33 - sun/net/www/protocol/http/NegotiatorImpl.java \
15.34 - sun/net/www/protocol/http/NegotiateCallbackHandler.java \
15.35 + sun/net/www/protocol/http/Negotiator.java \
15.36 + sun/net/www/protocol/http/ntlm/NTLMAuthentication.java \
15.37 + sun/net/www/protocol/http/spnego/NegotiatorImpl.java \
15.38 + sun/net/www/protocol/http/spnego/NegotiateCallbackHandler.java \
15.39 + sun/net/www/protocol/http/logging/HttpLogFormatter.java \
15.40 sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java \
15.41 sun/net/www/protocol/https/HttpsClient.java \
15.42 sun/net/www/protocol/https/DefaultHostnameVerifier.java \
15.43 @@ -128,7 +135,7 @@
15.44 sun/net/idn/StringPrep.java
15.45
15.46 ifeq ($(PLATFORM), windows)
15.47 - FILES_java += sun/net/www/protocol/http/NTLMAuthSequence.java
15.48 + FILES_java += sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java
15.49 endif
15.50
15.51 ifeq ($(PLATFORM), solaris)
16.1 --- a/make/sun/security/other/Makefile Mon Nov 23 10:04:47 2009 +0000
16.2 +++ b/make/sun/security/other/Makefile Wed Nov 25 11:08:25 2009 -0800
16.3 @@ -39,6 +39,7 @@
16.4 sun/security/provider \
16.5 sun/security/rsa \
16.6 sun/security/ssl \
16.7 + sun/security/ssl/krb5 \
16.8 sun/security/timestamp \
16.9 sun/security/validator \
16.10 sun/security/x509 \
17.1 --- a/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java Mon Nov 23 10:04:47 2009 +0000
17.2 +++ b/src/share/classes/com/sun/imageio/plugins/bmp/BMPImageReader.java Wed Nov 25 11:08:25 2009 -0800
17.3 @@ -62,6 +62,8 @@
17.4
17.5 import java.io.*;
17.6 import java.nio.*;
17.7 +import java.security.AccessController;
17.8 +import java.security.PrivilegedAction;
17.9 import java.util.ArrayList;
17.10 import java.util.Iterator;
17.11 import java.util.StringTokenizer;
17.12 @@ -502,12 +504,18 @@
17.13 iis.reset();
17.14
17.15 try {
17.16 - if (metadata.colorSpace == PROFILE_LINKED)
17.17 + if (metadata.colorSpace == PROFILE_LINKED &&
17.18 + isLinkedProfileAllowed() &&
17.19 + !isUncOrDevicePath(profile))
17.20 + {
17.21 + String path = new String(profile, "windows-1252");
17.22 +
17.23 colorSpace =
17.24 - new ICC_ColorSpace(ICC_Profile.getInstance(new String(profile)));
17.25 - else
17.26 + new ICC_ColorSpace(ICC_Profile.getInstance(path));
17.27 + } else {
17.28 colorSpace =
17.29 new ICC_ColorSpace(ICC_Profile.getInstance(profile));
17.30 + }
17.31 } catch (Exception e) {
17.32 colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
17.33 }
17.34 @@ -1745,4 +1753,69 @@
17.35 public void sequenceStarted(ImageReader src, int minIndex) {}
17.36 public void readAborted(ImageReader src) {}
17.37 }
17.38 +
17.39 + private static Boolean isLinkedProfileDisabled = null;
17.40 +
17.41 + private static boolean isLinkedProfileAllowed() {
17.42 + if (isLinkedProfileDisabled == null) {
17.43 + PrivilegedAction<Boolean> a = new PrivilegedAction<Boolean>() {
17.44 + public Boolean run() {
17.45 + return Boolean.getBoolean("sun.imageio.plugins.bmp.disableLinkedProfiles");
17.46 + }
17.47 + };
17.48 + isLinkedProfileDisabled = AccessController.doPrivileged(a);
17.49 + }
17.50 + return !isLinkedProfileDisabled;
17.51 + }
17.52 +
17.53 + private static Boolean isWindowsPlatform = null;
17.54 +
17.55 + /**
17.56 + * Verifies whether the byte array contans a unc path.
17.57 + * Non-UNC path examples:
17.58 + * c:\path\to\file - simple notation
17.59 + * \\?\c:\path\to\file - long notation
17.60 + *
17.61 + * UNC path examples:
17.62 + * \\server\share - a UNC path in simple notation
17.63 + * \\?\UNC\server\share - a UNC path in long notation
17.64 + * \\.\some\device - a path to device.
17.65 + */
17.66 + private static boolean isUncOrDevicePath(byte[] p) {
17.67 + if (isWindowsPlatform == null) {
17.68 + PrivilegedAction<Boolean> a = new PrivilegedAction<Boolean>() {
17.69 + public Boolean run() {
17.70 + String osname = System.getProperty("os.name");
17.71 + return (osname != null &&
17.72 + osname.toLowerCase().startsWith("win"));
17.73 + }
17.74 + };
17.75 + isWindowsPlatform = AccessController.doPrivileged(a);
17.76 + }
17.77 +
17.78 + if (!isWindowsPlatform) {
17.79 + /* no need for the check on platforms except windows */
17.80 + return false;
17.81 + }
17.82 +
17.83 + /* normalize prefix of the path */
17.84 + if (p[0] == '/') p[0] = '\\';
17.85 + if (p[1] == '/') p[1] = '\\';
17.86 + if (p[3] == '/') p[3] = '\\';
17.87 +
17.88 +
17.89 + if ((p[0] == '\\') && (p[1] == '\\')) {
17.90 + if ((p[2] == '?') && (p[3] == '\\')) {
17.91 + // long path: whether unc or local
17.92 + return ((p[4] == 'U' || p[4] == 'u') &&
17.93 + (p[5] == 'N' || p[5] == 'n') &&
17.94 + (p[6] == 'C' || p[6] == 'c'));
17.95 + } else {
17.96 + // device path or short unc notation
17.97 + return true;
17.98 + }
17.99 + } else {
17.100 + return false;
17.101 + }
17.102 + }
17.103 }
18.1 --- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifButtonUI.java Mon Nov 23 10:04:47 2009 +0000
18.2 +++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifButtonUI.java Wed Nov 25 11:08:25 2009 -0800
18.3 @@ -25,6 +25,8 @@
18.4
18.5 package com.sun.java.swing.plaf.motif;
18.6
18.7 +import sun.awt.AppContext;
18.8 +
18.9 import javax.swing.*;
18.10 import javax.swing.border.*;
18.11 import javax.swing.plaf.basic.*;
18.12 @@ -46,16 +48,23 @@
18.13 */
18.14 public class MotifButtonUI extends BasicButtonUI {
18.15
18.16 - private final static MotifButtonUI motifButtonUI = new MotifButtonUI();
18.17 -
18.18 protected Color selectColor;
18.19
18.20 private boolean defaults_initialized = false;
18.21
18.22 + private static final Object MOTIF_BUTTON_UI_KEY = new Object();
18.23 +
18.24 // ********************************
18.25 // Create PLAF
18.26 // ********************************
18.27 - public static ComponentUI createUI(JComponent c){
18.28 + public static ComponentUI createUI(JComponent c) {
18.29 + AppContext appContext = AppContext.getAppContext();
18.30 + MotifButtonUI motifButtonUI =
18.31 + (MotifButtonUI) appContext.get(MOTIF_BUTTON_UI_KEY);
18.32 + if (motifButtonUI == null) {
18.33 + motifButtonUI = new MotifButtonUI();
18.34 + appContext.put(MOTIF_BUTTON_UI_KEY, motifButtonUI);
18.35 + }
18.36 return motifButtonUI;
18.37 }
18.38
19.1 --- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifCheckBoxUI.java Mon Nov 23 10:04:47 2009 +0000
19.2 +++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifCheckBoxUI.java Wed Nov 25 11:08:25 2009 -0800
19.3 @@ -25,6 +25,8 @@
19.4
19.5 package com.sun.java.swing.plaf.motif;
19.6
19.7 +import sun.awt.AppContext;
19.8 +
19.9 import javax.swing.*;
19.10
19.11 import javax.swing.plaf.*;
19.12 @@ -45,7 +47,7 @@
19.13 */
19.14 public class MotifCheckBoxUI extends MotifRadioButtonUI {
19.15
19.16 - private static final MotifCheckBoxUI motifCheckBoxUI = new MotifCheckBoxUI();
19.17 + private static final Object MOTIF_CHECK_BOX_UI_KEY = new Object();
19.18
19.19 private final static String propertyPrefix = "CheckBox" + ".";
19.20
19.21 @@ -55,7 +57,14 @@
19.22 // ********************************
19.23 // Create PLAF
19.24 // ********************************
19.25 - public static ComponentUI createUI(JComponent c){
19.26 + public static ComponentUI createUI(JComponent c) {
19.27 + AppContext appContext = AppContext.getAppContext();
19.28 + MotifCheckBoxUI motifCheckBoxUI =
19.29 + (MotifCheckBoxUI) appContext.get(MOTIF_CHECK_BOX_UI_KEY);
19.30 + if (motifCheckBoxUI == null) {
19.31 + motifCheckBoxUI = new MotifCheckBoxUI();
19.32 + appContext.put(MOTIF_CHECK_BOX_UI_KEY, motifCheckBoxUI);
19.33 + }
19.34 return motifCheckBoxUI;
19.35 }
19.36
20.1 --- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifLabelUI.java Mon Nov 23 10:04:47 2009 +0000
20.2 +++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifLabelUI.java Wed Nov 25 11:08:25 2009 -0800
20.3 @@ -25,6 +25,8 @@
20.4
20.5 package com.sun.java.swing.plaf.motif;
20.6
20.7 +import sun.awt.AppContext;
20.8 +
20.9 import javax.swing.*;
20.10 import javax.swing.plaf.basic.BasicLabelUI;
20.11 import javax.swing.plaf.ComponentUI;
20.12 @@ -44,9 +46,16 @@
20.13 */
20.14 public class MotifLabelUI extends BasicLabelUI
20.15 {
20.16 - static MotifLabelUI sharedInstance = new MotifLabelUI();
20.17 + private static final Object MOTIF_LABEL_UI_KEY = new Object();
20.18
20.19 public static ComponentUI createUI(JComponent c) {
20.20 - return sharedInstance;
20.21 + AppContext appContext = AppContext.getAppContext();
20.22 + MotifLabelUI motifLabelUI =
20.23 + (MotifLabelUI) appContext.get(MOTIF_LABEL_UI_KEY);
20.24 + if (motifLabelUI == null) {
20.25 + motifLabelUI = new MotifLabelUI();
20.26 + appContext.put(MOTIF_LABEL_UI_KEY, motifLabelUI);
20.27 + }
20.28 + return motifLabelUI;
20.29 }
20.30 }
21.1 --- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifRadioButtonUI.java Mon Nov 23 10:04:47 2009 +0000
21.2 +++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifRadioButtonUI.java Wed Nov 25 11:08:25 2009 -0800
21.3 @@ -25,6 +25,8 @@
21.4
21.5 package com.sun.java.swing.plaf.motif;
21.6
21.7 +import sun.awt.AppContext;
21.8 +
21.9 import javax.swing.*;
21.10 import javax.swing.border.*;
21.11 import javax.swing.plaf.basic.BasicRadioButtonUI;
21.12 @@ -47,7 +49,7 @@
21.13 */
21.14 public class MotifRadioButtonUI extends BasicRadioButtonUI {
21.15
21.16 - private static final MotifRadioButtonUI motifRadioButtonUI = new MotifRadioButtonUI();
21.17 + private static final Object MOTIF_RADIO_BUTTON_UI_KEY = new Object();
21.18
21.19 protected Color focusColor;
21.20
21.21 @@ -57,6 +59,13 @@
21.22 // Create PLAF
21.23 // ********************************
21.24 public static ComponentUI createUI(JComponent c) {
21.25 + AppContext appContext = AppContext.getAppContext();
21.26 + MotifRadioButtonUI motifRadioButtonUI =
21.27 + (MotifRadioButtonUI) appContext.get(MOTIF_RADIO_BUTTON_UI_KEY);
21.28 + if (motifRadioButtonUI == null) {
21.29 + motifRadioButtonUI = new MotifRadioButtonUI();
21.30 + appContext.put(MOTIF_RADIO_BUTTON_UI_KEY, motifRadioButtonUI);
21.31 + }
21.32 return motifRadioButtonUI;
21.33 }
21.34
22.1 --- a/src/share/classes/com/sun/java/swing/plaf/motif/MotifToggleButtonUI.java Mon Nov 23 10:04:47 2009 +0000
22.2 +++ b/src/share/classes/com/sun/java/swing/plaf/motif/MotifToggleButtonUI.java Wed Nov 25 11:08:25 2009 -0800
22.3 @@ -25,6 +25,8 @@
22.4
22.5 package com.sun.java.swing.plaf.motif;
22.6
22.7 +import sun.awt.AppContext;
22.8 +
22.9 import java.awt.*;
22.10 import java.awt.event.*;
22.11
22.12 @@ -48,7 +50,7 @@
22.13 */
22.14 public class MotifToggleButtonUI extends BasicToggleButtonUI
22.15 {
22.16 - private final static MotifToggleButtonUI motifToggleButtonUI = new MotifToggleButtonUI();
22.17 + private static final Object MOTIF_TOGGLE_BUTTON_UI_KEY = new Object();
22.18
22.19 protected Color selectColor;
22.20
22.21 @@ -58,6 +60,13 @@
22.22 // Create PLAF
22.23 // ********************************
22.24 public static ComponentUI createUI(JComponent b) {
22.25 + AppContext appContext = AppContext.getAppContext();
22.26 + MotifToggleButtonUI motifToggleButtonUI =
22.27 + (MotifToggleButtonUI) appContext.get(MOTIF_TOGGLE_BUTTON_UI_KEY);
22.28 + if (motifToggleButtonUI == null) {
22.29 + motifToggleButtonUI = new MotifToggleButtonUI();
22.30 + appContext.put(MOTIF_TOGGLE_BUTTON_UI_KEY, motifToggleButtonUI);
22.31 + }
22.32 return motifToggleButtonUI;
22.33 }
22.34
23.1 --- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsButtonUI.java Mon Nov 23 10:04:47 2009 +0000
23.2 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsButtonUI.java Wed Nov 25 11:08:25 2009 -0800
23.3 @@ -35,6 +35,7 @@
23.4 import static com.sun.java.swing.plaf.windows.TMSchema.*;
23.5 import static com.sun.java.swing.plaf.windows.TMSchema.Part.*;
23.6 import static com.sun.java.swing.plaf.windows.XPStyle.Skin;
23.7 +import sun.awt.AppContext;
23.8
23.9
23.10 /**
23.11 @@ -52,8 +53,6 @@
23.12 */
23.13 public class WindowsButtonUI extends BasicButtonUI
23.14 {
23.15 - private final static WindowsButtonUI windowsButtonUI = new WindowsButtonUI();
23.16 -
23.17 protected int dashedRectGapX;
23.18 protected int dashedRectGapY;
23.19 protected int dashedRectGapWidth;
23.20 @@ -63,11 +62,19 @@
23.21
23.22 private boolean defaults_initialized = false;
23.23
23.24 + private static final Object WINDOWS_BUTTON_UI_KEY = new Object();
23.25
23.26 // ********************************
23.27 // Create PLAF
23.28 // ********************************
23.29 - public static ComponentUI createUI(JComponent c){
23.30 + public static ComponentUI createUI(JComponent c) {
23.31 + AppContext appContext = AppContext.getAppContext();
23.32 + WindowsButtonUI windowsButtonUI =
23.33 + (WindowsButtonUI) appContext.get(WINDOWS_BUTTON_UI_KEY);
23.34 + if (windowsButtonUI == null) {
23.35 + windowsButtonUI = new WindowsButtonUI();
23.36 + appContext.put(WINDOWS_BUTTON_UI_KEY, windowsButtonUI);
23.37 + }
23.38 return windowsButtonUI;
23.39 }
23.40
23.41 @@ -151,7 +158,7 @@
23.42 * allocating them in each paint call substantially reduced the time
23.43 * it took paint to run. Obviously, this method can't be re-entered.
23.44 */
23.45 - private static Rectangle viewRect = new Rectangle();
23.46 + private Rectangle viewRect = new Rectangle();
23.47
23.48 public void paint(Graphics g, JComponent c) {
23.49 if (XPStyle.getXP() != null) {
24.1 --- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxUI.java Mon Nov 23 10:04:47 2009 +0000
24.2 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsCheckBoxUI.java Wed Nov 25 11:08:25 2009 -0800
24.3 @@ -25,6 +25,8 @@
24.4
24.5 package com.sun.java.swing.plaf.windows;
24.6
24.7 +import sun.awt.AppContext;
24.8 +
24.9 import javax.swing.plaf.basic.*;
24.10 import javax.swing.*;
24.11 import javax.swing.plaf.*;
24.12 @@ -49,7 +51,7 @@
24.13 // of BasicCheckBoxUI because we want to pick up all the
24.14 // painting changes made in MetalRadioButtonUI.
24.15
24.16 - private static final WindowsCheckBoxUI windowsCheckBoxUI = new WindowsCheckBoxUI();
24.17 + private static final Object WINDOWS_CHECK_BOX_UI_KEY = new Object();
24.18
24.19 private final static String propertyPrefix = "CheckBox" + ".";
24.20
24.21 @@ -59,6 +61,13 @@
24.22 // Create PLAF
24.23 // ********************************
24.24 public static ComponentUI createUI(JComponent c) {
24.25 + AppContext appContext = AppContext.getAppContext();
24.26 + WindowsCheckBoxUI windowsCheckBoxUI =
24.27 + (WindowsCheckBoxUI) appContext.get(WINDOWS_CHECK_BOX_UI_KEY);
24.28 + if (windowsCheckBoxUI == null) {
24.29 + windowsCheckBoxUI = new WindowsCheckBoxUI();
24.30 + appContext.put(WINDOWS_CHECK_BOX_UI_KEY, windowsCheckBoxUI);
24.31 + }
24.32 return windowsCheckBoxUI;
24.33 }
24.34
25.1 --- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLabelUI.java Mon Nov 23 10:04:47 2009 +0000
25.2 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsLabelUI.java Wed Nov 25 11:08:25 2009 -0800
25.3 @@ -26,6 +26,8 @@
25.4 package com.sun.java.swing.plaf.windows;
25.5
25.6 import sun.swing.SwingUtilities2;
25.7 +import sun.awt.AppContext;
25.8 +
25.9 import java.awt.Color;
25.10 import java.awt.Graphics;
25.11
25.12 @@ -51,12 +53,19 @@
25.13 */
25.14 public class WindowsLabelUI extends BasicLabelUI {
25.15
25.16 - private final static WindowsLabelUI windowsLabelUI = new WindowsLabelUI();
25.17 + private static final Object WINDOWS_LABEL_UI_KEY = new Object();
25.18
25.19 // ********************************
25.20 // Create PLAF
25.21 // ********************************
25.22 - public static ComponentUI createUI(JComponent c){
25.23 + public static ComponentUI createUI(JComponent c) {
25.24 + AppContext appContext = AppContext.getAppContext();
25.25 + WindowsLabelUI windowsLabelUI =
25.26 + (WindowsLabelUI) appContext.get(WINDOWS_LABEL_UI_KEY);
25.27 + if (windowsLabelUI == null) {
25.28 + windowsLabelUI = new WindowsLabelUI();
25.29 + appContext.put(WINDOWS_LABEL_UI_KEY, windowsLabelUI);
25.30 + }
25.31 return windowsLabelUI;
25.32 }
25.33
26.1 --- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonUI.java Mon Nov 23 10:04:47 2009 +0000
26.2 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsRadioButtonUI.java Wed Nov 25 11:08:25 2009 -0800
26.3 @@ -25,6 +25,8 @@
26.4
26.5 package com.sun.java.swing.plaf.windows;
26.6
26.7 +import sun.awt.AppContext;
26.8 +
26.9 import javax.swing.plaf.basic.*;
26.10 import javax.swing.*;
26.11 import javax.swing.plaf.*;
26.12 @@ -44,7 +46,7 @@
26.13 */
26.14 public class WindowsRadioButtonUI extends BasicRadioButtonUI
26.15 {
26.16 - private static final WindowsRadioButtonUI windowsRadioButtonUI = new WindowsRadioButtonUI();
26.17 + private static final Object WINDOWS_RADIO_BUTTON_UI_KEY = new Object();
26.18
26.19 protected int dashedRectGapX;
26.20 protected int dashedRectGapY;
26.21 @@ -59,6 +61,13 @@
26.22 // Create PLAF
26.23 // ********************************
26.24 public static ComponentUI createUI(JComponent c) {
26.25 + AppContext appContext = AppContext.getAppContext();
26.26 + WindowsRadioButtonUI windowsRadioButtonUI =
26.27 + (WindowsRadioButtonUI) appContext.get(WINDOWS_RADIO_BUTTON_UI_KEY);
26.28 + if (windowsRadioButtonUI == null) {
26.29 + windowsRadioButtonUI = new WindowsRadioButtonUI();
26.30 + appContext.put(WINDOWS_RADIO_BUTTON_UI_KEY, windowsRadioButtonUI);
26.31 + }
26.32 return windowsRadioButtonUI;
26.33 }
26.34
27.1 --- a/src/share/classes/com/sun/java/swing/plaf/windows/WindowsToggleButtonUI.java Mon Nov 23 10:04:47 2009 +0000
27.2 +++ b/src/share/classes/com/sun/java/swing/plaf/windows/WindowsToggleButtonUI.java Wed Nov 25 11:08:25 2009 -0800
27.3 @@ -25,6 +25,8 @@
27.4
27.5 package com.sun.java.swing.plaf.windows;
27.6
27.7 +import sun.awt.AppContext;
27.8 +
27.9 import javax.swing.plaf.basic.*;
27.10 import javax.swing.border.*;
27.11 import javax.swing.plaf.*;
27.12 @@ -49,18 +51,25 @@
27.13 */
27.14 public class WindowsToggleButtonUI extends BasicToggleButtonUI
27.15 {
27.16 - protected static int dashedRectGapX;
27.17 - protected static int dashedRectGapY;
27.18 - protected static int dashedRectGapWidth;
27.19 - protected static int dashedRectGapHeight;
27.20 + protected int dashedRectGapX;
27.21 + protected int dashedRectGapY;
27.22 + protected int dashedRectGapWidth;
27.23 + protected int dashedRectGapHeight;
27.24
27.25 protected Color focusColor;
27.26
27.27 - private final static WindowsToggleButtonUI windowsToggleButtonUI = new WindowsToggleButtonUI();
27.28 + private static final Object WINDOWS_TOGGLE_BUTTON_UI_KEY = new Object();
27.29
27.30 private boolean defaults_initialized = false;
27.31
27.32 public static ComponentUI createUI(JComponent b) {
27.33 + AppContext appContext = AppContext.getAppContext();
27.34 + WindowsToggleButtonUI windowsToggleButtonUI =
27.35 + (WindowsToggleButtonUI) appContext.get(WINDOWS_TOGGLE_BUTTON_UI_KEY);
27.36 + if (windowsToggleButtonUI == null) {
27.37 + windowsToggleButtonUI = new WindowsToggleButtonUI();
27.38 + appContext.put(WINDOWS_TOGGLE_BUTTON_UI_KEY, windowsToggleButtonUI);
27.39 + }
27.40 return windowsToggleButtonUI;
27.41 }
27.42
28.1 --- a/src/share/classes/com/sun/jmx/defaults/JmxProperties.java Mon Nov 23 10:04:47 2009 +0000
28.2 +++ b/src/share/classes/com/sun/jmx/defaults/JmxProperties.java Wed Nov 25 11:08:25 2009 -0800
28.3 @@ -1,5 +1,5 @@
28.4 /*
28.5 - * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
28.6 + * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
28.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
28.8 *
28.9 * This code is free software; you can redistribute it and/or modify it
28.10 @@ -177,18 +177,6 @@
28.11 "javax.management.relation";
28.12
28.13 /**
28.14 - * Logger name for Namespaces.
28.15 - */
28.16 - public static final String NAMESPACE_LOGGER_NAME =
28.17 - "javax.management.namespace";
28.18 -
28.19 - /**
28.20 - * Logger name for Namespaces.
28.21 - */
28.22 - public static final Logger NAMESPACE_LOGGER =
28.23 - Logger.getLogger(NAMESPACE_LOGGER_NAME);
28.24 -
28.25 - /**
28.26 * Logger for Relation Service.
28.27 */
28.28 public static final Logger RELATION_LOGGER =
29.1 --- a/src/share/classes/com/sun/jmx/defaults/ServiceName.java Mon Nov 23 10:04:47 2009 +0000
29.2 +++ b/src/share/classes/com/sun/jmx/defaults/ServiceName.java Wed Nov 25 11:08:25 2009 -0800
29.3 @@ -69,9 +69,9 @@
29.4 /**
29.5 * The version of the JMX specification implemented by this product.
29.6 * <BR>
29.7 - * The value is <CODE>2.0</CODE>.
29.8 + * The value is <CODE>1.4</CODE>.
29.9 */
29.10 - public static final String JMX_SPEC_VERSION = "2.0";
29.11 + public static final String JMX_SPEC_VERSION = "1.4";
29.12
29.13 /**
29.14 * The vendor of the JMX specification implemented by this product.
30.1 --- a/src/share/classes/com/sun/jmx/event/DaemonThreadFactory.java Mon Nov 23 10:04:47 2009 +0000
30.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
30.3 @@ -1,77 +0,0 @@
30.4 -/*
30.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
30.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
30.7 - *
30.8 - * This code is free software; you can redistribute it and/or modify it
30.9 - * under the terms of the GNU General Public License version 2 only, as
30.10 - * published by the Free Software Foundation. Sun designates this
30.11 - * particular file as subject to the "Classpath" exception as provided
30.12 - * by Sun in the LICENSE file that accompanied this code.
30.13 - *
30.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
30.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
30.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
30.17 - * version 2 for more details (a copy is included in the LICENSE file that
30.18 - * accompanied this code).
30.19 - *
30.20 - * You should have received a copy of the GNU General Public License version
30.21 - * 2 along with this work; if not, write to the Free Software Foundation,
30.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
30.23 - *
30.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
30.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
30.26 - * have any questions.
30.27 - */
30.28 -
30.29 -package com.sun.jmx.event;
30.30 -
30.31 -import com.sun.jmx.remote.util.ClassLogger;
30.32 -import java.util.concurrent.ThreadFactory;
30.33 -import java.util.concurrent.atomic.AtomicInteger;
30.34 -
30.35 -public class DaemonThreadFactory implements ThreadFactory {
30.36 - public DaemonThreadFactory(String nameTemplate) {
30.37 - this(nameTemplate, null);
30.38 - }
30.39 -
30.40 - // nameTemplate should be a format with %d in it, which will be replaced
30.41 - // by a sequence number of threads created by this factory.
30.42 - public DaemonThreadFactory(String nameTemplate, ThreadGroup threadGroup) {
30.43 - if (logger.debugOn()) {
30.44 - logger.debug("DaemonThreadFactory",
30.45 - "Construct a new daemon factory: "+nameTemplate);
30.46 - }
30.47 -
30.48 - if (threadGroup == null) {
30.49 - SecurityManager s = System.getSecurityManager();
30.50 - threadGroup = (s != null) ? s.getThreadGroup() :
30.51 - Thread.currentThread().getThreadGroup();
30.52 - }
30.53 -
30.54 - this.nameTemplate = nameTemplate;
30.55 - this.threadGroup = threadGroup;
30.56 - }
30.57 -
30.58 - public Thread newThread(Runnable r) {
30.59 - final String name =
30.60 - String.format(nameTemplate, threadNumber.getAndIncrement());
30.61 - Thread t = new Thread(threadGroup, r, name, 0);
30.62 - t.setDaemon(true);
30.63 - if (t.getPriority() != Thread.NORM_PRIORITY)
30.64 - t.setPriority(Thread.NORM_PRIORITY);
30.65 -
30.66 - if (logger.debugOn()) {
30.67 - logger.debug("newThread",
30.68 - "Create a new daemon thread with the name "+t.getName());
30.69 - }
30.70 -
30.71 - return t;
30.72 - }
30.73 -
30.74 - private final String nameTemplate;
30.75 - private final ThreadGroup threadGroup;
30.76 - private final AtomicInteger threadNumber = new AtomicInteger(1);
30.77 -
30.78 - private static final ClassLogger logger =
30.79 - new ClassLogger("com.sun.jmx.event", "DaemonThreadFactory");
30.80 -}
31.1 --- a/src/share/classes/com/sun/jmx/event/EventBuffer.java Mon Nov 23 10:04:47 2009 +0000
31.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
31.3 @@ -1,252 +0,0 @@
31.4 -/*
31.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
31.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
31.7 - *
31.8 - * This code is free software; you can redistribute it and/or modify it
31.9 - * under the terms of the GNU General Public License version 2 only, as
31.10 - * published by the Free Software Foundation. Sun designates this
31.11 - * particular file as subject to the "Classpath" exception as provided
31.12 - * by Sun in the LICENSE file that accompanied this code.
31.13 - *
31.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
31.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
31.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
31.17 - * version 2 for more details (a copy is included in the LICENSE file that
31.18 - * accompanied this code).
31.19 - *
31.20 - * You should have received a copy of the GNU General Public License version
31.21 - * 2 along with this work; if not, write to the Free Software Foundation,
31.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
31.23 - *
31.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
31.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
31.26 - * have any questions.
31.27 - */
31.28 -
31.29 -package com.sun.jmx.event;
31.30 -
31.31 -import com.sun.jmx.remote.util.ClassLogger;
31.32 -import java.util.ArrayList;
31.33 -import java.util.Collections;
31.34 -import java.util.List;
31.35 -import javax.management.remote.NotificationResult;
31.36 -import javax.management.remote.TargetedNotification;
31.37 -
31.38 -public class EventBuffer {
31.39 -
31.40 - public EventBuffer() {
31.41 - this(Integer.MAX_VALUE, null);
31.42 - }
31.43 -
31.44 - public EventBuffer(int capacity) {
31.45 - this(capacity, new ArrayList<TargetedNotification>());
31.46 - }
31.47 -
31.48 - public EventBuffer(int capacity, final List<TargetedNotification> list) {
31.49 - if (logger.traceOn()) {
31.50 - logger.trace("EventBuffer", "New buffer with the capacity: "
31.51 - +capacity);
31.52 - }
31.53 - if (capacity < 1) {
31.54 - throw new IllegalArgumentException(
31.55 - "The capacity must be bigger than 0");
31.56 - }
31.57 -
31.58 - if (list == null) {
31.59 - throw new NullPointerException("Null list.");
31.60 - }
31.61 -
31.62 - this.capacity = capacity;
31.63 - this.list = list;
31.64 - }
31.65 -
31.66 - public void add(TargetedNotification tn) {
31.67 - if (logger.traceOn()) {
31.68 - logger.trace("add", "Add one notif.");
31.69 - }
31.70 -
31.71 - synchronized(lock) {
31.72 - if (list.size() == capacity) { // have to throw one
31.73 - passed++;
31.74 - list.remove(0);
31.75 -
31.76 - if (logger.traceOn()) {
31.77 - logger.trace("add", "Over, remove the oldest one.");
31.78 - }
31.79 - }
31.80 -
31.81 - list.add(tn);
31.82 - lock.notify();
31.83 - }
31.84 - }
31.85 -
31.86 - public void add(TargetedNotification[] tns) {
31.87 - if (tns == null || tns.length == 0) {
31.88 - return;
31.89 - }
31.90 -
31.91 - if (logger.traceOn()) {
31.92 - logger.trace("add", "Add notifs: "+tns.length);
31.93 - }
31.94 -
31.95 - synchronized(lock) {
31.96 - final int d = list.size() - capacity + tns.length;
31.97 - if (d > 0) { // have to throw
31.98 - passed += d;
31.99 - if (logger.traceOn()) {
31.100 - logger.trace("add",
31.101 - "Over, remove the oldest: "+d);
31.102 - }
31.103 - if (tns.length <= capacity){
31.104 - list.subList(0, d).clear();
31.105 - } else {
31.106 - list.clear();
31.107 - TargetedNotification[] tmp =
31.108 - new TargetedNotification[capacity];
31.109 - System.arraycopy(tns, tns.length-capacity, tmp, 0, capacity);
31.110 - tns = tmp;
31.111 - }
31.112 - }
31.113 -
31.114 - Collections.addAll(list,tns);
31.115 - lock.notify();
31.116 - }
31.117 - }
31.118 -
31.119 - public NotificationResult fetchNotifications(long startSequenceNumber,
31.120 - long timeout,
31.121 - int maxNotifications) {
31.122 - if (logger.traceOn()) {
31.123 - logger.trace("fetchNotifications",
31.124 - "Being called: "
31.125 - +startSequenceNumber+" "
31.126 - +timeout+" "+maxNotifications);
31.127 - }
31.128 - if (startSequenceNumber < 0 ||
31.129 - timeout < 0 ||
31.130 - maxNotifications < 0) {
31.131 - throw new IllegalArgumentException("Negative value.");
31.132 - }
31.133 -
31.134 - TargetedNotification[] tns = new TargetedNotification[0];
31.135 - long earliest = startSequenceNumber < passed ?
31.136 - passed : startSequenceNumber;
31.137 - long next = earliest;
31.138 -
31.139 - final long startTime = System.currentTimeMillis();
31.140 - long toWait = timeout;
31.141 - synchronized(lock) {
31.142 - int toSkip = (int)(startSequenceNumber - passed);
31.143 -
31.144 - // skip those before startSequenceNumber.
31.145 - while (!closed && toSkip > 0) {
31.146 - toWait = timeout - (System.currentTimeMillis() - startTime);
31.147 - if (list.size() == 0) {
31.148 - if (toWait <= 0) {
31.149 - // the notification of startSequenceNumber
31.150 - // does not arrive yet.
31.151 - return new NotificationResult(startSequenceNumber,
31.152 - startSequenceNumber,
31.153 - new TargetedNotification[0]);
31.154 - }
31.155 -
31.156 - waiting(toWait);
31.157 - continue;
31.158 - }
31.159 -
31.160 - if (toSkip <= list.size()) {
31.161 - list.subList(0, toSkip).clear();
31.162 - passed += toSkip;
31.163 -
31.164 - break;
31.165 - } else {
31.166 - passed += list.size();
31.167 - toSkip -= list.size();
31.168 -
31.169 - list.clear();
31.170 - }
31.171 - }
31.172 -
31.173 - earliest = passed;
31.174 -
31.175 - if (list.size() == 0) {
31.176 - toWait = timeout - (System.currentTimeMillis() - startTime);
31.177 -
31.178 - waiting(toWait);
31.179 - }
31.180 -
31.181 - if (list.size() == 0) {
31.182 - tns = new TargetedNotification[0];
31.183 - } else if (list.size() <= maxNotifications) {
31.184 - tns = list.toArray(new TargetedNotification[0]);
31.185 - } else {
31.186 - tns = new TargetedNotification[maxNotifications];
31.187 - for (int i=0; i<maxNotifications; i++) {
31.188 - tns[i] = list.get(i);
31.189 - }
31.190 - }
31.191 -
31.192 - next = earliest + tns.length;
31.193 - }
31.194 -
31.195 - if (logger.traceOn()) {
31.196 - logger.trace("fetchNotifications",
31.197 - "Return: "+earliest+" "+next+" "+tns.length);
31.198 - }
31.199 -
31.200 - return new NotificationResult(earliest, next, tns);
31.201 - }
31.202 -
31.203 - public int size() {
31.204 - return list.size();
31.205 - }
31.206 -
31.207 - public void addLost(long nb) {
31.208 - synchronized(lock) {
31.209 - passed += nb;
31.210 - }
31.211 - }
31.212 -
31.213 - public void close() {
31.214 - if (logger.traceOn()) {
31.215 - logger.trace("clear", "done");
31.216 - }
31.217 -
31.218 - synchronized(lock) {
31.219 - list.clear();
31.220 - closed = true;
31.221 - lock.notifyAll();
31.222 - }
31.223 - }
31.224 -
31.225 -
31.226 - // -------------------------------------------
31.227 - // private classes
31.228 - // -------------------------------------------
31.229 - private void waiting(long timeout) {
31.230 - final long startTime = System.currentTimeMillis();
31.231 - long toWait = timeout;
31.232 - synchronized(lock) {
31.233 - while (!closed && list.size() == 0 && toWait > 0) {
31.234 - try {
31.235 - lock.wait(toWait);
31.236 -
31.237 - toWait = timeout - (System.currentTimeMillis() - startTime);
31.238 - } catch (InterruptedException ire) {
31.239 - logger.trace("waiting", ire);
31.240 - break;
31.241 - }
31.242 - }
31.243 - }
31.244 - }
31.245 -
31.246 - private final int capacity;
31.247 - private final List<TargetedNotification> list;
31.248 - private boolean closed;
31.249 -
31.250 - private long passed = 0;
31.251 - private final int[] lock = new int[0];
31.252 -
31.253 - private static final ClassLogger logger =
31.254 - new ClassLogger("javax.management.event", "EventBuffer");
31.255 -}
32.1 --- a/src/share/classes/com/sun/jmx/event/EventClientFactory.java Mon Nov 23 10:04:47 2009 +0000
32.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
32.3 @@ -1,46 +0,0 @@
32.4 -/*
32.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
32.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
32.7 - *
32.8 - * This code is free software; you can redistribute it and/or modify it
32.9 - * under the terms of the GNU General Public License version 2 only, as
32.10 - * published by the Free Software Foundation. Sun designates this
32.11 - * particular file as subject to the "Classpath" exception as provided
32.12 - * by Sun in the LICENSE file that accompanied this code.
32.13 - *
32.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
32.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
32.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
32.17 - * version 2 for more details (a copy is included in the LICENSE file that
32.18 - * accompanied this code).
32.19 - *
32.20 - * You should have received a copy of the GNU General Public License version
32.21 - * 2 along with this work; if not, write to the Free Software Foundation,
32.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
32.23 - *
32.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
32.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
32.26 - * have any questions.
32.27 - */
32.28 -
32.29 -package com.sun.jmx.event;
32.30 -
32.31 -import javax.management.event.*;
32.32 -
32.33 -/**
32.34 - * Implemented by objects which are using an {@link EventClient} to
32.35 - * subscribe for Notifications.
32.36 - *
32.37 - */
32.38 -public interface EventClientFactory {
32.39 - /**
32.40 - * Returns the {@code EventClient} that the object implementing this
32.41 - * interface uses to subscribe for Notifications. This method returns
32.42 - * {@code null} if no {@code EventClient} can be used - e.g. because
32.43 - * the underlying server does not have any {@link EventDelegate}.
32.44 - *
32.45 - * @return an {@code EventClient} or {@code null}.
32.46 - **/
32.47 - public EventClient getEventClient();
32.48 -
32.49 -}
33.1 --- a/src/share/classes/com/sun/jmx/event/EventConnection.java Mon Nov 23 10:04:47 2009 +0000
33.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
33.3 @@ -1,81 +0,0 @@
33.4 -/*
33.5 - * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
33.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
33.7 - *
33.8 - * This code is free software; you can redistribute it and/or modify it
33.9 - * under the terms of the GNU General Public License version 2 only, as
33.10 - * published by the Free Software Foundation. Sun designates this
33.11 - * particular file as subject to the "Classpath" exception as provided
33.12 - * by Sun in the LICENSE file that accompanied this code.
33.13 - *
33.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
33.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
33.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
33.17 - * version 2 for more details (a copy is included in the LICENSE file that
33.18 - * accompanied this code).
33.19 - *
33.20 - * You should have received a copy of the GNU General Public License version
33.21 - * 2 along with this work; if not, write to the Free Software Foundation,
33.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
33.23 - *
33.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
33.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
33.26 - * have any questions.
33.27 - */
33.28 -
33.29 -package com.sun.jmx.event;
33.30 -
33.31 -import java.io.IOException;
33.32 -import java.lang.reflect.InvocationHandler;
33.33 -import java.lang.reflect.InvocationTargetException;
33.34 -import java.lang.reflect.Method;
33.35 -import java.lang.reflect.Proxy;
33.36 -import javax.management.MBeanServerConnection;
33.37 -import javax.management.event.EventClient;
33.38 -import javax.management.event.EventClientDelegate;
33.39 -import javax.management.event.EventConsumer;
33.40 -import javax.management.event.NotificationManager;
33.41 -
33.42 -/**
33.43 - * Override the methods related to the notification to use the
33.44 - * Event service.
33.45 - */
33.46 -public interface EventConnection extends MBeanServerConnection, EventConsumer {
33.47 - public EventClient getEventClient();
33.48 -
33.49 - public static class Factory {
33.50 - public static EventConnection make(
33.51 - final MBeanServerConnection mbsc,
33.52 - final EventClient eventClient)
33.53 - throws IOException {
33.54 - if (!mbsc.isRegistered(EventClientDelegate.OBJECT_NAME)) {
33.55 - throw new IOException(
33.56 - "The server does not support the event service.");
33.57 - }
33.58 - InvocationHandler ih = new InvocationHandler() {
33.59 - public Object invoke(Object proxy, Method method, Object[] args)
33.60 - throws Throwable {
33.61 - Class<?> intf = method.getDeclaringClass();
33.62 - try {
33.63 - if (intf.isInstance(eventClient))
33.64 - return method.invoke(eventClient, args);
33.65 - else
33.66 - return method.invoke(mbsc, args);
33.67 - } catch (InvocationTargetException e) {
33.68 - throw e.getCause();
33.69 - }
33.70 - }
33.71 - };
33.72 - // It is important to declare NotificationManager.class first
33.73 - // in the array below, so that the relevant addNL and removeNL
33.74 - // methods will show up with method.getDeclaringClass() as
33.75 - // being from that interface and not MBeanServerConnection.
33.76 - return (EventConnection) Proxy.newProxyInstance(
33.77 - NotificationManager.class.getClassLoader(),
33.78 - new Class<?>[] {
33.79 - NotificationManager.class, EventConnection.class,
33.80 - },
33.81 - ih);
33.82 - }
33.83 - }
33.84 -}
34.1 --- a/src/share/classes/com/sun/jmx/event/EventParams.java Mon Nov 23 10:04:47 2009 +0000
34.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
34.3 @@ -1,65 +0,0 @@
34.4 -/*
34.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
34.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
34.7 - *
34.8 - * This code is free software; you can redistribute it and/or modify it
34.9 - * under the terms of the GNU General Public License version 2 only, as
34.10 - * published by the Free Software Foundation. Sun designates this
34.11 - * particular file as subject to the "Classpath" exception as provided
34.12 - * by Sun in the LICENSE file that accompanied this code.
34.13 - *
34.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
34.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
34.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
34.17 - * version 2 for more details (a copy is included in the LICENSE file that
34.18 - * accompanied this code).
34.19 - *
34.20 - * You should have received a copy of the GNU General Public License version
34.21 - * 2 along with this work; if not, write to the Free Software Foundation,
34.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
34.23 - *
34.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
34.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
34.26 - * have any questions.
34.27 - */
34.28 -
34.29 -package com.sun.jmx.event;
34.30 -
34.31 -import com.sun.jmx.mbeanserver.GetPropertyAction;
34.32 -import com.sun.jmx.remote.util.ClassLogger;
34.33 -import java.security.AccessController;
34.34 -import javax.management.event.EventClient;
34.35 -
34.36 -/**
34.37 - *
34.38 - * @author sjiang
34.39 - */
34.40 -public class EventParams {
34.41 - public static final String DEFAULT_LEASE_TIMEOUT =
34.42 - "com.sun.event.lease.time";
34.43 -
34.44 -
34.45 - @SuppressWarnings("cast") // cast for jdk 1.5
34.46 - public static long getLeaseTimeout() {
34.47 - long timeout = EventClient.DEFAULT_REQUESTED_LEASE_TIME;
34.48 - try {
34.49 - final GetPropertyAction act =
34.50 - new GetPropertyAction(DEFAULT_LEASE_TIMEOUT);
34.51 - final String s = (String)AccessController.doPrivileged(act);
34.52 - if (s != null) {
34.53 - timeout = Long.parseLong(s);
34.54 - }
34.55 - } catch (RuntimeException e) {
34.56 - logger.fine("getLeaseTimeout", "exception getting property", e);
34.57 - }
34.58 -
34.59 - return timeout;
34.60 - }
34.61 -
34.62 - /** Creates a new instance of EventParams */
34.63 - private EventParams() {
34.64 - }
34.65 -
34.66 - private static final ClassLogger logger =
34.67 - new ClassLogger("javax.management.event", "EventParams");
34.68 -}
35.1 --- a/src/share/classes/com/sun/jmx/event/LeaseManager.java Mon Nov 23 10:04:47 2009 +0000
35.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
35.3 @@ -1,155 +0,0 @@
35.4 -/*
35.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
35.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
35.7 - *
35.8 - * This code is free software; you can redistribute it and/or modify it
35.9 - * under the terms of the GNU General Public License version 2 only, as
35.10 - * published by the Free Software Foundation. Sun designates this
35.11 - * particular file as subject to the "Classpath" exception as provided
35.12 - * by Sun in the LICENSE file that accompanied this code.
35.13 - *
35.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
35.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
35.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
35.17 - * version 2 for more details (a copy is included in the LICENSE file that
35.18 - * accompanied this code).
35.19 - *
35.20 - * You should have received a copy of the GNU General Public License version
35.21 - * 2 along with this work; if not, write to the Free Software Foundation,
35.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
35.23 - *
35.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
35.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
35.26 - * have any questions.
35.27 - */
35.28 -
35.29 -package com.sun.jmx.event;
35.30 -
35.31 -import com.sun.jmx.remote.util.ClassLogger;
35.32 -import java.util.concurrent.Executors;
35.33 -import java.util.concurrent.ScheduledExecutorService;
35.34 -import java.util.concurrent.ScheduledFuture;
35.35 -import java.util.concurrent.ThreadFactory;
35.36 -import java.util.concurrent.TimeUnit;
35.37 -
35.38 -/**
35.39 - * <p>Manage a renewable lease. The lease can be renewed indefinitely
35.40 - * but if the lease runs to its current expiry date without being renewed
35.41 - * then the expiry callback is invoked. If the lease has already expired
35.42 - * when renewal is attempted then the lease method returns zero.</p>
35.43 - * @author sjiang
35.44 - * @author emcmanus
35.45 - */
35.46 -// The synchronization logic of this class is tricky to deal correctly with the
35.47 -// case where the lease expires at the same time as the |lease| or |stop| method
35.48 -// is called. If the lease is active then the field |scheduled| represents
35.49 -// the expiry task; otherwise |scheduled| is null. Renewing or stopping the
35.50 -// lease involves canceling this task and setting |scheduled| either to a new
35.51 -// task (to renew) or to null (to stop).
35.52 -//
35.53 -// Suppose the expiry task runs at the same time as the |lease| method is called.
35.54 -// If the task enters its synchronized block before the method starts, then
35.55 -// it will set |scheduled| to null and the method will return 0. If the method
35.56 -// starts before the task enters its synchronized block, then the method will
35.57 -// cancel the task which will see that when it later enters the block.
35.58 -// Similar reasoning applies to the |stop| method. It is not expected that
35.59 -// different threads will call |lease| or |stop| simultaneously, although the
35.60 -// logic should be correct then too.
35.61 -public class LeaseManager {
35.62 - public LeaseManager(Runnable callback) {
35.63 - this(callback, EventParams.getLeaseTimeout());
35.64 - }
35.65 -
35.66 - public LeaseManager(Runnable callback, long timeout) {
35.67 - if (logger.traceOn()) {
35.68 - logger.trace("LeaseManager", "new manager with lease: "+timeout);
35.69 - }
35.70 - if (callback == null) {
35.71 - throw new NullPointerException("Null callback.");
35.72 - }
35.73 - if (timeout <= 0)
35.74 - throw new IllegalArgumentException("Timeout must be positive: " + timeout);
35.75 -
35.76 - this.callback = callback;
35.77 - schedule(timeout);
35.78 - }
35.79 -
35.80 - /**
35.81 - * <p>Renew the lease for the given time. The new time can be shorter
35.82 - * than the previous one, in which case the lease will expire earlier
35.83 - * than it would have.</p>
35.84 - *
35.85 - * <p>Calling this method after the lease has expired will return zero
35.86 - * immediately and have no other effect.</p>
35.87 - *
35.88 - * @param timeout the new lifetime. If zero, the lease
35.89 - * will expire immediately.
35.90 - */
35.91 - public synchronized long lease(long timeout) {
35.92 - if (logger.traceOn()) {
35.93 - logger.trace("lease", "new lease to: "+timeout);
35.94 - }
35.95 -
35.96 - if (timeout < 0)
35.97 - throw new IllegalArgumentException("Negative lease: " + timeout);
35.98 -
35.99 - if (scheduled == null)
35.100 - return 0L;
35.101 -
35.102 - scheduled.cancel(false);
35.103 -
35.104 - if (logger.traceOn())
35.105 - logger.trace("lease", "start lease: "+timeout);
35.106 - schedule(timeout);
35.107 -
35.108 - return timeout;
35.109 - }
35.110 -
35.111 - private class Expire implements Runnable {
35.112 - ScheduledFuture<?> task;
35.113 -
35.114 - public void run() {
35.115 - synchronized (LeaseManager.this) {
35.116 - if (task.isCancelled())
35.117 - return;
35.118 - scheduled = null;
35.119 - }
35.120 - callback.run();
35.121 - executor.shutdown();
35.122 - }
35.123 - }
35.124 -
35.125 - private synchronized void schedule(long timeout) {
35.126 - Expire expire = new Expire();
35.127 - scheduled = executor.schedule(expire, timeout, TimeUnit.MILLISECONDS);
35.128 - expire.task = scheduled;
35.129 - }
35.130 -
35.131 - /**
35.132 - * <p>Cancel the lease without calling the expiry callback.</p>
35.133 - */
35.134 - public synchronized void stop() {
35.135 - logger.trace("stop", "canceling lease");
35.136 - scheduled.cancel(false);
35.137 - scheduled = null;
35.138 - try {
35.139 - executor.shutdown();
35.140 - } catch (SecurityException e) {
35.141 - // OK: caller doesn't have RuntimePermission("modifyThread")
35.142 - // which is unlikely in reality but triggers a test failure otherwise
35.143 - logger.trace("stop", "exception from executor.shutdown", e);
35.144 - }
35.145 - }
35.146 -
35.147 - private final Runnable callback;
35.148 - private ScheduledFuture<?> scheduled; // If null, the lease has expired.
35.149 -
35.150 - private static final ThreadFactory threadFactory =
35.151 - new DaemonThreadFactory("JMX LeaseManager %d");
35.152 - private final ScheduledExecutorService executor
35.153 - = Executors.newScheduledThreadPool(1, threadFactory);
35.154 -
35.155 - private static final ClassLogger logger =
35.156 - new ClassLogger("javax.management.event", "LeaseManager");
35.157 -
35.158 -}
36.1 --- a/src/share/classes/com/sun/jmx/event/LeaseRenewer.java Mon Nov 23 10:04:47 2009 +0000
36.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
36.3 @@ -1,143 +0,0 @@
36.4 -/*
36.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
36.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
36.7 - *
36.8 - * This code is free software; you can redistribute it and/or modify it
36.9 - * under the terms of the GNU General Public License version 2 only, as
36.10 - * published by the Free Software Foundation. Sun designates this
36.11 - * particular file as subject to the "Classpath" exception as provided
36.12 - * by Sun in the LICENSE file that accompanied this code.
36.13 - *
36.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
36.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
36.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
36.17 - * version 2 for more details (a copy is included in the LICENSE file that
36.18 - * accompanied this code).
36.19 - *
36.20 - * You should have received a copy of the GNU General Public License version
36.21 - * 2 along with this work; if not, write to the Free Software Foundation,
36.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
36.23 - *
36.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
36.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
36.26 - * have any questions.
36.27 - */
36.28 -
36.29 -package com.sun.jmx.event;
36.30 -
36.31 -import com.sun.jmx.remote.util.ClassLogger;
36.32 -import java.util.concurrent.Callable;
36.33 -import java.util.concurrent.ScheduledExecutorService;
36.34 -import java.util.concurrent.ScheduledFuture;
36.35 -import java.util.concurrent.TimeUnit;
36.36 -
36.37 -/**
36.38 - *
36.39 - * @author sjiang
36.40 - */
36.41 -public class LeaseRenewer {
36.42 - public LeaseRenewer(ScheduledExecutorService scheduler, Callable<Long> doRenew) {
36.43 - if (logger.traceOn()) {
36.44 - logger.trace("LeaseRenewer", "New LeaseRenewer.");
36.45 - }
36.46 -
36.47 - if (doRenew == null) {
36.48 - throw new NullPointerException("Null job to call server.");
36.49 - }
36.50 -
36.51 - this.doRenew = doRenew;
36.52 - nextRenewTime = System.currentTimeMillis();
36.53 -
36.54 - this.scheduler = scheduler;
36.55 - future = this.scheduler.schedule(myRenew, 0, TimeUnit.MILLISECONDS);
36.56 - }
36.57 -
36.58 - public void close() {
36.59 - if (logger.traceOn()) {
36.60 - logger.trace("close", "Close the lease.");
36.61 - }
36.62 -
36.63 - synchronized(lock) {
36.64 - if (closed) {
36.65 - return;
36.66 - } else {
36.67 - closed = true;
36.68 - }
36.69 - }
36.70 -
36.71 - try {
36.72 - future.cancel(false); // not interrupt if running
36.73 - } catch (Exception e) {
36.74 - // OK
36.75 - if (logger.debugOn()) {
36.76 - logger.debug("close", "Failed to cancel the leasing job.", e);
36.77 - }
36.78 - }
36.79 - }
36.80 -
36.81 - public boolean closed() {
36.82 - synchronized(lock) {
36.83 - return closed;
36.84 - }
36.85 - }
36.86 -
36.87 - // ------------------------------
36.88 - // private
36.89 - // ------------------------------
36.90 - private final Runnable myRenew = new Runnable() {
36.91 - public void run() {
36.92 - synchronized(lock) {
36.93 - if (closed()) {
36.94 - return;
36.95 - }
36.96 - }
36.97 -
36.98 - long next = nextRenewTime - System.currentTimeMillis();
36.99 - if (next < MIN_MILLIS) {
36.100 - try {
36.101 - if (logger.traceOn()) {
36.102 - logger.trace("myRenew-run", "");
36.103 - }
36.104 - next = doRenew.call().longValue();
36.105 -
36.106 - } catch (Exception e) {
36.107 - logger.fine("myRenew-run", "Failed to renew lease", e);
36.108 - close();
36.109 - }
36.110 -
36.111 - if (next > 0 && next < Long.MAX_VALUE) {
36.112 - next = next/2;
36.113 - next = (next < MIN_MILLIS) ? MIN_MILLIS : next;
36.114 - } else {
36.115 - close();
36.116 - }
36.117 - }
36.118 -
36.119 - nextRenewTime = System.currentTimeMillis() + next;
36.120 -
36.121 - if (logger.traceOn()) {
36.122 - logger.trace("myRenew-run", "Next leasing: "+next);
36.123 - }
36.124 -
36.125 - synchronized(lock) {
36.126 - if (!closed) {
36.127 - future = scheduler.schedule(this, next, TimeUnit.MILLISECONDS);
36.128 - }
36.129 - }
36.130 - }
36.131 - };
36.132 -
36.133 - private final Callable<Long> doRenew;
36.134 - private ScheduledFuture<?> future;
36.135 - private boolean closed = false;
36.136 - private long nextRenewTime;
36.137 -
36.138 - private final int[] lock = new int[0];
36.139 -
36.140 - private final ScheduledExecutorService scheduler;
36.141 -
36.142 - private static final long MIN_MILLIS = 50;
36.143 -
36.144 - private static final ClassLogger logger =
36.145 - new ClassLogger("javax.management.event", "LeaseRenewer");
36.146 -}
37.1 --- a/src/share/classes/com/sun/jmx/event/ReceiverBuffer.java Mon Nov 23 10:04:47 2009 +0000
37.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
37.3 @@ -1,97 +0,0 @@
37.4 -/*
37.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
37.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
37.7 - *
37.8 - * This code is free software; you can redistribute it and/or modify it
37.9 - * under the terms of the GNU General Public License version 2 only, as
37.10 - * published by the Free Software Foundation. Sun designates this
37.11 - * particular file as subject to the "Classpath" exception as provided
37.12 - * by Sun in the LICENSE file that accompanied this code.
37.13 - *
37.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
37.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
37.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
37.17 - * version 2 for more details (a copy is included in the LICENSE file that
37.18 - * accompanied this code).
37.19 - *
37.20 - * You should have received a copy of the GNU General Public License version
37.21 - * 2 along with this work; if not, write to the Free Software Foundation,
37.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
37.23 - *
37.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
37.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
37.26 - * have any questions.
37.27 - */
37.28 -
37.29 -package com.sun.jmx.event;
37.30 -
37.31 -import com.sun.jmx.remote.util.ClassLogger;
37.32 -import java.util.ArrayList;
37.33 -import java.util.Collections;
37.34 -import java.util.List;
37.35 -import javax.management.remote.NotificationResult;
37.36 -import javax.management.remote.TargetedNotification;
37.37 -
37.38 -
37.39 -public class ReceiverBuffer {
37.40 - public void addNotifs(NotificationResult nr) {
37.41 - if (nr == null) {
37.42 - return;
37.43 - }
37.44 -
37.45 - TargetedNotification[] tns = nr.getTargetedNotifications();
37.46 -
37.47 - if (logger.traceOn()) {
37.48 - logger.trace("addNotifs", "" + tns.length);
37.49 - }
37.50 -
37.51 - long impliedStart = nr.getEarliestSequenceNumber();
37.52 - final long missed = impliedStart - start;
37.53 - start = nr.getNextSequenceNumber();
37.54 -
37.55 - if (missed > 0) {
37.56 - if (logger.traceOn()) {
37.57 - logger.trace("addNotifs",
37.58 - "lost: "+missed);
37.59 - }
37.60 -
37.61 - lost += missed;
37.62 - }
37.63 -
37.64 - Collections.addAll(notifList, nr.getTargetedNotifications());
37.65 - }
37.66 -
37.67 - public TargetedNotification[] removeNotifs() {
37.68 - if (logger.traceOn()) {
37.69 - logger.trace("removeNotifs", String.valueOf(notifList.size()));
37.70 - }
37.71 -
37.72 - if (notifList.size() == 0) {
37.73 - return null;
37.74 - }
37.75 -
37.76 - TargetedNotification[] ret = notifList.toArray(
37.77 - new TargetedNotification[]{});
37.78 - notifList.clear();
37.79 -
37.80 - return ret;
37.81 - }
37.82 -
37.83 - public int size() {
37.84 - return notifList.size();
37.85 - }
37.86 -
37.87 - public int removeLost() {
37.88 - int ret = lost;
37.89 - lost = 0;
37.90 - return ret;
37.91 - }
37.92 -
37.93 - private List<TargetedNotification> notifList
37.94 - = new ArrayList<TargetedNotification>();
37.95 - private long start = 0;
37.96 - private int lost = 0;
37.97 -
37.98 - private static final ClassLogger logger =
37.99 - new ClassLogger("javax.management.event", "ReceiverBuffer");
37.100 -}
38.1 --- a/src/share/classes/com/sun/jmx/event/RepeatedSingletonJob.java Mon Nov 23 10:04:47 2009 +0000
38.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
38.3 @@ -1,119 +0,0 @@
38.4 -/*
38.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
38.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
38.7 - *
38.8 - * This code is free software; you can redistribute it and/or modify it
38.9 - * under the terms of the GNU General Public License version 2 only, as
38.10 - * published by the Free Software Foundation. Sun designates this
38.11 - * particular file as subject to the "Classpath" exception as provided
38.12 - * by Sun in the LICENSE file that accompanied this code.
38.13 - *
38.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
38.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
38.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
38.17 - * version 2 for more details (a copy is included in the LICENSE file that
38.18 - * accompanied this code).
38.19 - *
38.20 - * You should have received a copy of the GNU General Public License version
38.21 - * 2 along with this work; if not, write to the Free Software Foundation,
38.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
38.23 - *
38.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
38.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
38.26 - * have any questions.
38.27 - */
38.28 -
38.29 -package com.sun.jmx.event;
38.30 -
38.31 -import com.sun.jmx.remote.util.ClassLogger;
38.32 -import java.util.concurrent.Executor;
38.33 -import java.util.concurrent.RejectedExecutionException;
38.34 -
38.35 -/**
38.36 - * <p>A task that is repeatedly run by an Executor. The task will be
38.37 - * repeated as long as the {@link #isSuspended()} method returns true. Once
38.38 - * that method returns false, the task is no longer executed until someone
38.39 - * calls {@link #resume()}.</p>
38.40 - * @author sjiang
38.41 - */
38.42 -public abstract class RepeatedSingletonJob implements Runnable {
38.43 - public RepeatedSingletonJob(Executor executor) {
38.44 - if (executor == null) {
38.45 - throw new NullPointerException("Null executor!");
38.46 - }
38.47 -
38.48 - this.executor = executor;
38.49 - }
38.50 -
38.51 - public boolean isWorking() {
38.52 - return working;
38.53 - }
38.54 -
38.55 - public void resume() {
38.56 -
38.57 - synchronized(this) {
38.58 - if (!working) {
38.59 - if (logger.traceOn()) {
38.60 - logger.trace("resume", "");
38.61 - }
38.62 - working = true;
38.63 - execute();
38.64 - }
38.65 - }
38.66 - }
38.67 -
38.68 - public abstract void task();
38.69 - public abstract boolean isSuspended();
38.70 -
38.71 - public void run() {
38.72 - if (logger.traceOn()) {
38.73 - logger.trace("run", "execute the task");
38.74 - }
38.75 - try {
38.76 - task();
38.77 - } catch (Exception e) {
38.78 - // A correct task() implementation should not throw exceptions.
38.79 - // It may cause isSuspended() to start returning true, though.
38.80 - logger.trace("run", "failed to execute the task", e);
38.81 - }
38.82 -
38.83 - synchronized(this) {
38.84 - if (!isSuspended()) {
38.85 - execute();
38.86 - } else {
38.87 - if (logger.traceOn()) {
38.88 - logger.trace("run", "suspend the task");
38.89 - }
38.90 - working = false;
38.91 - }
38.92 - }
38.93 -
38.94 - }
38.95 -
38.96 - private void execute() {
38.97 - try {
38.98 - executor.execute(this);
38.99 - } catch (RejectedExecutionException e) {
38.100 - logger.warning(
38.101 - "execute",
38.102 - "Executor threw exception (" + this.getClass().getName() + ")",
38.103 - e);
38.104 - throw new RejectedExecutionException(
38.105 - "Executor.execute threw exception -" +
38.106 - "should not be possible", e);
38.107 - // User-supplied Executor should not be configured in a way that
38.108 - // might cause this exception, for example if it is shared between
38.109 - // several client objects and doesn't have capacity for one job
38.110 - // from each one. CR 6732037 will add text to the spec explaining
38.111 - // the problem. The rethrown exception will propagate either out
38.112 - // of resume() to user code, or out of run() to the Executor
38.113 - // (which will probably ignore it).
38.114 - }
38.115 - }
38.116 -
38.117 - private boolean working = false;
38.118 - private final Executor executor;
38.119 -
38.120 - private static final ClassLogger logger =
38.121 - new ClassLogger("javax.management.event", "RepeatedSingletonJob");
38.122 -}
39.1 --- a/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java Mon Nov 23 10:04:47 2009 +0000
39.2 +++ b/src/share/classes/com/sun/jmx/interceptor/DefaultMBeanServerInterceptor.java Wed Nov 25 11:08:25 2009 -0800
39.3 @@ -30,16 +30,15 @@
39.4 import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
39.5 import com.sun.jmx.mbeanserver.DynamicMBean2;
39.6 import com.sun.jmx.mbeanserver.Introspector;
39.7 -import com.sun.jmx.mbeanserver.MBeanInjector;
39.8 import com.sun.jmx.mbeanserver.MBeanInstantiator;
39.9 import com.sun.jmx.mbeanserver.ModifiableClassLoaderRepository;
39.10 import com.sun.jmx.mbeanserver.NamedObject;
39.11 -import com.sun.jmx.mbeanserver.NotifySupport;
39.12 import com.sun.jmx.mbeanserver.Repository;
39.13 import com.sun.jmx.mbeanserver.Repository.RegistrationContext;
39.14 import com.sun.jmx.mbeanserver.Util;
39.15 import com.sun.jmx.remote.util.EnvHelp;
39.16
39.17 +import java.io.ObjectInputStream;
39.18 import java.lang.ref.WeakReference;
39.19 import java.security.AccessControlContext;
39.20 import java.security.AccessController;
39.21 @@ -48,10 +47,7 @@
39.22 import java.security.ProtectionDomain;
39.23 import java.util.ArrayList;
39.24 import java.util.HashSet;
39.25 -import java.util.Iterator;
39.26 -import java.util.LinkedList;
39.27 import java.util.List;
39.28 -import java.util.Queue;
39.29 import java.util.Set;
39.30 import java.util.WeakHashMap;
39.31 import java.util.logging.Level;
39.32 @@ -61,7 +57,6 @@
39.33 import javax.management.AttributeList;
39.34 import javax.management.AttributeNotFoundException;
39.35 import javax.management.DynamicMBean;
39.36 -import javax.management.DynamicWrapperMBean;
39.37 import javax.management.InstanceAlreadyExistsException;
39.38 import javax.management.InstanceNotFoundException;
39.39 import javax.management.IntrospectionException;
39.40 @@ -70,7 +65,6 @@
39.41 import javax.management.ListenerNotFoundException;
39.42 import javax.management.MBeanException;
39.43 import javax.management.MBeanInfo;
39.44 -import javax.management.MBeanNotificationInfo;
39.45 import javax.management.MBeanPermission;
39.46 import javax.management.MBeanRegistration;
39.47 import javax.management.MBeanRegistrationException;
39.48 @@ -81,19 +75,19 @@
39.49 import javax.management.NotCompliantMBeanException;
39.50 import javax.management.Notification;
39.51 import javax.management.NotificationBroadcaster;
39.52 -import javax.management.NotificationBroadcasterSupport;
39.53 import javax.management.NotificationEmitter;
39.54 import javax.management.NotificationFilter;
39.55 import javax.management.NotificationListener;
39.56 import javax.management.ObjectInstance;
39.57 import javax.management.ObjectName;
39.58 +import javax.management.OperationsException;
39.59 import javax.management.QueryEval;
39.60 import javax.management.QueryExp;
39.61 import javax.management.ReflectionException;
39.62 import javax.management.RuntimeErrorException;
39.63 import javax.management.RuntimeMBeanException;
39.64 import javax.management.RuntimeOperationsException;
39.65 -import javax.management.namespace.JMXNamespace;
39.66 +import javax.management.loading.ClassLoaderRepository;
39.67
39.68 /**
39.69 * This is the default class for MBean manipulation on the agent side. It
39.70 @@ -116,8 +110,7 @@
39.71 *
39.72 * @since 1.5
39.73 */
39.74 -public class DefaultMBeanServerInterceptor
39.75 - extends MBeanServerInterceptorSupport {
39.76 +public class DefaultMBeanServerInterceptor implements MBeanServerInterceptor {
39.77
39.78 /** The MBeanInstantiator object used by the
39.79 * DefaultMBeanServerInterceptor */
39.80 @@ -142,14 +135,9 @@
39.81 new WeakHashMap<ListenerWrapper,
39.82 WeakReference<ListenerWrapper>>();
39.83
39.84 - private final NamespaceDispatchInterceptor dispatcher;
39.85 -
39.86 /** The default domain of the object names */
39.87 private final String domain;
39.88
39.89 - /** The mbeanServerName */
39.90 - private final String mbeanServerName;
39.91 -
39.92 /** The sequence number identifying the notifications sent */
39.93 // Now sequence number is handled by MBeanServerDelegate.
39.94 // private int sequenceNumber=0;
39.95 @@ -168,13 +156,11 @@
39.96 * @param instantiator The MBeanInstantiator that will be used to
39.97 * instantiate MBeans and take care of class loading issues.
39.98 * @param repository The repository to use for this MBeanServer.
39.99 - * @param dispatcher The dispatcher used by this MBeanServer
39.100 */
39.101 public DefaultMBeanServerInterceptor(MBeanServer outer,
39.102 MBeanServerDelegate delegate,
39.103 MBeanInstantiator instantiator,
39.104 - Repository repository,
39.105 - NamespaceDispatchInterceptor dispatcher) {
39.106 + Repository repository) {
39.107 if (outer == null) throw new
39.108 IllegalArgumentException("outer MBeanServer cannot be null");
39.109 if (delegate == null) throw new
39.110 @@ -189,8 +175,6 @@
39.111 this.instantiator = instantiator;
39.112 this.repository = repository;
39.113 this.domain = repository.getDefaultDomain();
39.114 - this.dispatcher = dispatcher;
39.115 - this.mbeanServerName = Util.getMBeanServerSecurityName(delegate);
39.116 }
39.117
39.118 public ObjectInstance createMBean(String className, ObjectName name)
39.119 @@ -269,8 +253,8 @@
39.120 name = nonDefaultDomain(name);
39.121 }
39.122
39.123 - checkMBeanPermission(mbeanServerName,className, null, null, "instantiate");
39.124 - checkMBeanPermission(mbeanServerName,className, null, name, "registerMBean");
39.125 + checkMBeanPermission(className, null, null, "instantiate");
39.126 + checkMBeanPermission(className, null, name, "registerMBean");
39.127
39.128 /* Load the appropriate class. */
39.129 if (withDefaultLoaderRepository) {
39.130 @@ -334,7 +318,7 @@
39.131
39.132 final String infoClassName = getNewMBeanClassName(object);
39.133
39.134 - checkMBeanPermission(mbeanServerName,infoClassName, null, name, "registerMBean");
39.135 + checkMBeanPermission(infoClassName, null, name, "registerMBean");
39.136 checkMBeanTrustPermission(theClass);
39.137
39.138 return registerObject(infoClassName, object, name);
39.139 @@ -443,8 +427,7 @@
39.140 DynamicMBean instance = getMBean(name);
39.141 // may throw InstanceNotFoundException
39.142
39.143 - checkMBeanPermission(mbeanServerName, instance, null, name,
39.144 - "unregisterMBean");
39.145 + checkMBeanPermission(instance, null, name, "unregisterMBean");
39.146
39.147 if (instance instanceof MBeanRegistration)
39.148 preDeregisterInvoke((MBeanRegistration) instance);
39.149 @@ -478,8 +461,7 @@
39.150 name = nonDefaultDomain(name);
39.151 DynamicMBean instance = getMBean(name);
39.152
39.153 - checkMBeanPermission(mbeanServerName,
39.154 - instance, null, name, "getObjectInstance");
39.155 + checkMBeanPermission(instance, null, name, "getObjectInstance");
39.156
39.157 final String className = getClassName(instance);
39.158
39.159 @@ -491,7 +473,7 @@
39.160 if (sm != null) {
39.161 // Check if the caller has the right to invoke 'queryMBeans'
39.162 //
39.163 - checkMBeanPermission(mbeanServerName,(String) null, null, null, "queryMBeans");
39.164 + checkMBeanPermission((String) null, null, null, "queryMBeans");
39.165
39.166 // Perform query without "query".
39.167 //
39.168 @@ -504,7 +486,7 @@
39.169 new HashSet<ObjectInstance>(list.size());
39.170 for (ObjectInstance oi : list) {
39.171 try {
39.172 - checkMBeanPermission(mbeanServerName,oi.getClassName(), null,
39.173 + checkMBeanPermission(oi.getClassName(), null,
39.174 oi.getObjectName(), "queryMBeans");
39.175 allowedList.add(oi);
39.176 } catch (SecurityException e) {
39.177 @@ -537,7 +519,7 @@
39.178 if (sm != null) {
39.179 // Check if the caller has the right to invoke 'queryNames'
39.180 //
39.181 - checkMBeanPermission(mbeanServerName,(String) null, null, null, "queryNames");
39.182 + checkMBeanPermission((String) null, null, null, "queryNames");
39.183
39.184 // Perform query without "query".
39.185 //
39.186 @@ -550,7 +532,7 @@
39.187 new HashSet<ObjectInstance>(list.size());
39.188 for (ObjectInstance oi : list) {
39.189 try {
39.190 - checkMBeanPermission(mbeanServerName, oi.getClassName(), null,
39.191 + checkMBeanPermission(oi.getClassName(), null,
39.192 oi.getObjectName(), "queryNames");
39.193 allowedList.add(oi);
39.194 } catch (SecurityException e) {
39.195 @@ -602,7 +584,7 @@
39.196 if (sm != null) {
39.197 // Check if the caller has the right to invoke 'getDomains'
39.198 //
39.199 - checkMBeanPermission(mbeanServerName, (String) null, null, null, "getDomains");
39.200 + checkMBeanPermission((String) null, null, null, "getDomains");
39.201
39.202 // Return domains
39.203 //
39.204 @@ -614,8 +596,8 @@
39.205 List<String> result = new ArrayList<String>(domains.length);
39.206 for (int i = 0; i < domains.length; i++) {
39.207 try {
39.208 - ObjectName dom = ObjectName.valueOf(domains[i] + ":x=x");
39.209 - checkMBeanPermission(mbeanServerName, (String) null, null, dom, "getDomains");
39.210 + ObjectName dom = Util.newObjectName(domains[i] + ":x=x");
39.211 + checkMBeanPermission((String) null, null, dom, "getDomains");
39.212 result.add(domains[i]);
39.213 } catch (SecurityException e) {
39.214 // OK: Do not add this domain to the list
39.215 @@ -659,8 +641,7 @@
39.216 }
39.217
39.218 final DynamicMBean instance = getMBean(name);
39.219 - checkMBeanPermission(mbeanServerName, instance, attribute,
39.220 - name, "getAttribute");
39.221 + checkMBeanPermission(instance, attribute, name, "getAttribute");
39.222
39.223 try {
39.224 return instance.getAttribute(attribute);
39.225 @@ -705,7 +686,7 @@
39.226
39.227 // Check if the caller has the right to invoke 'getAttribute'
39.228 //
39.229 - checkMBeanPermission(mbeanServerName, classname, null, name, "getAttribute");
39.230 + checkMBeanPermission(classname, null, name, "getAttribute");
39.231
39.232 // Check if the caller has the right to invoke 'getAttribute'
39.233 // on each specific attribute
39.234 @@ -714,8 +695,7 @@
39.235 new ArrayList<String>(attributes.length);
39.236 for (String attr : attributes) {
39.237 try {
39.238 - checkMBeanPermission(mbeanServerName, classname, attr,
39.239 - name, "getAttribute");
39.240 + checkMBeanPermission(classname, attr, name, "getAttribute");
39.241 allowedList.add(attr);
39.242 } catch (SecurityException e) {
39.243 // OK: Do not add this attribute to the list
39.244 @@ -760,8 +740,7 @@
39.245 }
39.246
39.247 DynamicMBean instance = getMBean(name);
39.248 - checkMBeanPermission(mbeanServerName, instance, attribute.getName(),
39.249 - name, "setAttribute");
39.250 + checkMBeanPermission(instance, attribute.getName(), name, "setAttribute");
39.251
39.252 try {
39.253 instance.setAttribute(attribute);
39.254 @@ -803,7 +782,7 @@
39.255
39.256 // Check if the caller has the right to invoke 'setAttribute'
39.257 //
39.258 - checkMBeanPermission(mbeanServerName, classname, null, name, "setAttribute");
39.259 + checkMBeanPermission(classname, null, name, "setAttribute");
39.260
39.261 // Check if the caller has the right to invoke 'setAttribute'
39.262 // on each specific attribute
39.263 @@ -811,7 +790,7 @@
39.264 allowedAttributes = new AttributeList(attributes.size());
39.265 for (Attribute attribute : attributes.asList()) {
39.266 try {
39.267 - checkMBeanPermission(mbeanServerName, classname, attribute.getName(),
39.268 + checkMBeanPermission(classname, attribute.getName(),
39.269 name, "setAttribute");
39.270 allowedAttributes.add(attribute);
39.271 } catch (SecurityException e) {
39.272 @@ -835,8 +814,7 @@
39.273 name = nonDefaultDomain(name);
39.274
39.275 DynamicMBean instance = getMBean(name);
39.276 - checkMBeanPermission(mbeanServerName, instance, operationName,
39.277 - name, "invoke");
39.278 + checkMBeanPermission(instance, operationName, name, "invoke");
39.279 try {
39.280 return instance.invoke(operationName, params, signature);
39.281 } catch (Throwable t) {
39.282 @@ -919,12 +897,6 @@
39.283
39.284 DynamicMBean mbean = Introspector.makeDynamicMBean(object);
39.285
39.286 - //Access the ObjectName template value only if the provided name is null
39.287 - if(name == null) {
39.288 - name = Introspector.templateToObjectName(mbean.getMBeanInfo().
39.289 - getDescriptor(), mbean);
39.290 - }
39.291 -
39.292 return registerDynamicMBean(classname, mbean, name);
39.293 }
39.294
39.295 @@ -953,8 +925,6 @@
39.296 ResourceContext context = null;
39.297
39.298 try {
39.299 - mbean = injectResources(mbean, server, logicalName);
39.300 -
39.301 if (mbean instanceof DynamicMBean2) {
39.302 try {
39.303 ((DynamicMBean2) mbean).preRegister2(server, logicalName);
39.304 @@ -973,8 +943,7 @@
39.305 ObjectName.getInstance(nonDefaultDomain(logicalName));
39.306 }
39.307
39.308 - checkMBeanPermission(mbeanServerName, classname, null, logicalName,
39.309 - "registerMBean");
39.310 + checkMBeanPermission(classname, null, logicalName, "registerMBean");
39.311
39.312 if (logicalName == null) {
39.313 final RuntimeException wrapped =
39.314 @@ -988,10 +957,9 @@
39.315 // Register the MBean with the repository.
39.316 // Returns the resource context that was used.
39.317 // The returned context does nothing for regular MBeans.
39.318 - // For ClassLoader MBeans and JMXNamespace (and JMXDomain)
39.319 - // MBeans - the context makes it possible to register these
39.320 + // For ClassLoader MBeans the context makes it possible to register these
39.321 // objects with the appropriate framework artifacts, such as
39.322 - // the CLR or the dispatcher, from within the repository lock.
39.323 + // the CLR, from within the repository lock.
39.324 // In case of success, we also need to call context.done() at the
39.325 // end of this method.
39.326 //
39.327 @@ -1045,27 +1013,6 @@
39.328 else return name;
39.329 }
39.330
39.331 - private static DynamicMBean injectResources(
39.332 - DynamicMBean mbean, MBeanServer mbs, ObjectName name)
39.333 - throws MBeanRegistrationException {
39.334 - try {
39.335 - Object resource = getResource(mbean);
39.336 - MBeanInjector.inject(resource, mbs, name);
39.337 - if (MBeanInjector.injectsSendNotification(resource)) {
39.338 - MBeanNotificationInfo[] mbnis =
39.339 - mbean.getMBeanInfo().getNotifications();
39.340 - NotificationBroadcasterSupport nbs =
39.341 - new NotificationBroadcasterSupport(mbnis);
39.342 - MBeanInjector.injectSendNotification(resource, nbs);
39.343 - mbean = NotifySupport.wrap(mbean, nbs);
39.344 - }
39.345 - return mbean;
39.346 - } catch (Throwable t) {
39.347 - throwMBeanRegistrationException(t, "injecting @Resources");
39.348 - return null; // not reached
39.349 - }
39.350 - }
39.351 -
39.352 private static void postRegister(
39.353 ObjectName logicalName, DynamicMBean mbean,
39.354 boolean registrationDone, boolean registerFailed) {
39.355 @@ -1151,19 +1098,12 @@
39.356 }
39.357
39.358 private static Object getResource(DynamicMBean mbean) {
39.359 - if (mbean instanceof DynamicWrapperMBean)
39.360 - return ((DynamicWrapperMBean) mbean).getWrappedObject();
39.361 + if (mbean instanceof DynamicMBean2)
39.362 + return ((DynamicMBean2) mbean).getResource();
39.363 else
39.364 return mbean;
39.365 }
39.366
39.367 - private static ClassLoader getResourceLoader(DynamicMBean mbean) {
39.368 - if (mbean instanceof DynamicWrapperMBean)
39.369 - return ((DynamicWrapperMBean) mbean).getWrappedClassLoader();
39.370 - else
39.371 - return mbean.getClass().getClassLoader();
39.372 - }
39.373 -
39.374 private ObjectName nonDefaultDomain(ObjectName name) {
39.375 if (name == null || name.getDomain().length() > 0)
39.376 return name;
39.377 @@ -1177,7 +1117,7 @@
39.378 if one is supplied where it shouldn't be). */
39.379 final String completeName = domain + name;
39.380
39.381 - return ObjectName.valueOf(completeName);
39.382 + return Util.newObjectName(completeName);
39.383 }
39.384
39.385 public String getDefaultDomain() {
39.386 @@ -1243,8 +1183,7 @@
39.387 }
39.388
39.389 DynamicMBean instance = getMBean(name);
39.390 - checkMBeanPermission(mbeanServerName, instance, null,
39.391 - name, "addNotificationListener");
39.392 + checkMBeanPermission(instance, null, name, "addNotificationListener");
39.393
39.394 NotificationBroadcaster broadcaster =
39.395 getNotificationBroadcaster(name, instance,
39.396 @@ -1381,8 +1320,7 @@
39.397 }
39.398
39.399 DynamicMBean instance = getMBean(name);
39.400 - checkMBeanPermission(mbeanServerName, instance, null, name,
39.401 - "removeNotificationListener");
39.402 + checkMBeanPermission(instance, null, name, "removeNotificationListener");
39.403
39.404 /* We could simplify the code by assigning broadcaster after
39.405 assigning listenerWrapper, but that would change the error
39.406 @@ -1415,8 +1353,8 @@
39.407 Class<T> reqClass) {
39.408 if (reqClass.isInstance(instance))
39.409 return reqClass.cast(instance);
39.410 - if (instance instanceof DynamicWrapperMBean)
39.411 - instance = ((DynamicWrapperMBean) instance).getWrappedObject();
39.412 + if (instance instanceof DynamicMBean2)
39.413 + instance = ((DynamicMBean2) instance).getResource();
39.414 if (reqClass.isInstance(instance))
39.415 return reqClass.cast(instance);
39.416 final RuntimeException exc =
39.417 @@ -1452,7 +1390,7 @@
39.418 throw new JMRuntimeException("MBean " + name +
39.419 "has no MBeanInfo");
39.420
39.421 - checkMBeanPermission(mbeanServerName, mbi.getClassName(), null, name, "getMBeanInfo");
39.422 + checkMBeanPermission(mbi.getClassName(), null, name, "getMBeanInfo");
39.423
39.424 return mbi;
39.425 }
39.426 @@ -1461,8 +1399,7 @@
39.427 throws InstanceNotFoundException {
39.428
39.429 final DynamicMBean instance = getMBean(name);
39.430 - checkMBeanPermission(mbeanServerName,
39.431 - instance, null, name, "isInstanceOf");
39.432 + checkMBeanPermission(instance, null, name, "isInstanceOf");
39.433
39.434 try {
39.435 Object resource = getResource(instance);
39.436 @@ -1474,20 +1411,12 @@
39.437
39.438 if (resourceClassName.equals(className))
39.439 return true;
39.440 - final ClassLoader cl = getResourceLoader(instance);
39.441 + final ClassLoader cl = resource.getClass().getClassLoader();
39.442
39.443 final Class<?> classNameClass = Class.forName(className, false, cl);
39.444 if (classNameClass.isInstance(resource))
39.445 return true;
39.446
39.447 - // Ensure that isInstanceOf(NotificationEmitter) is true when
39.448 - // the MBean is a NotificationEmitter by virtue of a @Resource
39.449 - // annotation specifying a SendNotification resource.
39.450 - // This is a hack.
39.451 - if (instance instanceof NotificationBroadcaster &&
39.452 - classNameClass.isAssignableFrom(NotificationEmitter.class))
39.453 - return true;
39.454 -
39.455 final Class<?> resourceClass = Class.forName(resourceClassName, false, cl);
39.456 return classNameClass.isAssignableFrom(resourceClass);
39.457 } catch (Exception x) {
39.458 @@ -1513,9 +1442,8 @@
39.459 throws InstanceNotFoundException {
39.460
39.461 DynamicMBean instance = getMBean(mbeanName);
39.462 - checkMBeanPermission(mbeanServerName, instance, null, mbeanName,
39.463 - "getClassLoaderFor");
39.464 - return getResourceLoader(instance);
39.465 + checkMBeanPermission(instance, null, mbeanName, "getClassLoaderFor");
39.466 + return getResource(instance).getClass().getClassLoader();
39.467 }
39.468
39.469 /**
39.470 @@ -1529,13 +1457,12 @@
39.471 throws InstanceNotFoundException {
39.472
39.473 if (loaderName == null) {
39.474 - checkMBeanPermission(mbeanServerName, (String) null, null, null, "getClassLoader");
39.475 + checkMBeanPermission((String) null, null, null, "getClassLoader");
39.476 return server.getClass().getClassLoader();
39.477 }
39.478
39.479 DynamicMBean instance = getMBean(loaderName);
39.480 - checkMBeanPermission(mbeanServerName, instance, null, loaderName,
39.481 - "getClassLoader");
39.482 + checkMBeanPermission(instance, null, loaderName, "getClassLoader");
39.483
39.484 Object resource = getResource(instance);
39.485
39.486 @@ -1757,6 +1684,49 @@
39.487 }
39.488 }
39.489
39.490 + public Object instantiate(String className) throws ReflectionException,
39.491 + MBeanException {
39.492 + throw new UnsupportedOperationException("Not supported yet.");
39.493 + }
39.494 +
39.495 + public Object instantiate(String className, ObjectName loaderName) throws ReflectionException,
39.496 + MBeanException,
39.497 + InstanceNotFoundException {
39.498 + throw new UnsupportedOperationException("Not supported yet.");
39.499 + }
39.500 +
39.501 + public Object instantiate(String className, Object[] params,
39.502 + String[] signature) throws ReflectionException, MBeanException {
39.503 + throw new UnsupportedOperationException("Not supported yet.");
39.504 + }
39.505 +
39.506 + public Object instantiate(String className, ObjectName loaderName,
39.507 + Object[] params, String[] signature) throws ReflectionException,
39.508 + MBeanException,
39.509 + InstanceNotFoundException {
39.510 + throw new UnsupportedOperationException("Not supported yet.");
39.511 + }
39.512 +
39.513 + public ObjectInputStream deserialize(ObjectName name, byte[] data) throws InstanceNotFoundException,
39.514 + OperationsException {
39.515 + throw new UnsupportedOperationException("Not supported yet.");
39.516 + }
39.517 +
39.518 + public ObjectInputStream deserialize(String className, byte[] data) throws OperationsException,
39.519 + ReflectionException {
39.520 + throw new UnsupportedOperationException("Not supported yet.");
39.521 + }
39.522 +
39.523 + public ObjectInputStream deserialize(String className, ObjectName loaderName,
39.524 + byte[] data) throws InstanceNotFoundException, OperationsException,
39.525 + ReflectionException {
39.526 + throw new UnsupportedOperationException("Not supported yet.");
39.527 + }
39.528 +
39.529 + public ClassLoaderRepository getClassLoaderRepository() {
39.530 + throw new UnsupportedOperationException("Not supported yet.");
39.531 + }
39.532 +
39.533 private static class ListenerWrapper implements NotificationListener {
39.534 ListenerWrapper(NotificationListener l, ObjectName name,
39.535 Object mbean) {
39.536 @@ -1834,30 +1804,26 @@
39.537 return mbean.getMBeanInfo().getClassName();
39.538 }
39.539
39.540 - private static void checkMBeanPermission(String mbeanServerName,
39.541 - DynamicMBean mbean,
39.542 + private static void checkMBeanPermission(DynamicMBean mbean,
39.543 String member,
39.544 ObjectName objectName,
39.545 String actions) {
39.546 SecurityManager sm = System.getSecurityManager();
39.547 if (sm != null) {
39.548 - checkMBeanPermission(mbeanServerName,
39.549 - safeGetClassName(mbean),
39.550 + checkMBeanPermission(safeGetClassName(mbean),
39.551 member,
39.552 objectName,
39.553 actions);
39.554 }
39.555 }
39.556
39.557 - private static void checkMBeanPermission(String mbeanServerName,
39.558 - String classname,
39.559 + private static void checkMBeanPermission(String classname,
39.560 String member,
39.561 ObjectName objectName,
39.562 String actions) {
39.563 SecurityManager sm = System.getSecurityManager();
39.564 if (sm != null) {
39.565 - Permission perm = new MBeanPermission(mbeanServerName,
39.566 - classname,
39.567 + Permission perm = new MBeanPermission(classname,
39.568 member,
39.569 objectName,
39.570 actions);
39.571 @@ -1923,12 +1889,6 @@
39.572 throws InstanceAlreadyExistsException,
39.573 MBeanRegistrationException {
39.574
39.575 - // this will throw an exception if the pair (resource, logicalName)
39.576 - // violates namespace conventions - for instance, if logicalName
39.577 - // ends with // but resource is not a JMXNamespace.
39.578 - //
39.579 - checkResourceObjectNameConstraints(resource, logicalName);
39.580 -
39.581 // Creates a registration context, if needed.
39.582 //
39.583 final ResourceContext context =
39.584 @@ -1996,56 +1956,6 @@
39.585
39.586
39.587 /**
39.588 - * Checks that the ObjectName is legal with regards to the
39.589 - * type of the MBean resource.
39.590 - * If the MBean name is domain:type=JMXDomain, the
39.591 - * MBean must be a JMXDomain.
39.592 - * If the MBean name is namespace//:type=JMXNamespace, the
39.593 - * MBean must be a JMXNamespace.
39.594 - * If the MBean is a JMXDomain, its name
39.595 - * must be domain:type=JMXDomain.
39.596 - * If the MBean is a JMXNamespace, its name
39.597 - * must be namespace//:type=JMXNamespace.
39.598 - */
39.599 - private void checkResourceObjectNameConstraints(Object resource,
39.600 - ObjectName logicalName)
39.601 - throws MBeanRegistrationException {
39.602 - try {
39.603 - dispatcher.checkLocallyRegistrable(resource, logicalName);
39.604 - } catch (Throwable x) {
39.605 - DefaultMBeanServerInterceptor.throwMBeanRegistrationException(x, "validating ObjectName");
39.606 - }
39.607 - }
39.608 -
39.609 - /**
39.610 - * Registers a JMXNamespace with the dispatcher.
39.611 - * This method is called by the ResourceContext from within the
39.612 - * repository lock.
39.613 - * @param namespace The JMXNamespace
39.614 - * @param logicalName The JMXNamespaceMBean ObjectName
39.615 - * @param postQueue A queue that will be processed after postRegister.
39.616 - */
39.617 - private void addJMXNamespace(JMXNamespace namespace,
39.618 - final ObjectName logicalName,
39.619 - final Queue<Runnable> postQueue) {
39.620 - dispatcher.addInterceptorFor(logicalName, namespace, postQueue);
39.621 - }
39.622 -
39.623 - /**
39.624 - * Unregisters a JMXNamespace from the dispatcher.
39.625 - * This method is called by the ResourceContext from within the
39.626 - * repository lock.
39.627 - * @param namespace The JMXNamespace
39.628 - * @param logicalName The JMXNamespaceMBean ObjectName
39.629 - * @param postQueue A queue that will be processed after postDeregister.
39.630 - */
39.631 - private void removeJMXNamespace(JMXNamespace namespace,
39.632 - final ObjectName logicalName,
39.633 - final Queue<Runnable> postQueue) {
39.634 - dispatcher.removeInterceptorFor(logicalName, namespace, postQueue);
39.635 - }
39.636 -
39.637 - /**
39.638 * Registers a ClassLoader with the CLR.
39.639 * This method is called by the ResourceContext from within the
39.640 * repository lock.
39.641 @@ -2100,51 +2010,6 @@
39.642
39.643
39.644 /**
39.645 - * Creates a ResourceContext for a JMXNamespace MBean.
39.646 - * The resource context makes it possible to add the JMXNamespace to
39.647 - * (ResourceContext.registering) or resp. remove the JMXNamespace from
39.648 - * (ResourceContext.unregistered) the NamespaceDispatchInterceptor
39.649 - * when the associated MBean is added to or resp. removed from the
39.650 - * repository.
39.651 - * Note: JMXDomains are special sub classes of JMXNamespaces and
39.652 - * are also handled by this object.
39.653 - *
39.654 - * @param namespace The JMXNamespace MBean being registered or
39.655 - * unregistered.
39.656 - * @param logicalName The name of the JMXNamespace MBean.
39.657 - * @return a ResourceContext that takes in charge the addition or removal
39.658 - * of the namespace to or from the NamespaceDispatchInterceptor.
39.659 - */
39.660 - private ResourceContext createJMXNamespaceContext(
39.661 - final JMXNamespace namespace,
39.662 - final ObjectName logicalName) {
39.663 - final Queue<Runnable> doneTaskQueue = new LinkedList<Runnable>();
39.664 - return new ResourceContext() {
39.665 -
39.666 - public void registering() {
39.667 - addJMXNamespace(namespace, logicalName, doneTaskQueue);
39.668 - }
39.669 -
39.670 - public void unregistered() {
39.671 - removeJMXNamespace(namespace, logicalName,
39.672 - doneTaskQueue);
39.673 - }
39.674 -
39.675 - public void done() {
39.676 - for (Runnable r : doneTaskQueue) {
39.677 - try {
39.678 - r.run();
39.679 - } catch (RuntimeException x) {
39.680 - MBEANSERVER_LOGGER.log(Level.FINE,
39.681 - "Failed to process post queue for "+
39.682 - logicalName, x);
39.683 - }
39.684 - }
39.685 - }
39.686 - };
39.687 - }
39.688 -
39.689 - /**
39.690 * Creates a ResourceContext for a ClassLoader MBean.
39.691 * The resource context makes it possible to add the ClassLoader to
39.692 * (ResourceContext.registering) or resp. remove the ClassLoader from
39.693 @@ -2180,8 +2045,7 @@
39.694 * Creates a ResourceContext for the given resource.
39.695 * If the resource does not need a ResourceContext, returns
39.696 * ResourceContext.NONE.
39.697 - * At this time, only JMXNamespaces and ClassLoaders need a
39.698 - * ResourceContext.
39.699 + * At this time, only ClassLoaders need a ResourceContext.
39.700 *
39.701 * @param resource The resource being registered or unregistered.
39.702 * @param logicalName The name of the associated MBean.
39.703 @@ -2189,10 +2053,6 @@
39.704 */
39.705 private ResourceContext makeResourceContextFor(Object resource,
39.706 ObjectName logicalName) {
39.707 - if (resource instanceof JMXNamespace) {
39.708 - return createJMXNamespaceContext((JMXNamespace) resource,
39.709 - logicalName);
39.710 - }
39.711 if (resource instanceof ClassLoader) {
39.712 return createClassLoaderContext((ClassLoader) resource,
39.713 logicalName);
40.1 --- a/src/share/classes/com/sun/jmx/interceptor/DispatchInterceptor.java Mon Nov 23 10:04:47 2009 +0000
40.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
40.3 @@ -1,551 +0,0 @@
40.4 -/*
40.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
40.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
40.7 - *
40.8 - * This code is free software; you can redistribute it and/or modify it
40.9 - * under the terms of the GNU General Public License version 2 only, as
40.10 - * published by the Free Software Foundation. Sun designates this
40.11 - * particular file as subject to the "Classpath" exception as provided
40.12 - * by Sun in the LICENSE file that accompanied this code.
40.13 - *
40.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
40.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
40.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
40.17 - * version 2 for more details (a copy is included in the LICENSE file that
40.18 - * accompanied this code).
40.19 - *
40.20 - * You should have received a copy of the GNU General Public License version
40.21 - * 2 along with this work; if not, write to the Free Software Foundation,
40.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
40.23 - *
40.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
40.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
40.26 - * have any questions.
40.27 - */
40.28 -
40.29 -package com.sun.jmx.interceptor;
40.30 -
40.31 -
40.32 -import java.util.Collections;
40.33 -import java.util.HashMap;
40.34 -import java.util.Map;
40.35 -import java.util.Queue;
40.36 -import java.util.Set;
40.37 -
40.38 -import javax.management.Attribute;
40.39 -import javax.management.AttributeList;
40.40 -import javax.management.AttributeNotFoundException;
40.41 -import javax.management.InstanceAlreadyExistsException;
40.42 -import javax.management.InstanceNotFoundException;
40.43 -import javax.management.IntrospectionException;
40.44 -import javax.management.InvalidAttributeValueException;
40.45 -import javax.management.ListenerNotFoundException;
40.46 -import javax.management.MBeanException;
40.47 -import javax.management.MBeanInfo;
40.48 -import javax.management.MBeanRegistrationException;
40.49 -import javax.management.MBeanServer;
40.50 -import javax.management.NotCompliantMBeanException;
40.51 -import javax.management.NotificationFilter;
40.52 -import javax.management.NotificationListener;
40.53 -import javax.management.ObjectInstance;
40.54 -import javax.management.ObjectName;
40.55 -import javax.management.QueryExp;
40.56 -import javax.management.ReflectionException;
40.57 -import javax.management.namespace.JMXNamespace;
40.58 -
40.59 -/**
40.60 - * A dispatcher that dispatches to MBeanServers.
40.61 - * <p><b>
40.62 - * This API is a Sun internal API and is subject to changes without notice.
40.63 - * </b></p>
40.64 - * @since 1.7
40.65 - */
40.66 -//
40.67 -// This is the base class for implementing dispatchers. We have two concrete
40.68 -// dispatcher implementations:
40.69 -//
40.70 -// * A NamespaceDispatchInterceptor, which dispatch calls to existing
40.71 -// namespace interceptors
40.72 -// * A DomainDispatchInterceptor, which dispatch calls to existing domain
40.73 -// interceptors.
40.74 -//
40.75 -// With the JMX Namespaces feature, the JMX MBeanServer is now structured
40.76 -// as follows:
40.77 -//
40.78 -// The JMX MBeanServer delegates to a NamespaceDispatchInterceptor,
40.79 -// which either dispatches to a namespace, or delegates to the
40.80 -// DomainDispatchInterceptor (if the object name contained no namespace).
40.81 -// The DomainDispatchInterceptor in turn either dispatches to a domain (if
40.82 -// there is a JMXDomain for that domain) or delegates to the
40.83 -// DefaultMBeanServerInterceptor (if there is no JMXDomain for that
40.84 -// domain). This makes the following picture:
40.85 -//
40.86 -// JMX MBeanServer (outer shell)
40.87 -// |
40.88 -// |
40.89 -// NamespaceDispatchInterceptor
40.90 -// / \
40.91 -// no namespace in object name? \
40.92 -// / \
40.93 -// / dispatch to namespace
40.94 -// DomainDispatchInterceptor
40.95 -// / \
40.96 -// no JMXDomain for domain? \
40.97 -// / \
40.98 -// / dispatch to domain
40.99 -// DefaultMBeanServerInterceptor
40.100 -// /
40.101 -// invoke locally registered MBean
40.102 -//
40.103 -// The logic for maintaining a map of interceptors
40.104 -// and dispatching to impacted interceptor, is implemented in this
40.105 -// base class, which both NamespaceDispatchInterceptor and
40.106 -// DomainDispatchInterceptor extend.
40.107 -//
40.108 -public abstract class DispatchInterceptor
40.109 - <T extends MBeanServer, N extends JMXNamespace>
40.110 - extends MBeanServerInterceptorSupport {
40.111 -
40.112 - /**
40.113 - * This is an abstraction which allows us to handle queryNames
40.114 - * and queryMBeans with the same algorithm. There are some subclasses
40.115 - * where we need to override both queryNames & queryMBeans to apply
40.116 - * the same transformation (usually aggregation of results when
40.117 - * several namespaces/domains are impacted) to both algorithms.
40.118 - * Usually the only thing that varies between the algorithm of
40.119 - * queryNames & the algorithm of queryMBean is the type of objects
40.120 - * in the returned Set. By using a QueryInvoker we can implement the
40.121 - * transformation only once and apply it to both queryNames &
40.122 - * queryMBeans.
40.123 - * @see QueryInterceptor below, and its subclass in
40.124 - * {@link DomainDispatcher}.
40.125 - **/
40.126 - static abstract class QueryInvoker<T> {
40.127 - abstract Set<T> query(MBeanServer mbs,
40.128 - ObjectName pattern, QueryExp query);
40.129 - }
40.130 -
40.131 - /**
40.132 - * Used to perform queryNames. A QueryInvoker that invokes
40.133 - * queryNames on an MBeanServer.
40.134 - **/
40.135 - final static QueryInvoker<ObjectName> queryNamesInvoker =
40.136 - new QueryInvoker<ObjectName>() {
40.137 - Set<ObjectName> query(MBeanServer mbs,
40.138 - ObjectName pattern, QueryExp query) {
40.139 - return mbs.queryNames(pattern,query);
40.140 - }
40.141 - };
40.142 -
40.143 - /**
40.144 - * Used to perform queryMBeans. A QueryInvoker that invokes
40.145 - * queryMBeans on an MBeanServer.
40.146 - **/
40.147 - final static QueryInvoker<ObjectInstance> queryMBeansInvoker =
40.148 - new QueryInvoker<ObjectInstance>() {
40.149 - Set<ObjectInstance> query(MBeanServer mbs,
40.150 - ObjectName pattern, QueryExp query) {
40.151 - return mbs.queryMBeans(pattern,query);
40.152 - }
40.153 - };
40.154 -
40.155 - /**
40.156 - * We use this class to intercept queries.
40.157 - * There's a special case for JMXNamespace MBeans, because
40.158 - * "namespace//*:*" matches both "namespace//domain:k=v" and
40.159 - * "namespace//:type=JMXNamespace".
40.160 - * Therefore, queries may need to be forwarded to more than
40.161 - * on interceptor and the results aggregated...
40.162 - */
40.163 - static class QueryInterceptor {
40.164 - final MBeanServer wrapped;
40.165 - QueryInterceptor(MBeanServer mbs) {
40.166 - wrapped = mbs;
40.167 - }
40.168 - <X> Set<X> query(ObjectName pattern, QueryExp query,
40.169 - QueryInvoker<X> invoker, MBeanServer server) {
40.170 - return invoker.query(server, pattern, query);
40.171 - }
40.172 -
40.173 - public Set<ObjectName> queryNames(ObjectName pattern, QueryExp query) {
40.174 - return query(pattern,query,queryNamesInvoker,wrapped);
40.175 - }
40.176 -
40.177 - public Set<ObjectInstance> queryMBeans(ObjectName pattern,
40.178 - QueryExp query) {
40.179 - return query(pattern,query,queryMBeansInvoker,wrapped);
40.180 - }
40.181 - }
40.182 -
40.183 - // We don't need a ConcurrentHashMap here because getkeys() returns
40.184 - // an array of keys. Therefore there's no risk to have a
40.185 - // ConcurrentModificationException. We must however take into
40.186 - // account the fact that there can be no interceptor for
40.187 - // some of the returned keys if the map is being modified by
40.188 - // another thread, or by a callback within the same thread...
40.189 - // See getKeys() in this class and query() in DomainDispatcher.
40.190 - //
40.191 - private final Map<String,T> handlerMap =
40.192 - Collections.synchronizedMap(
40.193 - new HashMap<String,T>());
40.194 -
40.195 - // The key at which an interceptor for accessing the named MBean can be
40.196 - // found in the handlerMap. Note: there doesn't need to be an interceptor
40.197 - // for that key in the Map.
40.198 - //
40.199 - abstract String getHandlerKey(ObjectName name);
40.200 -
40.201 - // Returns an interceptor for that name, or null if there's no interceptor
40.202 - // for that name.
40.203 - abstract MBeanServer getInterceptorOrNullFor(ObjectName name);
40.204 -
40.205 - // Returns a QueryInterceptor for that pattern.
40.206 - abstract QueryInterceptor getInterceptorForQuery(ObjectName pattern);
40.207 -
40.208 - // Returns the ObjectName of the JMXNamespace (or JMXDomain) for that
40.209 - // key (a namespace or a domain name).
40.210 - abstract ObjectName getHandlerNameFor(String key);
40.211 -
40.212 - // Creates an interceptor for the given key, name, JMXNamespace (or
40.213 - // JMXDomain). Note: this will be either a NamespaceInterceptor
40.214 - // wrapping a JMXNamespace, if this object is an instance of
40.215 - // NamespaceDispatchInterceptor, or a DomainInterceptor wrapping a
40.216 - // JMXDomain, if this object is an instance of DomainDispatchInterceptor.
40.217 - abstract T createInterceptorFor(String key, ObjectName name,
40.218 - N jmxNamespace, Queue<Runnable> postRegisterQueue);
40.219 - //
40.220 - // The next interceptor in the chain.
40.221 - //
40.222 - // For the NamespaceDispatchInterceptor, this the DomainDispatchInterceptor.
40.223 - // For the DomainDispatchInterceptor, this is the
40.224 - // DefaultMBeanServerInterceptor.
40.225 - //
40.226 - // The logic of when to invoke the next interceptor in the chain depends
40.227 - // on the logic of the concrete dispatcher class.
40.228 - //
40.229 - // For instance, the NamespaceDispatchInterceptor invokes the next
40.230 - // interceptor when the object name doesn't contain any namespace.
40.231 - //
40.232 - // On the other hand, the DomainDispatchInterceptor invokes the
40.233 - // next interceptor when there's no interceptor for the accessed domain.
40.234 - //
40.235 - abstract MBeanServer getNextInterceptor();
40.236 -
40.237 - // hook for cleanup in subclasses.
40.238 - void interceptorReleased(T interceptor,
40.239 - Queue<Runnable> postDeregisterQueue) {
40.240 - // hook
40.241 - }
40.242 -
40.243 - // Hook for subclasses.
40.244 - MBeanServer getInterceptorForCreate(ObjectName name)
40.245 - throws MBeanRegistrationException {
40.246 - final MBeanServer ns = getInterceptorOrNullFor(name);
40.247 - if (ns == null) // name cannot be null here.
40.248 - throw new MBeanRegistrationException(
40.249 - new IllegalArgumentException("No such MBean handler: " +
40.250 - getHandlerKey(name) + " for " +name));
40.251 - return ns;
40.252 - }
40.253 -
40.254 - // Hook for subclasses.
40.255 - MBeanServer getInterceptorForInstance(ObjectName name)
40.256 - throws InstanceNotFoundException {
40.257 - final MBeanServer ns = getInterceptorOrNullFor(name);
40.258 - if (ns == null) // name cannot be null here.
40.259 - throw new InstanceNotFoundException(String.valueOf(name));
40.260 - return ns;
40.261 - }
40.262 -
40.263 - // sanity checks
40.264 - void validateHandlerNameFor(String key, ObjectName name) {
40.265 - if (key == null || key.equals(""))
40.266 - throw new IllegalArgumentException("invalid key for "+name+": "+key);
40.267 - final ObjectName handlerName = getHandlerNameFor(key);
40.268 - if (!name.equals(handlerName))
40.269 - throw new IllegalArgumentException("bad handler name: "+name+
40.270 - ". Should be: "+handlerName);
40.271 - }
40.272 -
40.273 - // Called by the DefaultMBeanServerInterceptor when an instance
40.274 - // of JMXNamespace (or a subclass of it) is registered as an MBean.
40.275 - // This method is usually invoked from within the repository lock,
40.276 - // hence the necessity of the postRegisterQueue.
40.277 - public void addInterceptorFor(ObjectName name, N jmxNamespace,
40.278 - Queue<Runnable> postRegisterQueue) {
40.279 - final String key = getHandlerKey(name);
40.280 - validateHandlerNameFor(key,name);
40.281 - synchronized (handlerMap) {
40.282 - final T exists =
40.283 - handlerMap.get(key);
40.284 - if (exists != null)
40.285 - throw new IllegalArgumentException(key+
40.286 - ": handler already exists");
40.287 -
40.288 - final T ns = createInterceptorFor(key,name,jmxNamespace,
40.289 - postRegisterQueue);
40.290 - handlerMap.put(key,ns);
40.291 - }
40.292 - }
40.293 -
40.294 - // Called by the DefaultMBeanServerInterceptor when an instance
40.295 - // of JMXNamespace (or a subclass of it) is deregistered.
40.296 - // This method is usually invoked from within the repository lock,
40.297 - // hence the necessity of the postDeregisterQueue.
40.298 - public void removeInterceptorFor(ObjectName name, N jmxNamespace,
40.299 - Queue<Runnable> postDeregisterQueue) {
40.300 - final String key = getHandlerKey(name);
40.301 - final T ns;
40.302 - synchronized(handlerMap) {
40.303 - ns = handlerMap.remove(key);
40.304 - }
40.305 - interceptorReleased(ns,postDeregisterQueue);
40.306 - }
40.307 -
40.308 - // Get the interceptor for that key.
40.309 - T getInterceptor(String key) {
40.310 - synchronized (handlerMap) {
40.311 - return handlerMap.get(key);
40.312 - }
40.313 - }
40.314 -
40.315 - // We return an array of keys, which makes it possible to make
40.316 - // concurrent modifications of the handlerMap, provided that
40.317 - // the code which loops over the keys is prepared to handle null
40.318 - // interceptors.
40.319 - // See declaration of handlerMap above, and see also query() in
40.320 - // DomainDispatcher
40.321 - //
40.322 - public String[] getKeys() {
40.323 - synchronized (handlerMap) {
40.324 - final int size = handlerMap.size();
40.325 - return handlerMap.keySet().toArray(new String[size]);
40.326 - }
40.327 - }
40.328 -
40.329 - // From MBeanServer
40.330 - public final ObjectInstance createMBean(String className, ObjectName name)
40.331 - throws ReflectionException, InstanceAlreadyExistsException,
40.332 - MBeanRegistrationException, MBeanException,
40.333 - NotCompliantMBeanException {
40.334 - return getInterceptorForCreate(name).createMBean(className,name);
40.335 - }
40.336 -
40.337 - // From MBeanServer
40.338 - public final ObjectInstance createMBean(String className, ObjectName name,
40.339 - ObjectName loaderName)
40.340 - throws ReflectionException, InstanceAlreadyExistsException,
40.341 - MBeanRegistrationException, MBeanException,
40.342 - NotCompliantMBeanException, InstanceNotFoundException{
40.343 - return getInterceptorForCreate(name).createMBean(className,name,loaderName);
40.344 - }
40.345 -
40.346 - // From MBeanServer
40.347 - public final ObjectInstance createMBean(String className, ObjectName name,
40.348 - Object params[], String signature[])
40.349 - throws ReflectionException, InstanceAlreadyExistsException,
40.350 - MBeanRegistrationException, MBeanException,
40.351 - NotCompliantMBeanException{
40.352 - return getInterceptorForCreate(name).
40.353 - createMBean(className,name,params,signature);
40.354 - }
40.355 -
40.356 - // From MBeanServer
40.357 - public final ObjectInstance createMBean(String className, ObjectName name,
40.358 - ObjectName loaderName, Object params[],
40.359 - String signature[])
40.360 - throws ReflectionException, InstanceAlreadyExistsException,
40.361 - MBeanRegistrationException, MBeanException,
40.362 - NotCompliantMBeanException, InstanceNotFoundException{
40.363 - return getInterceptorForCreate(name).createMBean(className,name,loaderName,
40.364 - params,signature);
40.365 - }
40.366 -
40.367 - // From MBeanServer
40.368 - public final ObjectInstance registerMBean(Object object, ObjectName name)
40.369 - throws InstanceAlreadyExistsException, MBeanRegistrationException,
40.370 - NotCompliantMBeanException {
40.371 - return getInterceptorForCreate(name).registerMBean(object,name);
40.372 - }
40.373 -
40.374 - // From MBeanServer
40.375 - public final void unregisterMBean(ObjectName name)
40.376 - throws InstanceNotFoundException, MBeanRegistrationException {
40.377 - getInterceptorForInstance(name).unregisterMBean(name);
40.378 - }
40.379 -
40.380 - // From MBeanServer
40.381 - public final ObjectInstance getObjectInstance(ObjectName name)
40.382 - throws InstanceNotFoundException {
40.383 - return getInterceptorForInstance(name).getObjectInstance(name);
40.384 - }
40.385 -
40.386 - // From MBeanServer
40.387 - public final Set<ObjectInstance> queryMBeans(ObjectName name,
40.388 - QueryExp query) {
40.389 - final QueryInterceptor queryInvoker =
40.390 - getInterceptorForQuery(name);
40.391 - if (queryInvoker == null) return Collections.emptySet();
40.392 - else return queryInvoker.queryMBeans(name,query);
40.393 - }
40.394 -
40.395 - // From MBeanServer
40.396 - public final Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
40.397 - final QueryInterceptor queryInvoker =
40.398 - getInterceptorForQuery(name);
40.399 - if (queryInvoker == null) return Collections.emptySet();
40.400 - else return queryInvoker.queryNames(name,query);
40.401 - }
40.402 -
40.403 - // From MBeanServer
40.404 - public final boolean isRegistered(ObjectName name) {
40.405 - final MBeanServer mbs = getInterceptorOrNullFor(name);
40.406 - if (mbs == null) return false;
40.407 - else return mbs.isRegistered(name);
40.408 - }
40.409 -
40.410 - // From MBeanServer
40.411 - public Integer getMBeanCount() {
40.412 - return getNextInterceptor().getMBeanCount();
40.413 - }
40.414 -
40.415 - // From MBeanServer
40.416 - public final Object getAttribute(ObjectName name, String attribute)
40.417 - throws MBeanException, AttributeNotFoundException,
40.418 - InstanceNotFoundException, ReflectionException {
40.419 - return getInterceptorForInstance(name).getAttribute(name,attribute);
40.420 - }
40.421 -
40.422 - // From MBeanServer
40.423 - public final AttributeList getAttributes(ObjectName name,
40.424 - String[] attributes)
40.425 - throws InstanceNotFoundException, ReflectionException {
40.426 - return getInterceptorForInstance(name).getAttributes(name,attributes);
40.427 - }
40.428 -
40.429 - // From MBeanServer
40.430 - public final void setAttribute(ObjectName name, Attribute attribute)
40.431 - throws InstanceNotFoundException, AttributeNotFoundException,
40.432 - InvalidAttributeValueException, MBeanException,
40.433 - ReflectionException {
40.434 - getInterceptorForInstance(name).setAttribute(name,attribute);
40.435 - }
40.436 -
40.437 - // From MBeanServer
40.438 - public final AttributeList setAttributes(ObjectName name,
40.439 - AttributeList attributes)
40.440 - throws InstanceNotFoundException, ReflectionException {
40.441 - return getInterceptorForInstance(name).setAttributes(name,attributes);
40.442 - }
40.443 -
40.444 - // From MBeanServer
40.445 - public final Object invoke(ObjectName name, String operationName,
40.446 - Object params[], String signature[])
40.447 - throws InstanceNotFoundException, MBeanException,
40.448 - ReflectionException {
40.449 - return getInterceptorForInstance(name).invoke(name,operationName,params,
40.450 - signature);
40.451 - }
40.452 -
40.453 - // From MBeanServer
40.454 - public String getDefaultDomain() {
40.455 - return getNextInterceptor().getDefaultDomain();
40.456 - }
40.457 -
40.458 - /**
40.459 - * Returns the list of domains in which any MBean is currently
40.460 - * registered.
40.461 - */
40.462 - public abstract String[] getDomains();
40.463 -
40.464 - // From MBeanServer
40.465 - public final void addNotificationListener(ObjectName name,
40.466 - NotificationListener listener,
40.467 - NotificationFilter filter,
40.468 - Object handback)
40.469 - throws InstanceNotFoundException {
40.470 - getInterceptorForInstance(name).
40.471 - addNotificationListener(name,listener,filter,
40.472 - handback);
40.473 - }
40.474 -
40.475 -
40.476 - // From MBeanServer
40.477 - public final void addNotificationListener(ObjectName name,
40.478 - ObjectName listener,
40.479 - NotificationFilter filter,
40.480 - Object handback)
40.481 - throws InstanceNotFoundException {
40.482 - getInterceptorForInstance(name).
40.483 - addNotificationListener(name,listener,filter,
40.484 - handback);
40.485 - }
40.486 -
40.487 - // From MBeanServer
40.488 - public final void removeNotificationListener(ObjectName name,
40.489 - ObjectName listener)
40.490 - throws InstanceNotFoundException, ListenerNotFoundException {
40.491 - getInterceptorForInstance(name).
40.492 - removeNotificationListener(name,listener);
40.493 - }
40.494 -
40.495 - // From MBeanServer
40.496 - public final void removeNotificationListener(ObjectName name,
40.497 - ObjectName listener,
40.498 - NotificationFilter filter,
40.499 - Object handback)
40.500 - throws InstanceNotFoundException, ListenerNotFoundException {
40.501 - getInterceptorForInstance(name).
40.502 - removeNotificationListener(name,listener,filter,
40.503 - handback);
40.504 - }
40.505 -
40.506 -
40.507 - // From MBeanServer
40.508 - public final void removeNotificationListener(ObjectName name,
40.509 - NotificationListener listener)
40.510 - throws InstanceNotFoundException, ListenerNotFoundException {
40.511 - getInterceptorForInstance(name).
40.512 - removeNotificationListener(name,listener);
40.513 - }
40.514 -
40.515 - // From MBeanServer
40.516 - public final void removeNotificationListener(ObjectName name,
40.517 - NotificationListener listener,
40.518 - NotificationFilter filter,
40.519 - Object handback)
40.520 - throws InstanceNotFoundException, ListenerNotFoundException {
40.521 - getInterceptorForInstance(name).
40.522 - removeNotificationListener(name,listener,filter,
40.523 - handback);
40.524 - }
40.525 -
40.526 - // From MBeanServer
40.527 - public final MBeanInfo getMBeanInfo(ObjectName name)
40.528 - throws InstanceNotFoundException, IntrospectionException,
40.529 - ReflectionException {
40.530 - return getInterceptorForInstance(name).getMBeanInfo(name);
40.531 - }
40.532 -
40.533 -
40.534 - // From MBeanServer
40.535 - public final boolean isInstanceOf(ObjectName name, String className)
40.536 - throws InstanceNotFoundException {
40.537 - return getInterceptorForInstance(name).isInstanceOf(name,className);
40.538 - }
40.539 -
40.540 - // From MBeanServer
40.541 - public final ClassLoader getClassLoaderFor(ObjectName mbeanName)
40.542 - throws InstanceNotFoundException {
40.543 - return getInterceptorForInstance(mbeanName).
40.544 - getClassLoaderFor(mbeanName);
40.545 - }
40.546 -
40.547 - // From MBeanServer
40.548 - public final ClassLoader getClassLoader(ObjectName loaderName)
40.549 - throws InstanceNotFoundException {
40.550 - return getInterceptorForInstance(loaderName).
40.551 - getClassLoader(loaderName);
40.552 - }
40.553 -
40.554 -}
41.1 --- a/src/share/classes/com/sun/jmx/interceptor/DomainDispatchInterceptor.java Mon Nov 23 10:04:47 2009 +0000
41.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
41.3 @@ -1,350 +0,0 @@
41.4 -/*
41.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
41.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
41.7 - *
41.8 - * This code is free software; you can redistribute it and/or modify it
41.9 - * under the terms of the GNU General Public License version 2 only, as
41.10 - * published by the Free Software Foundation. Sun designates this
41.11 - * particular file as subject to the "Classpath" exception as provided
41.12 - * by Sun in the LICENSE file that accompanied this code.
41.13 - *
41.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
41.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
41.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
41.17 - * version 2 for more details (a copy is included in the LICENSE file that
41.18 - * accompanied this code).
41.19 - *
41.20 - * You should have received a copy of the GNU General Public License version
41.21 - * 2 along with this work; if not, write to the Free Software Foundation,
41.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
41.23 - *
41.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
41.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
41.26 - * have any questions.
41.27 - */
41.28 -
41.29 -package com.sun.jmx.interceptor;
41.30 -
41.31 -import com.sun.jmx.defaults.JmxProperties;
41.32 -import com.sun.jmx.mbeanserver.MBeanInstantiator;
41.33 -import com.sun.jmx.mbeanserver.Repository;
41.34 -import com.sun.jmx.mbeanserver.Util;
41.35 -import com.sun.jmx.namespace.DomainInterceptor;
41.36 -import java.util.Queue;
41.37 -import java.util.Set;
41.38 -
41.39 -import java.util.logging.Level;
41.40 -import java.util.logging.Logger;
41.41 -
41.42 -import javax.management.MBeanServer;
41.43 -import javax.management.MBeanServerDelegate;
41.44 -import javax.management.ObjectName;
41.45 -import javax.management.QueryExp;
41.46 -import javax.management.namespace.JMXDomain;
41.47 -import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR;
41.48 -
41.49 -/**
41.50 - * A dispatcher that dispatch incoming MBeanServer requests to
41.51 - * DomainInterceptors.
41.52 - * <p><b>
41.53 - * This API is a Sun internal API and is subject to changes without notice.
41.54 - * </b></p>
41.55 - * @since 1.7
41.56 - */
41.57 -//
41.58 -// See comments in DispatchInterceptor.
41.59 -//
41.60 -class DomainDispatchInterceptor
41.61 - extends DispatchInterceptor<DomainInterceptor, JMXDomain> {
41.62 -
41.63 - /**
41.64 - * A logger for this class.
41.65 - **/
41.66 - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
41.67 -
41.68 - private static final ObjectName ALL_DOMAINS =
41.69 - JMXDomain.getDomainObjectName("*");
41.70 -
41.71 -
41.72 - /**
41.73 - * A QueryInterceptor that perform & aggregates queries spanning several
41.74 - * domains.
41.75 - */
41.76 - final static class AggregatingQueryInterceptor extends QueryInterceptor {
41.77 -
41.78 - private final DomainDispatchInterceptor parent;
41.79 - AggregatingQueryInterceptor(DomainDispatchInterceptor dispatcher) {
41.80 - super(dispatcher.nextInterceptor);
41.81 - parent = dispatcher;
41.82 - }
41.83 -
41.84 - /**
41.85 - * Perform queryNames or queryMBeans, depending on which QueryInvoker
41.86 - * is passed as argument. This is closures without closures.
41.87 - **/
41.88 - @Override
41.89 - <T> Set<T> query(ObjectName pattern, QueryExp query,
41.90 - QueryInvoker<T> invoker, MBeanServer localNamespace) {
41.91 - final Set<T> local = invoker.query(localNamespace, pattern, query);
41.92 -
41.93 - // Add all matching MBeans from local namespace.
41.94 - final Set<T> res = Util.cloneSet(local);
41.95 -
41.96 - if (pattern == null) pattern = ObjectName.WILDCARD;
41.97 - final boolean all = pattern.getDomain().equals("*");
41.98 -
41.99 - final String domain = pattern.getDomain();
41.100 -
41.101 - // If there's no domain pattern, just include the pattern's domain.
41.102 - // Otherwiae, loop over all virtual domains (parent.getKeys()).
41.103 - final String[] keys =
41.104 - (pattern.isDomainPattern() ?
41.105 - parent.getKeys() : new String[]{domain});
41.106 -
41.107 - // Add all matching MBeans from each virtual domain
41.108 - //
41.109 - for (String key : keys) {
41.110 - // Only invoke those virtual domain which are selected
41.111 - // by the domain pattern
41.112 - //
41.113 - if (!all && !Util.isDomainSelected(key, domain))
41.114 - continue;
41.115 -
41.116 - try {
41.117 - final MBeanServer mbs = parent.getInterceptor(key);
41.118 -
41.119 - // mbs can be null if the interceptor was removed
41.120 - // concurrently...
41.121 - // See handlerMap and getKeys() in DispatchInterceptor
41.122 - //
41.123 - if (mbs == null) continue;
41.124 -
41.125 - // If the domain is selected, we can replace the pattern
41.126 - // by the actual domain. This is safer if we want to avoid
41.127 - // a domain (which could be backed up by an MBeanServer) to
41.128 - // return names from outside the domain.
41.129 - // So instead of asking the domain handler for "foo" to
41.130 - // return all names which match "?o*:type=Bla,*" we're
41.131 - // going to ask it to return all names which match
41.132 - // "foo:type=Bla,*"
41.133 - //
41.134 - final ObjectName subPattern = pattern.withDomain(key);
41.135 - res.addAll(invoker.query(mbs, subPattern, query));
41.136 - } catch (Exception x) {
41.137 - LOG.finest("Ignoring exception " +
41.138 - "when attempting to query namespace "+key+": "+x);
41.139 - continue;
41.140 - }
41.141 - }
41.142 - return res;
41.143 - }
41.144 - }
41.145 -
41.146 - private final DefaultMBeanServerInterceptor nextInterceptor;
41.147 - private final String mbeanServerName;
41.148 - private final MBeanServerDelegate delegate;
41.149 -
41.150 - /**
41.151 - * Creates a DomainDispatchInterceptor with the specified
41.152 - * repository instance.
41.153 - *
41.154 - * @param outer A pointer to the MBeanServer object that must be
41.155 - * passed to the MBeans when invoking their
41.156 - * {@link javax.management.MBeanRegistration} interface.
41.157 - * @param delegate A pointer to the MBeanServerDelegate associated
41.158 - * with the new MBeanServer. The new MBeanServer must register
41.159 - * this MBean in its MBean repository.
41.160 - * @param instantiator The MBeanInstantiator that will be used to
41.161 - * instantiate MBeans and take care of class loading issues.
41.162 - * @param repository The repository to use for this MBeanServer
41.163 - */
41.164 - public DomainDispatchInterceptor(MBeanServer outer,
41.165 - MBeanServerDelegate delegate,
41.166 - MBeanInstantiator instantiator,
41.167 - Repository repository,
41.168 - NamespaceDispatchInterceptor namespaces) {
41.169 - nextInterceptor = new DefaultMBeanServerInterceptor(outer,
41.170 - delegate, instantiator,repository,namespaces);
41.171 - mbeanServerName = Util.getMBeanServerSecurityName(delegate);
41.172 - this.delegate = delegate;
41.173 - }
41.174 -
41.175 - final boolean isLocalHandlerNameFor(String domain,
41.176 - ObjectName handlerName) {
41.177 - if (domain == null) return true;
41.178 - return handlerName.getDomain().equals(domain) &&
41.179 - JMXDomain.TYPE_ASSIGNMENT.equals(
41.180 - handlerName.getKeyPropertyListString());
41.181 - }
41.182 -
41.183 - @Override
41.184 - void validateHandlerNameFor(String key, ObjectName name) {
41.185 - super.validateHandlerNameFor(key,name);
41.186 - final String[] domains = nextInterceptor.getDomains();
41.187 - for (int i=0;i<domains.length;i++) {
41.188 - if (domains[i].equals(key))
41.189 - throw new IllegalArgumentException("domain "+key+
41.190 - " is not empty");
41.191 - }
41.192 - }
41.193 -
41.194 - @Override
41.195 - final MBeanServer getInterceptorOrNullFor(ObjectName name) {
41.196 -
41.197 - if (name == null) return nextInterceptor;
41.198 -
41.199 - final String domain = name.getDomain();
41.200 - if (domain.endsWith(NAMESPACE_SEPARATOR))
41.201 - return nextInterceptor; // This can be a namespace handler.
41.202 - if (domain.contains(NAMESPACE_SEPARATOR))
41.203 - return null; // shouldn't reach here.
41.204 - if (isLocalHandlerNameFor(domain,name)) {
41.205 - // This is the name of a JMXDomain MBean. Return nextInterceptor.
41.206 - LOG.finer("dispatching to local namespace");
41.207 - return nextInterceptor;
41.208 - }
41.209 -
41.210 - final DomainInterceptor ns = getInterceptor(domain);
41.211 - if (ns == null) {
41.212 - // no JMXDomain found for that domain - return nextInterceptor.
41.213 - if (LOG.isLoggable(Level.FINER)) {
41.214 - LOG.finer("dispatching to local namespace: " + domain);
41.215 - }
41.216 - return getNextInterceptor();
41.217 - }
41.218 -
41.219 - if (LOG.isLoggable(Level.FINER)) {
41.220 - LOG.finer("dispatching to domain: " + domain);
41.221 - }
41.222 - return ns;
41.223 - }
41.224 -
41.225 - // This method returns true if the given pattern must be evaluated against
41.226 - // several interceptors. This happens when either:
41.227 - //
41.228 - // a) the pattern can select several domains (it's null, or it's a
41.229 - // domain pattern)
41.230 - // or b) it's not a domain pattern, but it might select the name of a
41.231 - // JMXDomain MBean in charge of that domain. Since the JMXDomain
41.232 - // MBean is located in the nextInterceptor, the pattern might need
41.233 - // to be evaluated on two interceptors.
41.234 - //
41.235 - // 1. When this method returns false, the query is evaluated on a single
41.236 - // interceptor:
41.237 - // The interceptor for pattern.getDomain(), if there is one,
41.238 - // or the next interceptor, if there is none.
41.239 - //
41.240 - // 2. When this method returns true, we loop over all the domain
41.241 - // interceptors:
41.242 - // in the list, and if the domain pattern matches the interceptor domain
41.243 - // we evaluate the query on that interceptor and aggregate the results.
41.244 - // Eventually we also evaluate the pattern against the next interceptor.
41.245 - //
41.246 - // See getInterceptorForQuery below.
41.247 - //
41.248 - private boolean multipleQuery(ObjectName pattern) {
41.249 - // case a) above
41.250 - if (pattern == null) return true;
41.251 - if (pattern.isDomainPattern()) return true;
41.252 -
41.253 - // case b) above.
41.254 - //
41.255 - // This is a bit of a hack. If there's any chance that a JMXDomain
41.256 - // MBean name is selected by the given pattern then we must include
41.257 - // the local namespace in our search.
41.258 - //
41.259 - // Returning true will have this effect. see 2. above.
41.260 - //
41.261 - if (pattern.apply(ALL_DOMAINS.withDomain(pattern.getDomain())))
41.262 - return true;
41.263 -
41.264 - return false;
41.265 - }
41.266 -
41.267 - @Override
41.268 - final QueryInterceptor getInterceptorForQuery(ObjectName pattern) {
41.269 -
41.270 - // Check if we need to aggregate.
41.271 - if (multipleQuery(pattern))
41.272 - return new AggregatingQueryInterceptor(this);
41.273 -
41.274 - // We don't need to aggregate: do the "simple" thing...
41.275 - final String domain = pattern.getDomain();
41.276 -
41.277 - // Do we have a virtual domain?
41.278 - final DomainInterceptor ns = getInterceptor(domain);
41.279 - if (ns != null) {
41.280 - if (LOG.isLoggable(Level.FINER))
41.281 - LOG.finer("dispatching to domain: " + domain);
41.282 - return new QueryInterceptor(ns);
41.283 - }
41.284 -
41.285 - // We don't have a virtual domain. Send to local domains.
41.286 - if (LOG.isLoggable(Level.FINER))
41.287 - LOG.finer("dispatching to local namespace: " + domain);
41.288 - return new QueryInterceptor(nextInterceptor);
41.289 - }
41.290 -
41.291 - @Override
41.292 - final ObjectName getHandlerNameFor(String key) {
41.293 - return JMXDomain.getDomainObjectName(key);
41.294 - }
41.295 -
41.296 - @Override
41.297 - final public String getHandlerKey(ObjectName name) {
41.298 - return name.getDomain();
41.299 - }
41.300 -
41.301 - @Override
41.302 - final DomainInterceptor createInterceptorFor(String key,
41.303 - ObjectName name, JMXDomain handler,
41.304 - Queue<Runnable> postRegisterQueue) {
41.305 - final DomainInterceptor ns =
41.306 - new DomainInterceptor(mbeanServerName,handler,key);
41.307 - ns.addPostRegisterTask(postRegisterQueue, delegate);
41.308 - if (LOG.isLoggable(Level.FINER)) {
41.309 - LOG.finer("DomainInterceptor created: "+ns);
41.310 - }
41.311 - return ns;
41.312 - }
41.313 -
41.314 - @Override
41.315 - final void interceptorReleased(DomainInterceptor interceptor,
41.316 - Queue<Runnable> postDeregisterQueue) {
41.317 - interceptor.addPostDeregisterTask(postDeregisterQueue, delegate);
41.318 - }
41.319 -
41.320 - @Override
41.321 - final DefaultMBeanServerInterceptor getNextInterceptor() {
41.322 - return nextInterceptor;
41.323 - }
41.324 -
41.325 - /**
41.326 - * Returns the list of domains in which any MBean is currently
41.327 - * registered.
41.328 - */
41.329 - @Override
41.330 - public String[] getDomains() {
41.331 - // A JMXDomain is registered in its own domain.
41.332 - // Therefore, nextInterceptor.getDomains() contains all domains.
41.333 - // In addition, nextInterceptor will perform the necessary
41.334 - // MBeanPermission checks for getDomains().
41.335 - //
41.336 - return nextInterceptor.getDomains();
41.337 - }
41.338 -
41.339 - /**
41.340 - * Returns the number of MBeans registered in the MBean server.
41.341 - */
41.342 - @Override
41.343 - public Integer getMBeanCount() {
41.344 - int count = getNextInterceptor().getMBeanCount();
41.345 - final String[] keys = getKeys();
41.346 - for (String key:keys) {
41.347 - final MBeanServer mbs = getInterceptor(key);
41.348 - if (mbs == null) continue;
41.349 - count += mbs.getMBeanCount();
41.350 - }
41.351 - return count;
41.352 - }
41.353 -}
42.1 --- a/src/share/classes/com/sun/jmx/interceptor/MBeanServerInterceptorSupport.java Mon Nov 23 10:04:47 2009 +0000
42.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
42.3 @@ -1,127 +0,0 @@
42.4 -/*
42.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
42.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
42.7 - *
42.8 - * This code is free software; you can redistribute it and/or modify it
42.9 - * under the terms of the GNU General Public License version 2 only, as
42.10 - * published by the Free Software Foundation. Sun designates this
42.11 - * particular file as subject to the "Classpath" exception as provided
42.12 - * by Sun in the LICENSE file that accompanied this code.
42.13 - *
42.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
42.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
42.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
42.17 - * version 2 for more details (a copy is included in the LICENSE file that
42.18 - * accompanied this code).
42.19 - *
42.20 - * You should have received a copy of the GNU General Public License version
42.21 - * 2 along with this work; if not, write to the Free Software Foundation,
42.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
42.23 - *
42.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
42.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
42.26 - * have any questions.
42.27 - */
42.28 -
42.29 -package com.sun.jmx.interceptor;
42.30 -
42.31 -import java.io.ObjectInputStream;
42.32 -import javax.management.InstanceNotFoundException;
42.33 -import javax.management.MBeanException;
42.34 -import javax.management.ObjectName;
42.35 -import javax.management.OperationsException;
42.36 -import javax.management.ReflectionException;
42.37 -import javax.management.loading.ClassLoaderRepository;
42.38 -
42.39 -/**
42.40 - * An abstract class for MBeanServerInterceptorSupport.
42.41 - * Some methods in MBeanServerInterceptor should never be called.
42.42 - * This base class provides an implementation of these methods that simply
42.43 - * throw an {@link UnsupportedOperationException}.
42.44 - * <p><b>
42.45 - * This API is a Sun internal API and is subject to changes without notice.
42.46 - * </b></p>
42.47 - * @since 1.7
42.48 - */
42.49 -public abstract class MBeanServerInterceptorSupport
42.50 - implements MBeanServerInterceptor {
42.51 - /**
42.52 - * This method should never be called.
42.53 - * Throws UnsupportedOperationException.
42.54 - */
42.55 - public Object instantiate(String className)
42.56 - throws ReflectionException, MBeanException {
42.57 - throw new UnsupportedOperationException("Not applicable.");
42.58 - }
42.59 -
42.60 - /**
42.61 - * This method should never be called.
42.62 - * Throws UnsupportedOperationException.
42.63 - */
42.64 - public Object instantiate(String className, ObjectName loaderName)
42.65 - throws ReflectionException, MBeanException,
42.66 - InstanceNotFoundException {
42.67 - throw new UnsupportedOperationException("Not applicable.");
42.68 - }
42.69 -
42.70 - /**
42.71 - * This method should never be called.
42.72 - * Throws UnsupportedOperationException.
42.73 - */
42.74 - public Object instantiate(String className, Object[] params,
42.75 - String[] signature) throws ReflectionException, MBeanException {
42.76 - throw new UnsupportedOperationException("Not applicable.");
42.77 - }
42.78 -
42.79 - /**
42.80 - * This method should never be called.
42.81 - * Throws UnsupportedOperationException.
42.82 - */
42.83 - public Object instantiate(String className, ObjectName loaderName,
42.84 - Object[] params, String[] signature)
42.85 - throws ReflectionException, MBeanException,
42.86 - InstanceNotFoundException {
42.87 - throw new UnsupportedOperationException("Not applicable.");
42.88 - }
42.89 -
42.90 - /**
42.91 - * This method should never be called.
42.92 - * Throws UnsupportedOperationException.
42.93 - */
42.94 - @Deprecated
42.95 - public ObjectInputStream deserialize(ObjectName name, byte[] data)
42.96 - throws InstanceNotFoundException, OperationsException {
42.97 - throw new UnsupportedOperationException("Not applicable.");
42.98 - }
42.99 -
42.100 - /**
42.101 - * This method should never be called.
42.102 - * Throws UnsupportedOperationException.
42.103 - */
42.104 - @Deprecated
42.105 - public ObjectInputStream deserialize(String className, byte[] data)
42.106 - throws OperationsException, ReflectionException {
42.107 - throw new UnsupportedOperationException("Not applicable.");
42.108 - }
42.109 -
42.110 - /**
42.111 - * This method should never be called.
42.112 - * Throws UnsupportedOperationException.
42.113 - */
42.114 - @Deprecated
42.115 - public ObjectInputStream deserialize(String className,
42.116 - ObjectName loaderName, byte[] data)
42.117 - throws InstanceNotFoundException, OperationsException,
42.118 - ReflectionException {
42.119 - throw new UnsupportedOperationException("Not applicable.");
42.120 - }
42.121 -
42.122 - /**
42.123 - * This method should never be called.
42.124 - * Throws UnsupportedOperationException.
42.125 - */
42.126 - public ClassLoaderRepository getClassLoaderRepository() {
42.127 - throw new UnsupportedOperationException("Not applicable.");
42.128 - }
42.129 -
42.130 -}
43.1 --- a/src/share/classes/com/sun/jmx/interceptor/NamespaceDispatchInterceptor.java Mon Nov 23 10:04:47 2009 +0000
43.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
43.3 @@ -1,297 +0,0 @@
43.4 -/*
43.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
43.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
43.7 - *
43.8 - * This code is free software; you can redistribute it and/or modify it
43.9 - * under the terms of the GNU General Public License version 2 only, as
43.10 - * published by the Free Software Foundation. Sun designates this
43.11 - * particular file as subject to the "Classpath" exception as provided
43.12 - * by Sun in the LICENSE file that accompanied this code.
43.13 - *
43.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
43.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
43.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
43.17 - * version 2 for more details (a copy is included in the LICENSE file that
43.18 - * accompanied this code).
43.19 - *
43.20 - * You should have received a copy of the GNU General Public License version
43.21 - * 2 along with this work; if not, write to the Free Software Foundation,
43.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
43.23 - *
43.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
43.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
43.26 - * have any questions.
43.27 - */
43.28 -
43.29 -package com.sun.jmx.interceptor;
43.30 -
43.31 -import com.sun.jmx.defaults.JmxProperties;
43.32 -import com.sun.jmx.mbeanserver.MBeanInstantiator;
43.33 -import com.sun.jmx.mbeanserver.Repository;
43.34 -import com.sun.jmx.mbeanserver.Util;
43.35 -import com.sun.jmx.namespace.NamespaceInterceptor;
43.36 -
43.37 -import java.util.Queue;
43.38 -import java.util.logging.Level;
43.39 -import java.util.logging.Logger;
43.40 -
43.41 -import javax.management.MBeanServer;
43.42 -import javax.management.MBeanServerDelegate;
43.43 -import javax.management.ObjectName;
43.44 -import javax.management.RuntimeOperationsException;
43.45 -import javax.management.namespace.JMXDomain;
43.46 -import javax.management.namespace.JMXNamespace;
43.47 -import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR;
43.48 -
43.49 -/**
43.50 - * A dispatcher that dispatches to NamespaceInterceptors.
43.51 - * <p><b>
43.52 - * This API is a Sun internal API and is subject to changes without notice.
43.53 - * </b></p>
43.54 - * @since 1.7
43.55 - */
43.56 -public class NamespaceDispatchInterceptor
43.57 - extends DispatchInterceptor<NamespaceInterceptor, JMXNamespace> {
43.58 -
43.59 - /**
43.60 - * A logger for this class.
43.61 - **/
43.62 - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
43.63 -
43.64 - private static final int NAMESPACE_SEPARATOR_LENGTH =
43.65 - NAMESPACE_SEPARATOR.length();
43.66 - private static final ObjectName X3 = ObjectName.valueOf("x:x=x");
43.67 -
43.68 - private final DomainDispatchInterceptor nextInterceptor;
43.69 - private final String serverName;
43.70 -
43.71 - /**
43.72 - * Creates a NamespaceDispatchInterceptor with the specified
43.73 - * repository instance.
43.74 - * <p>Do not forget to call <code>initialize(outer,delegate)</code>
43.75 - * before using this object.
43.76 - *
43.77 - * @param outer A pointer to the MBeanServer object that must be
43.78 - * passed to the MBeans when invoking their
43.79 - * {@link javax.management.MBeanRegistration} interface.
43.80 - * @param delegate A pointer to the MBeanServerDelegate associated
43.81 - * with the new MBeanServer. The new MBeanServer must register
43.82 - * this MBean in its MBean repository.
43.83 - * @param instantiator The MBeanInstantiator that will be used to
43.84 - * instantiate MBeans and take care of class loading issues.
43.85 - * @param repository The repository to use for this MBeanServer
43.86 - */
43.87 - public NamespaceDispatchInterceptor(MBeanServer outer,
43.88 - MBeanServerDelegate delegate,
43.89 - MBeanInstantiator instantiator,
43.90 - Repository repository) {
43.91 - nextInterceptor = new DomainDispatchInterceptor(outer,delegate,
43.92 - instantiator,repository,this);
43.93 - serverName = Util.getMBeanServerSecurityName(delegate);
43.94 - }
43.95 -
43.96 - /**
43.97 - * Get first name space in ObjectName path. Ignore leading namespace
43.98 - * separators. Includes the trailing //.
43.99 - *
43.100 - * Examples:
43.101 - * <pre>
43.102 - * For ObjectName: Returns:
43.103 - * foo//bar//baz:x=x -> "foo//"
43.104 - * foo//:type=JMXNamespace -> "foo//"
43.105 - * foo//:x=x -> "foo//"
43.106 - * foo////:x=x -> "foo//"
43.107 - * //foo//bar//baz:x=x -> "//"
43.108 - * ////foo//bar//baz:x=x -> "//"
43.109 - * //:x=x -> "//"
43.110 - * foo:x=x -> ""
43.111 - * (null) -> ""
43.112 - * :x=x -> ""
43.113 - *
43.114 - * </pre>
43.115 - **/
43.116 - static String getFirstNamespaceWithSlash(ObjectName name) {
43.117 - if (name == null) return "";
43.118 - final String domain = name.getDomain();
43.119 - if (domain.equals("")) return "";
43.120 -
43.121 - // go to next separator
43.122 - final int end = domain.indexOf(NAMESPACE_SEPARATOR);
43.123 - if (end == -1) return ""; // no namespace
43.124 -
43.125 - // This is the first element in the namespace path.
43.126 - final String namespace =
43.127 - domain.substring(0,end+NAMESPACE_SEPARATOR_LENGTH);
43.128 -
43.129 - return namespace;
43.130 - }
43.131 -
43.132 - /**
43.133 - * Called by the DefaultMBeanServerInterceptor, just before adding an
43.134 - * MBean to the repository.
43.135 - *
43.136 - * @param resource the MBean to be registered.
43.137 - * @param logicalName the name of the MBean to be registered.
43.138 - */
43.139 - final void checkLocallyRegistrable(Object resource,
43.140 - ObjectName logicalName) {
43.141 - if (!(resource instanceof JMXNamespace) &&
43.142 - logicalName.getDomain().contains(NAMESPACE_SEPARATOR))
43.143 - throw new IllegalArgumentException(String.valueOf(logicalName)+
43.144 - ": Invalid ObjectName for an instance of " +
43.145 - resource.getClass().getName());
43.146 - }
43.147 -
43.148 - // Removes the trailing //. namespaceWithSlash should be either
43.149 - // "" or a namespace path ending with //.
43.150 - //
43.151 - private final String getKeyFor(String namespaceWithSlash) {
43.152 - final int end = namespaceWithSlash.length() -
43.153 - NAMESPACE_SEPARATOR_LENGTH;
43.154 - if (end <= 0) return "";
43.155 - final String key = namespaceWithSlash.substring(0,end);
43.156 - return key;
43.157 - }
43.158 -
43.159 - @Override
43.160 - final MBeanServer getInterceptorOrNullFor(ObjectName name) {
43.161 - final String namespace = getFirstNamespaceWithSlash(name);
43.162 -
43.163 - // Leading separators should trigger instance not found exception.
43.164 - // returning null here has this effect.
43.165 - //
43.166 - if (namespace.equals(NAMESPACE_SEPARATOR)) {
43.167 - LOG.finer("ObjectName starts with: "+namespace);
43.168 - return null;
43.169 - }
43.170 -
43.171 - // namespace="" means that there was no namespace path in the
43.172 - // ObjectName. => delegate to the next interceptor (local MBS)
43.173 - // name.getDomain()=namespace means that we have an ObjectName of
43.174 - // the form blah//:x=x. This is either a JMXNamespace or a non
43.175 - // existent MBean. => delegate to the next interceptor (local MBS)
43.176 - if (namespace.equals("") || name.getDomain().equals(namespace)) {
43.177 - LOG.finer("dispatching to local name space");
43.178 - return nextInterceptor;
43.179 - }
43.180 -
43.181 - // There was a namespace path in the ObjectName. Returns the
43.182 - // interceptor that handles it, or null if there is no such
43.183 - // interceptor.
43.184 - final String key = getKeyFor(namespace);
43.185 - final NamespaceInterceptor ns = getInterceptor(key);
43.186 - if (LOG.isLoggable(Level.FINER)) {
43.187 - if (ns != null) {
43.188 - LOG.finer("dispatching to name space: " + key);
43.189 - } else {
43.190 - LOG.finer("no handler for: " + key);
43.191 - }
43.192 - }
43.193 - return ns;
43.194 - }
43.195 -
43.196 - @Override
43.197 - final QueryInterceptor getInterceptorForQuery(ObjectName pattern) {
43.198 - final String namespace = getFirstNamespaceWithSlash(pattern);
43.199 -
43.200 - // Leading separators should trigger instance not found exception.
43.201 - // returning null here has this effect.
43.202 - //
43.203 - if (namespace.equals(NAMESPACE_SEPARATOR)) {
43.204 - LOG.finer("ObjectName starts with: "+namespace);
43.205 - return null;
43.206 - }
43.207 -
43.208 - // namespace="" means that there was no namespace path in the
43.209 - // ObjectName. => delegate to the next interceptor (local MBS)
43.210 - // name.getDomain()=namespace means that we have an ObjectName of
43.211 - // the form blah//:x=x. This is either a JMXNamespace or a non
43.212 - // existent MBean. => delegate to the next interceptor (local MBS)
43.213 - if (namespace.equals("") || pattern.getDomain().equals(namespace)) {
43.214 - LOG.finer("dispatching to local name space");
43.215 - return new QueryInterceptor(nextInterceptor);
43.216 - }
43.217 -
43.218 - // This is a 'hack' to check whether the first namespace is a pattern.
43.219 - // We wan to throw RTOE wrapping IAE in that case
43.220 - if (X3.withDomain(namespace).isDomainPattern()) {
43.221 - throw new RuntimeOperationsException(
43.222 - new IllegalArgumentException("Pattern not allowed in namespace path"));
43.223 - }
43.224 -
43.225 - // There was a namespace path in the ObjectName. Returns the
43.226 - // interceptor that handles it, or null if there is no such
43.227 - // interceptor.
43.228 - //
43.229 - final String key = getKeyFor(namespace);
43.230 - final NamespaceInterceptor ns = getInterceptor(key);
43.231 - if (LOG.isLoggable(Level.FINER)) {
43.232 - if (ns != null) {
43.233 - LOG.finer("dispatching to name space: " + key);
43.234 - } else {
43.235 - LOG.finer("no handler for: " + key);
43.236 - }
43.237 - }
43.238 - if (ns == null) return null;
43.239 - return new QueryInterceptor(ns);
43.240 - }
43.241 -
43.242 - @Override
43.243 - final ObjectName getHandlerNameFor(String key) {
43.244 - return ObjectName.valueOf(key+NAMESPACE_SEPARATOR,
43.245 - "type", JMXNamespace.TYPE);
43.246 - }
43.247 -
43.248 - @Override
43.249 - final public String getHandlerKey(ObjectName name) {
43.250 - final String namespace = getFirstNamespaceWithSlash(name);
43.251 - // namespace is either "" or a namespace ending with //
43.252 - return getKeyFor(namespace);
43.253 - }
43.254 -
43.255 - @Override
43.256 - final NamespaceInterceptor createInterceptorFor(String key,
43.257 - ObjectName name, JMXNamespace handler,
43.258 - Queue<Runnable> postRegisterQueue) {
43.259 - final NamespaceInterceptor ns =
43.260 - new NamespaceInterceptor(serverName,handler,key);
43.261 - if (LOG.isLoggable(Level.FINER)) {
43.262 - LOG.finer("NamespaceInterceptor created: "+ns);
43.263 - }
43.264 - return ns;
43.265 - }
43.266 -
43.267 - @Override
43.268 - final DomainDispatchInterceptor getNextInterceptor() {
43.269 - return nextInterceptor;
43.270 - }
43.271 -
43.272 - /**
43.273 - * Returns the list of domains in which any MBean is currently
43.274 - * registered.
43.275 - */
43.276 - @Override
43.277 - public String[] getDomains() {
43.278 - return nextInterceptor.getDomains();
43.279 - }
43.280 -
43.281 - @Override
43.282 - public void addInterceptorFor(ObjectName name, JMXNamespace handler,
43.283 - Queue<Runnable> postRegisterQueue) {
43.284 - if (handler instanceof JMXDomain)
43.285 - nextInterceptor.addInterceptorFor(name,
43.286 - (JMXDomain)handler,postRegisterQueue);
43.287 - else super.addInterceptorFor(name,handler,postRegisterQueue);
43.288 - }
43.289 -
43.290 - @Override
43.291 - public void removeInterceptorFor(ObjectName name, JMXNamespace handler,
43.292 - Queue<Runnable> postDeregisterQueue) {
43.293 - if (handler instanceof JMXDomain)
43.294 - nextInterceptor.removeInterceptorFor(name,(JMXDomain)handler,
43.295 - postDeregisterQueue);
43.296 - else super.removeInterceptorFor(name,handler,postDeregisterQueue);
43.297 - }
43.298 -
43.299 -
43.300 -}
44.1 --- a/src/share/classes/com/sun/jmx/interceptor/SingleMBeanForwarder.java Mon Nov 23 10:04:47 2009 +0000
44.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
44.3 @@ -1,442 +0,0 @@
44.4 -/*
44.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
44.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44.7 - *
44.8 - * This code is free software; you can redistribute it and/or modify it
44.9 - * under the terms of the GNU General Public License version 2 only, as
44.10 - * published by the Free Software Foundation. Sun designates this
44.11 - * particular file as subject to the "Classpath" exception as provided
44.12 - * by Sun in the LICENSE file that accompanied this code.
44.13 - *
44.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
44.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
44.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
44.17 - * version 2 for more details (a copy is included in the LICENSE file that
44.18 - * accompanied this code).
44.19 - *
44.20 - * You should have received a copy of the GNU General Public License version
44.21 - * 2 along with this work; if not, write to the Free Software Foundation,
44.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
44.23 - *
44.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
44.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
44.26 - * have any questions.
44.27 - */
44.28 -
44.29 -package com.sun.jmx.interceptor;
44.30 -
44.31 -import com.sun.jmx.mbeanserver.Util;
44.32 -import java.util.Arrays;
44.33 -import java.util.Collections;
44.34 -import java.util.Set;
44.35 -import java.util.TreeSet;
44.36 -import javax.management.Attribute;
44.37 -import javax.management.AttributeList;
44.38 -import javax.management.AttributeNotFoundException;
44.39 -import javax.management.DynamicMBean;
44.40 -import javax.management.InstanceAlreadyExistsException;
44.41 -import javax.management.InstanceNotFoundException;
44.42 -import javax.management.IntrospectionException;
44.43 -import javax.management.InvalidAttributeValueException;
44.44 -import javax.management.ListenerNotFoundException;
44.45 -import javax.management.MBeanException;
44.46 -import javax.management.MBeanInfo;
44.47 -import javax.management.MBeanRegistrationException;
44.48 -import javax.management.MBeanServer;
44.49 -import javax.management.NotCompliantMBeanException;
44.50 -import javax.management.NotificationEmitter;
44.51 -import javax.management.NotificationFilter;
44.52 -import javax.management.NotificationListener;
44.53 -import javax.management.ObjectInstance;
44.54 -import javax.management.ObjectName;
44.55 -import javax.management.QueryExp;
44.56 -import javax.management.ReflectionException;
44.57 -import javax.management.namespace.JMXNamespaces;
44.58 -import javax.management.namespace.MBeanServerSupport;
44.59 -import javax.management.remote.IdentityMBeanServerForwarder;
44.60 -
44.61 -/**
44.62 - * <p>An {@link MBeanServerForwarder} that simulates the existence of a
44.63 - * given MBean. Requests for that MBean, call it X, are intercepted by the
44.64 - * forwarder, and requests for any other MBean are forwarded to the next
44.65 - * forwarder in the chain. Requests such as queryNames which can span both the
44.66 - * X and other MBeans are handled by merging the results for X with the results
44.67 - * from the next forwarder, unless the "visible" parameter is false, in which
44.68 - * case X is invisible to such requests.</p>
44.69 - */
44.70 -public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
44.71 -
44.72 - private final ObjectName mbeanName;
44.73 - private final boolean visible;
44.74 - private DynamicMBean mbean;
44.75 -
44.76 - private MBeanServer mbeanMBS = new MBeanServerSupport() {
44.77 -
44.78 - @Override
44.79 - public DynamicMBean getDynamicMBeanFor(ObjectName name)
44.80 - throws InstanceNotFoundException {
44.81 - if (mbeanName.equals(name)) {
44.82 - return mbean;
44.83 - } else {
44.84 - throw new InstanceNotFoundException(name.toString());
44.85 - }
44.86 - }
44.87 -
44.88 - @Override
44.89 - protected Set<ObjectName> getNames() {
44.90 - return Collections.singleton(mbeanName);
44.91 - }
44.92 -
44.93 - @Override
44.94 - public NotificationEmitter getNotificationEmitterFor(
44.95 - ObjectName name) {
44.96 - if (mbean instanceof NotificationEmitter)
44.97 - return (NotificationEmitter) mbean;
44.98 - return null;
44.99 - }
44.100 -
44.101 - // This will only be called if mbeanName has an empty domain.
44.102 - // In that case a getAttribute (e.g.) of that name will have the
44.103 - // domain replaced by MBeanServerSupport with the default domain,
44.104 - // so we must be sure that the default domain is empty too.
44.105 - @Override
44.106 - public String getDefaultDomain() {
44.107 - return mbeanName.getDomain();
44.108 - }
44.109 - };
44.110 -
44.111 - public SingleMBeanForwarder(
44.112 - ObjectName mbeanName, DynamicMBean mbean, boolean visible) {
44.113 - this.mbeanName = mbeanName;
44.114 - this.visible = visible;
44.115 - setSingleMBean(mbean);
44.116 - }
44.117 -
44.118 - protected void setSingleMBean(DynamicMBean mbean) {
44.119 - this.mbean = mbean;
44.120 - }
44.121 -
44.122 - @Override
44.123 - public void addNotificationListener(ObjectName name, ObjectName listener,
44.124 - NotificationFilter filter,
44.125 - Object handback)
44.126 - throws InstanceNotFoundException {
44.127 - if (mbeanName.equals(name))
44.128 - mbeanMBS.addNotificationListener(name, listener, filter, handback);
44.129 - else
44.130 - super.addNotificationListener(name, listener, filter, handback);
44.131 - }
44.132 -
44.133 - @Override
44.134 - public void addNotificationListener(ObjectName name,
44.135 - NotificationListener listener,
44.136 - NotificationFilter filter,
44.137 - Object handback)
44.138 - throws InstanceNotFoundException {
44.139 - if (mbeanName.equals(name))
44.140 - mbeanMBS.addNotificationListener(name, listener, filter, handback);
44.141 - else
44.142 - super.addNotificationListener(name, listener, filter, handback);
44.143 - }
44.144 -
44.145 - @Override
44.146 - public ObjectInstance createMBean(String className, ObjectName name,
44.147 - ObjectName loaderName, Object[] params,
44.148 - String[] signature)
44.149 - throws ReflectionException,
44.150 - InstanceAlreadyExistsException,
44.151 - MBeanRegistrationException,
44.152 - MBeanException,
44.153 - NotCompliantMBeanException,
44.154 - InstanceNotFoundException {
44.155 - if (mbeanName.equals(name))
44.156 - throw new InstanceAlreadyExistsException(mbeanName.toString());
44.157 - else
44.158 - return super.createMBean(className, name, loaderName, params, signature);
44.159 - }
44.160 -
44.161 - @Override
44.162 - public ObjectInstance createMBean(String className, ObjectName name,
44.163 - Object[] params, String[] signature)
44.164 - throws ReflectionException, InstanceAlreadyExistsException,
44.165 - MBeanRegistrationException, MBeanException,
44.166 - NotCompliantMBeanException {
44.167 - if (mbeanName.equals(name))
44.168 - throw new InstanceAlreadyExistsException(mbeanName.toString());
44.169 - return super.createMBean(className, name, params, signature);
44.170 - }
44.171 -
44.172 - @Override
44.173 - public ObjectInstance createMBean(String className, ObjectName name,
44.174 - ObjectName loaderName)
44.175 - throws ReflectionException,
44.176 - InstanceAlreadyExistsException,
44.177 - MBeanRegistrationException,
44.178 - MBeanException,
44.179 - NotCompliantMBeanException,
44.180 - InstanceNotFoundException {
44.181 - if (mbeanName.equals(name))
44.182 - throw new InstanceAlreadyExistsException(mbeanName.toString());
44.183 - return super.createMBean(className, name, loaderName);
44.184 - }
44.185 -
44.186 - @Override
44.187 - public ObjectInstance createMBean(String className, ObjectName name)
44.188 - throws ReflectionException,
44.189 - InstanceAlreadyExistsException,
44.190 - MBeanRegistrationException,
44.191 - MBeanException,
44.192 - NotCompliantMBeanException {
44.193 - if (mbeanName.equals(name))
44.194 - throw new InstanceAlreadyExistsException(mbeanName.toString());
44.195 - return super.createMBean(className, name);
44.196 - }
44.197 -
44.198 - @Override
44.199 - public Object getAttribute(ObjectName name, String attribute)
44.200 - throws MBeanException,
44.201 - AttributeNotFoundException,
44.202 - InstanceNotFoundException,
44.203 - ReflectionException {
44.204 - if (mbeanName.equals(name))
44.205 - return mbeanMBS.getAttribute(name, attribute);
44.206 - else
44.207 - return super.getAttribute(name, attribute);
44.208 - }
44.209 -
44.210 - @Override
44.211 - public AttributeList getAttributes(ObjectName name, String[] attributes)
44.212 - throws InstanceNotFoundException, ReflectionException {
44.213 - if (mbeanName.equals(name))
44.214 - return mbeanMBS.getAttributes(name, attributes);
44.215 - else
44.216 - return super.getAttributes(name, attributes);
44.217 - }
44.218 -
44.219 - @Override
44.220 - public ClassLoader getClassLoader(ObjectName loaderName)
44.221 - throws InstanceNotFoundException {
44.222 - if (mbeanName.equals(loaderName))
44.223 - return mbeanMBS.getClassLoader(loaderName);
44.224 - else
44.225 - return super.getClassLoader(loaderName);
44.226 - }
44.227 -
44.228 - @Override
44.229 - public ClassLoader getClassLoaderFor(ObjectName name)
44.230 - throws InstanceNotFoundException {
44.231 - if (mbeanName.equals(name))
44.232 - return mbeanMBS.getClassLoaderFor(name);
44.233 - else
44.234 - return super.getClassLoaderFor(name);
44.235 - }
44.236 -
44.237 - @Override
44.238 - public String[] getDomains() {
44.239 - String[] domains = super.getDomains();
44.240 - if (!visible)
44.241 - return domains;
44.242 - TreeSet<String> domainSet = new TreeSet<String>(Arrays.asList(domains));
44.243 - domainSet.add(mbeanName.getDomain());
44.244 - return domainSet.toArray(new String[domainSet.size()]);
44.245 - }
44.246 -
44.247 - @Override
44.248 - public Integer getMBeanCount() {
44.249 - Integer count = super.getMBeanCount();
44.250 - if (visible && !super.isRegistered(mbeanName))
44.251 - count++;
44.252 - return count;
44.253 - }
44.254 -
44.255 - @Override
44.256 - public MBeanInfo getMBeanInfo(ObjectName name)
44.257 - throws InstanceNotFoundException,
44.258 - IntrospectionException,
44.259 - ReflectionException {
44.260 - if (mbeanName.equals(name))
44.261 - return mbeanMBS.getMBeanInfo(name);
44.262 - else
44.263 - return super.getMBeanInfo(name);
44.264 - }
44.265 -
44.266 - @Override
44.267 - public ObjectInstance getObjectInstance(ObjectName name)
44.268 - throws InstanceNotFoundException {
44.269 - if (mbeanName.equals(name))
44.270 - return mbeanMBS.getObjectInstance(name);
44.271 - else
44.272 - return super.getObjectInstance(name);
44.273 - }
44.274 -
44.275 - @Override
44.276 - public Object invoke(ObjectName name, String operationName, Object[] params,
44.277 - String[] signature)
44.278 - throws InstanceNotFoundException,
44.279 - MBeanException,
44.280 - ReflectionException {
44.281 - if (mbeanName.equals(name))
44.282 - return mbeanMBS.invoke(name, operationName, params, signature);
44.283 - else
44.284 - return super.invoke(name, operationName, params, signature);
44.285 - }
44.286 -
44.287 - @Override
44.288 - public boolean isInstanceOf(ObjectName name, String className)
44.289 - throws InstanceNotFoundException {
44.290 - if (mbeanName.equals(name))
44.291 - return mbeanMBS.isInstanceOf(name, className);
44.292 - else
44.293 - return super.isInstanceOf(name, className);
44.294 - }
44.295 -
44.296 - @Override
44.297 - public boolean isRegistered(ObjectName name) {
44.298 - if (mbeanName.equals(name))
44.299 - return true;
44.300 - else
44.301 - return super.isRegistered(name);
44.302 - }
44.303 -
44.304 - /**
44.305 - * This is a ugly hack. Although jmx.context//*:* matches jmx.context//:*
44.306 - * queryNames(jmx.context//*:*,null) must not return jmx.context//:*
44.307 - * @param pattern the pattern to match against. must not be null.
44.308 - * @return true if mbeanName can be included, false if it must not.
44.309 - */
44.310 - private boolean applies(ObjectName pattern) {
44.311 - // we know pattern is not null.
44.312 - if (!visible || !pattern.apply(mbeanName))
44.313 - return false;
44.314 -
44.315 - final String dompat = pattern.getDomain();
44.316 - if (!dompat.contains(JMXNamespaces.NAMESPACE_SEPARATOR))
44.317 - return true; // We already checked that patterns apply.
44.318 -
44.319 - if (mbeanName.getDomain().endsWith(JMXNamespaces.NAMESPACE_SEPARATOR)) {
44.320 - // only matches if pattern ends with //
44.321 - return dompat.endsWith(JMXNamespaces.NAMESPACE_SEPARATOR);
44.322 - }
44.323 -
44.324 - // should not come here, unless mbeanName contains a // in the
44.325 - // middle of its domain, which would be weird.
44.326 - // let query on mbeanMBS proceed and take care of that.
44.327 - //
44.328 - return true;
44.329 - }
44.330 -
44.331 - @Override
44.332 - public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
44.333 - Set<ObjectInstance> names = super.queryMBeans(name, query);
44.334 - if (visible) {
44.335 - if (name == null || applies(name) ) {
44.336 - // Don't assume mbs.queryNames returns a writable set.
44.337 - names = Util.cloneSet(names);
44.338 - names.addAll(mbeanMBS.queryMBeans(name, query));
44.339 - }
44.340 - }
44.341 - return names;
44.342 - }
44.343 -
44.344 - @Override
44.345 - public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
44.346 - Set<ObjectName> names = super.queryNames(name, query);
44.347 - if (visible) {
44.348 - if (name == null || applies(name)) {
44.349 - // Don't assume mbs.queryNames returns a writable set.
44.350 - names = Util.cloneSet(names);
44.351 - names.addAll(mbeanMBS.queryNames(name, query));
44.352 - }
44.353 - }
44.354 - return names;
44.355 - }
44.356 -
44.357 -
44.358 - @Override
44.359 - public ObjectInstance registerMBean(Object object, ObjectName name)
44.360 - throws InstanceAlreadyExistsException,
44.361 - MBeanRegistrationException,
44.362 - NotCompliantMBeanException {
44.363 - if (mbeanName.equals(name))
44.364 - throw new InstanceAlreadyExistsException(mbeanName.toString());
44.365 - else
44.366 - return super.registerMBean(object, name);
44.367 - }
44.368 -
44.369 - @Override
44.370 - public void removeNotificationListener(ObjectName name,
44.371 - NotificationListener listener,
44.372 - NotificationFilter filter,
44.373 - Object handback)
44.374 - throws InstanceNotFoundException,
44.375 - ListenerNotFoundException {
44.376 - if (mbeanName.equals(name))
44.377 - mbeanMBS.removeNotificationListener(name, listener, filter, handback);
44.378 - else
44.379 - super.removeNotificationListener(name, listener, filter, handback);
44.380 - }
44.381 -
44.382 - @Override
44.383 - public void removeNotificationListener(ObjectName name,
44.384 - NotificationListener listener)
44.385 - throws InstanceNotFoundException, ListenerNotFoundException {
44.386 - if (mbeanName.equals(name))
44.387 - mbeanMBS.removeNotificationListener(name, listener);
44.388 - else
44.389 - super.removeNotificationListener(name, listener);
44.390 - }
44.391 -
44.392 - @Override
44.393 - public void removeNotificationListener(ObjectName name, ObjectName listener,
44.394 - NotificationFilter filter,
44.395 - Object handback)
44.396 - throws InstanceNotFoundException,
44.397 - ListenerNotFoundException {
44.398 - if (mbeanName.equals(name))
44.399 - mbeanMBS.removeNotificationListener(name, listener, filter, handback);
44.400 - else
44.401 - super.removeNotificationListener(name, listener, filter, handback);
44.402 - }
44.403 -
44.404 - @Override
44.405 - public void removeNotificationListener(ObjectName name, ObjectName listener)
44.406 - throws InstanceNotFoundException, ListenerNotFoundException {
44.407 - if (mbeanName.equals(name))
44.408 - mbeanMBS.removeNotificationListener(name, listener);
44.409 - else
44.410 - super.removeNotificationListener(name, listener);
44.411 - }
44.412 -
44.413 - @Override
44.414 - public void setAttribute(ObjectName name, Attribute attribute)
44.415 - throws InstanceNotFoundException,
44.416 - AttributeNotFoundException,
44.417 - InvalidAttributeValueException,
44.418 - MBeanException,
44.419 - ReflectionException {
44.420 - if (mbeanName.equals(name))
44.421 - mbeanMBS.setAttribute(name, attribute);
44.422 - else
44.423 - super.setAttribute(name, attribute);
44.424 - }
44.425 -
44.426 - @Override
44.427 - public AttributeList setAttributes(ObjectName name,
44.428 - AttributeList attributes)
44.429 - throws InstanceNotFoundException, ReflectionException {
44.430 - if (mbeanName.equals(name))
44.431 - return mbeanMBS.setAttributes(name, attributes);
44.432 - else
44.433 - return super.setAttributes(name, attributes);
44.434 - }
44.435 -
44.436 - @Override
44.437 - public void unregisterMBean(ObjectName name)
44.438 - throws InstanceNotFoundException,
44.439 - MBeanRegistrationException {
44.440 - if (mbeanName.equals(name))
44.441 - mbeanMBS.unregisterMBean(name);
44.442 - else
44.443 - super.unregisterMBean(name);
44.444 - }
44.445 -}
45.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/ConvertingMethod.java Mon Nov 23 10:04:47 2009 +0000
45.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/ConvertingMethod.java Wed Nov 25 11:08:25 2009 -0800
45.3 @@ -31,15 +31,13 @@
45.4
45.5 import javax.management.Descriptor;
45.6 import javax.management.MBeanException;
45.7 -import javax.management.openmbean.MXBeanMapping;
45.8 -import javax.management.openmbean.MXBeanMappingFactory;
45.9 import javax.management.openmbean.OpenDataException;
45.10 import javax.management.openmbean.OpenType;
45.11
45.12 final class ConvertingMethod {
45.13 - static ConvertingMethod from(Method m, MXBeanMappingFactory mappingFactory) {
45.14 + static ConvertingMethod from(Method m) {
45.15 try {
45.16 - return new ConvertingMethod(m, mappingFactory);
45.17 + return new ConvertingMethod(m);
45.18 } catch (OpenDataException ode) {
45.19 final String msg = "Method " + m.getDeclaringClass().getName() +
45.20 "." + m.getName() + " has parameter or return type that " +
45.21 @@ -53,7 +51,7 @@
45.22 }
45.23
45.24 Descriptor getDescriptor() {
45.25 - return Introspector.descriptorForElement(method, false);
45.26 + return Introspector.descriptorForElement(method);
45.27 }
45.28
45.29 Type getGenericReturnType() {
45.30 @@ -206,9 +204,9 @@
45.31 return method.getDeclaringClass() + "." + method.getName();
45.32 }
45.33
45.34 - private ConvertingMethod(Method m, MXBeanMappingFactory mappingFactory)
45.35 - throws OpenDataException {
45.36 + private ConvertingMethod(Method m) throws OpenDataException {
45.37 this.method = m;
45.38 + MXBeanMappingFactory mappingFactory = MXBeanMappingFactory.DEFAULT;
45.39 returnMapping =
45.40 mappingFactory.mappingForType(m.getGenericReturnType(), mappingFactory);
45.41 Type[] params = m.getGenericParameterTypes();
46.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java Mon Nov 23 10:04:47 2009 +0000
46.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/DefaultMXBeanMappingFactory.java Wed Nov 25 11:08:25 2009 -0800
46.3 @@ -28,8 +28,6 @@
46.4 import static com.sun.jmx.mbeanserver.Util.*;
46.5 import static com.sun.jmx.mbeanserver.MXBeanIntrospector.typeName;
46.6
46.7 -import javax.management.openmbean.MXBeanMappingClass;
46.8 -
46.9 import static javax.management.openmbean.SimpleType.*;
46.10
46.11 import com.sun.jmx.remote.util.EnvHelp;
46.12 @@ -69,8 +67,6 @@
46.13 import javax.management.openmbean.CompositeDataSupport;
46.14 import javax.management.openmbean.CompositeDataView;
46.15 import javax.management.openmbean.CompositeType;
46.16 -import javax.management.openmbean.MXBeanMapping;
46.17 -import javax.management.openmbean.MXBeanMappingFactory;
46.18 import javax.management.openmbean.OpenDataException;
46.19 import javax.management.openmbean.OpenType;
46.20 import javax.management.openmbean.SimpleType;
46.21 @@ -165,34 +161,29 @@
46.22 private static final class Mappings
46.23 extends WeakHashMap<Type, WeakReference<MXBeanMapping>> {}
46.24
46.25 - private static final Map<MXBeanMappingFactory, Mappings> factoryMappings =
46.26 - new WeakHashMap<MXBeanMappingFactory, Mappings>();
46.27 + private static final Mappings mappings = new Mappings();
46.28
46.29 - private static final Map<Type, MXBeanMapping> permanentMappings = newMap();
46.30 + /** Following List simply serves to keep a reference to predefined
46.31 + MXBeanMappings so they don't get garbage collected. */
46.32 + private static final List<MXBeanMapping> permanentMappings = newList();
46.33
46.34 - private static synchronized MXBeanMapping getMapping(
46.35 - Type type, MXBeanMappingFactory factory) {
46.36 - Mappings mappings = factoryMappings.get(factory);
46.37 - if (mappings == null) {
46.38 - mappings = new Mappings();
46.39 - factoryMappings.put(factory, mappings);
46.40 - }
46.41 + private static synchronized MXBeanMapping getMapping(Type type) {
46.42 WeakReference<MXBeanMapping> wr = mappings.get(type);
46.43 return (wr == null) ? null : wr.get();
46.44 }
46.45
46.46 - private static synchronized void putMapping(
46.47 - Type type, MXBeanMapping mapping, MXBeanMappingFactory factory) {
46.48 - Mappings mappings = factoryMappings.get(factory);
46.49 - if (mappings == null) {
46.50 - mappings = new Mappings();
46.51 - factoryMappings.put(factory, mappings);
46.52 - }
46.53 + private static synchronized void putMapping(Type type, MXBeanMapping mapping) {
46.54 WeakReference<MXBeanMapping> wr =
46.55 new WeakReference<MXBeanMapping>(mapping);
46.56 mappings.put(type, wr);
46.57 }
46.58
46.59 + private static synchronized void putPermanentMapping(
46.60 + Type type, MXBeanMapping mapping) {
46.61 + putMapping(type, mapping);
46.62 + permanentMappings.add(mapping);
46.63 + }
46.64 +
46.65 static {
46.66 /* Set up the mappings for Java types that map to SimpleType. */
46.67
46.68 @@ -213,7 +204,7 @@
46.69 throw new Error(e);
46.70 }
46.71 final MXBeanMapping mapping = new IdentityMapping(c, t);
46.72 - permanentMappings.put(c, mapping);
46.73 + putPermanentMapping(c, mapping);
46.74
46.75 if (c.getName().startsWith("java.lang.")) {
46.76 try {
46.77 @@ -221,7 +212,7 @@
46.78 final Class<?> primitiveType = (Class<?>) typeField.get(null);
46.79 final MXBeanMapping primitiveMapping =
46.80 new IdentityMapping(primitiveType, t);
46.81 - permanentMappings.put(primitiveType, primitiveMapping);
46.82 + putPermanentMapping(primitiveType, primitiveMapping);
46.83 if (primitiveType != void.class) {
46.84 final Class<?> primitiveArrayType =
46.85 Array.newInstance(primitiveType, 0).getClass();
46.86 @@ -230,8 +221,8 @@
46.87 final MXBeanMapping primitiveArrayMapping =
46.88 new IdentityMapping(primitiveArrayType,
46.89 primitiveArrayOpenType);
46.90 - permanentMappings.put(primitiveArrayType,
46.91 - primitiveArrayMapping);
46.92 + putPermanentMapping(primitiveArrayType,
46.93 + primitiveArrayMapping);
46.94 }
46.95 } catch (NoSuchFieldException e) {
46.96 // OK: must not be a primitive wrapper
46.97 @@ -255,7 +246,7 @@
46.98
46.99 MXBeanMapping mapping;
46.100
46.101 - mapping = getMapping(objType, null);
46.102 + mapping = getMapping(objType);
46.103 if (mapping != null)
46.104 return mapping;
46.105
46.106 @@ -268,7 +259,7 @@
46.107 inProgress.remove(objType);
46.108 }
46.109
46.110 - putMapping(objType, mapping, factory);
46.111 + putMapping(objType, mapping);
46.112 return mapping;
46.113 }
46.114
46.115 @@ -278,14 +269,6 @@
46.116 /* It's not yet worth formalizing these tests by having for example
46.117 an array of factory classes, each of which says whether it
46.118 recognizes the Type (Chain of Responsibility pattern). */
46.119 - MXBeanMapping mapping = permanentMappings.get(objType);
46.120 - if (mapping != null)
46.121 - return mapping;
46.122 - Class<?> erasure = erasure(objType);
46.123 - MXBeanMappingClass mappingClass =
46.124 - erasure.getAnnotation(MXBeanMappingClass.class);
46.125 - if (mappingClass != null)
46.126 - return makeAnnotationMapping(mappingClass, objType, factory);
46.127 if (objType instanceof GenericArrayType) {
46.128 Type componentType =
46.129 ((GenericArrayType) objType).getGenericComponentType();
46.130 @@ -313,51 +296,6 @@
46.131 throw new OpenDataException("Cannot map type: " + objType);
46.132 }
46.133
46.134 - private static MXBeanMapping
46.135 - makeAnnotationMapping(MXBeanMappingClass mappingClass,
46.136 - Type objType,
46.137 - MXBeanMappingFactory factory)
46.138 - throws OpenDataException {
46.139 - Class<? extends MXBeanMapping> c = mappingClass.value();
46.140 - Constructor<? extends MXBeanMapping> cons;
46.141 - try {
46.142 - cons = c.getConstructor(Type.class);
46.143 - } catch (NoSuchMethodException e) {
46.144 - final String msg =
46.145 - "Annotation @" + MXBeanMappingClass.class.getName() +
46.146 - " must name a class with a public constructor that has a " +
46.147 - "single " + Type.class.getName() + " argument";
46.148 - OpenDataException ode = new OpenDataException(msg);
46.149 - ode.initCause(e);
46.150 - throw ode;
46.151 - }
46.152 - try {
46.153 - return cons.newInstance(objType);
46.154 - } catch (Exception e) {
46.155 - final String msg =
46.156 - "Could not construct a " + c.getName() + " for @" +
46.157 - MXBeanMappingClass.class.getName();
46.158 - OpenDataException ode = new OpenDataException(msg);
46.159 - ode.initCause(e);
46.160 - throw ode;
46.161 - }
46.162 - }
46.163 -
46.164 - private static Class<?> erasure(Type t) {
46.165 - if (t instanceof Class<?>)
46.166 - return (Class<?>) t;
46.167 - if (t instanceof ParameterizedType)
46.168 - return erasure(((ParameterizedType) t).getRawType());
46.169 - /* Other cases: GenericArrayType, TypeVariable, WildcardType.
46.170 - * Returning the erasure of GenericArrayType is not necessary because
46.171 - * anyway we will be recursing on the element type, and we'll erase
46.172 - * then. Returning the erasure of the other two would mean returning
46.173 - * the type bound (e.g. Foo in <T extends Foo> or <? extends Foo>)
46.174 - * and since we don't treat this as Foo elsewhere we shouldn't here.
46.175 - */
46.176 - return Object.class;
46.177 - }
46.178 -
46.179 private static <T extends Enum<T>> MXBeanMapping
46.180 makeEnumMapping(Class<?> enumClass, Class<T> fake) {
46.181 return new EnumMapping<T>(Util.<Class<T>>cast(enumClass));
47.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/DynamicMBean2.java Mon Nov 23 10:04:47 2009 +0000
47.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/DynamicMBean2.java Wed Nov 25 11:08:25 2009 -0800
47.3 @@ -1,5 +1,5 @@
47.4 /*
47.5 - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
47.6 + * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
47.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
47.8 *
47.9 * This code is free software; you can redistribute it and/or modify it
47.10 @@ -25,7 +25,7 @@
47.11
47.12 package com.sun.jmx.mbeanserver;
47.13
47.14 -import javax.management.DynamicWrapperMBean;
47.15 +import javax.management.DynamicMBean;
47.16 import javax.management.MBeanServer;
47.17 import javax.management.ObjectName;
47.18
47.19 @@ -35,7 +35,17 @@
47.20 *
47.21 * @since 1.6
47.22 */
47.23 -public interface DynamicMBean2 extends DynamicWrapperMBean {
47.24 +public interface DynamicMBean2 extends DynamicMBean {
47.25 + /**
47.26 + * The resource corresponding to this MBean. This is the object whose
47.27 + * class name should be reflected by the MBean's
47.28 + * getMBeanInfo().getClassName() for example. For a "plain"
47.29 + * DynamicMBean it will be "this". For an MBean that wraps another
47.30 + * object, like javax.management.StandardMBean, it will be the wrapped
47.31 + * object.
47.32 + */
47.33 + public Object getResource();
47.34 +
47.35 /**
47.36 * The name of this MBean's class, as used by permission checks.
47.37 * This is typically equal to getResource().getClass().getName().
48.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Mon Nov 23 10:04:47 2009 +0000
48.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/Introspector.java Wed Nov 25 11:08:25 2009 -0800
48.3 @@ -25,14 +25,9 @@
48.4
48.5 package com.sun.jmx.mbeanserver;
48.6
48.7 -import com.sun.jmx.remote.util.EnvHelp;
48.8 -import java.beans.BeanInfo;
48.9 -import java.beans.PropertyDescriptor;
48.10 import java.lang.annotation.Annotation;
48.11 import java.lang.reflect.AnnotatedElement;
48.12 -import java.lang.reflect.Array;
48.13 import java.lang.reflect.Constructor;
48.14 -import java.lang.reflect.InvocationTargetException;
48.15 import java.lang.reflect.Method;
48.16 import java.lang.reflect.Modifier;
48.17 import java.lang.reflect.Proxy;
48.18 @@ -40,39 +35,21 @@
48.19 import java.util.Arrays;
48.20 import java.util.HashMap;
48.21 import java.util.Map;
48.22 -import java.util.logging.Level;
48.23 -import javax.management.AttributeNotFoundException;
48.24 -import javax.management.Description;
48.25
48.26 import javax.management.Descriptor;
48.27 -import javax.management.DescriptorFields;
48.28 import javax.management.DescriptorKey;
48.29 import javax.management.DynamicMBean;
48.30 import javax.management.ImmutableDescriptor;
48.31 -import javax.management.MBean;
48.32 import javax.management.MBeanInfo;
48.33 -import javax.management.MXBean;
48.34 import javax.management.NotCompliantMBeanException;
48.35 -import javax.management.openmbean.CompositeData;
48.36 -import javax.management.openmbean.MXBeanMappingFactory;
48.37
48.38 -import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
48.39 -import com.sun.jmx.mbeanserver.Util;
48.40 import com.sun.jmx.remote.util.EnvHelp;
48.41 import java.beans.BeanInfo;
48.42 import java.beans.PropertyDescriptor;
48.43 import java.lang.reflect.Array;
48.44 import java.lang.reflect.InvocationTargetException;
48.45 -import java.util.LinkedHashSet;
48.46 -import java.util.Set;
48.47 -import java.util.regex.Matcher;
48.48 -import java.util.regex.Pattern;
48.49 import javax.management.AttributeNotFoundException;
48.50 -import javax.management.JMX;
48.51 -import javax.management.ObjectName;
48.52 -import javax.management.ObjectNameTemplate;
48.53 import javax.management.openmbean.CompositeData;
48.54 -import javax.management.openmbean.MXBeanMappingFactory;
48.55
48.56 /**
48.57 * This class contains the methods for performing all the tests needed to verify
48.58 @@ -82,13 +59,7 @@
48.59 */
48.60 public class Introspector {
48.61
48.62 - /**
48.63 - * Pattern used to extract Attribute Names from ObjectNameTemplate Annotation
48.64 - * For example, in the following example, the Name attribute value is
48.65 - * retrieved : ":type=MyType, name={Name}"
48.66 - */
48.67 - private static Pattern OBJECT_NAME_PATTERN_TEMPLATE =
48.68 - Pattern.compile("(\\{[^\\}]+\\})|(=\"\\{[^\\}]+\\}\")");
48.69 +
48.70 /*
48.71 * ------------------------------------------
48.72 * PRIVATE CONSTRUCTORS
48.73 @@ -164,10 +135,6 @@
48.74
48.75 public static void checkCompliance(Class<?> mbeanClass)
48.76 throws NotCompliantMBeanException {
48.77 -
48.78 - // Check that @Resource is used correctly (if it used).
48.79 - MBeanInjector.validate(mbeanClass);
48.80 -
48.81 // Is DynamicMBean?
48.82 //
48.83 if (DynamicMBean.class.isAssignableFrom(mbeanClass))
48.84 @@ -190,36 +157,16 @@
48.85 } catch (NotCompliantMBeanException e) {
48.86 mxbeanException = e;
48.87 }
48.88 - // Is @MBean or @MXBean class?
48.89 - // In fact we find @MBean or @MXBean as a hacky variant of
48.90 - // getStandardMBeanInterface or getMXBeanInterface. If we get here
48.91 - // then nothing worked.
48.92 final String msg =
48.93 "MBean class " + mbeanClass.getName() + " does not implement " +
48.94 - "DynamicMBean; does not follow the Standard MBean conventions (" +
48.95 - mbeanException.toString() + "); does not follow the MXBean conventions (" +
48.96 - mxbeanException.toString() + "); and does not have or inherit the @" +
48.97 - MBean.class.getSimpleName() + " or @" + MXBean.class.getSimpleName() +
48.98 - " annotation";
48.99 + "DynamicMBean, and neither follows the Standard MBean conventions (" +
48.100 + mbeanException.toString() + ") nor the MXBean conventions (" +
48.101 + mxbeanException.toString() + ")";
48.102 throw new NotCompliantMBeanException(msg);
48.103 }
48.104
48.105 - /**
48.106 - * <p>Make a DynamicMBean out of the existing MBean object. The object
48.107 - * may already be a DynamicMBean, or it may be a Standard MBean or
48.108 - * MXBean, possibly defined using {@code @MBean} or {@code @MXBean}.</p>
48.109 - * @param mbean the object to convert to a DynamicMBean.
48.110 - * @param <T> a type parameter defined for implementation convenience
48.111 - * (which would have to be removed if this method were part of the public
48.112 - * API).
48.113 - * @return the converted DynamicMBean.
48.114 - * @throws NotCompliantMBeanException if {@code mbean} is not a compliant
48.115 - * MBean object, including the case where it is null.
48.116 - */
48.117 public static <T> DynamicMBean makeDynamicMBean(T mbean)
48.118 - throws NotCompliantMBeanException {
48.119 - if (mbean == null)
48.120 - throw new NotCompliantMBeanException("Null MBean object");
48.121 + throws NotCompliantMBeanException {
48.122 if (mbean instanceof DynamicMBean)
48.123 return (DynamicMBean) mbean;
48.124 final Class<?> mbeanClass = mbean.getClass();
48.125 @@ -240,18 +187,8 @@
48.126 // to be an MBean or an MXBean. We will call checkCompliance()
48.127 // to generate the appropriate exception.
48.128 }
48.129 - if (c != null) {
48.130 - MXBeanMappingFactory factory;
48.131 - try {
48.132 - factory = MXBeanMappingFactory.forInterface(c);
48.133 - } catch (IllegalArgumentException e) {
48.134 - NotCompliantMBeanException ncmbe =
48.135 - new NotCompliantMBeanException(e.getMessage());
48.136 - ncmbe.initCause(e);
48.137 - throw ncmbe;
48.138 - }
48.139 - return new MXBeanSupport(mbean, c, factory);
48.140 - }
48.141 + if (c != null)
48.142 + return new MXBeanSupport(mbean, c);
48.143 checkCompliance(mbeanClass);
48.144 throw new NotCompliantMBeanException("Not compliant"); // not reached
48.145 }
48.146 @@ -280,10 +217,9 @@
48.147 return testCompliance(baseClass, null);
48.148 }
48.149
48.150 - public static void testComplianceMXBeanInterface(Class<?> interfaceClass,
48.151 - MXBeanMappingFactory factory)
48.152 + public static void testComplianceMXBeanInterface(Class<?> interfaceClass)
48.153 throws NotCompliantMBeanException {
48.154 - MXBeanIntrospector.getInstance(factory).getAnalyzer(interfaceClass);
48.155 + MXBeanIntrospector.getInstance().getAnalyzer(interfaceClass);
48.156 }
48.157
48.158 /**
48.159 @@ -352,8 +288,6 @@
48.160 */
48.161 public static <T> Class<? super T> getStandardMBeanInterface(Class<T> baseClass)
48.162 throws NotCompliantMBeanException {
48.163 - if (baseClass.isAnnotationPresent(MBean.class))
48.164 - return baseClass;
48.165 Class<? super T> current = baseClass;
48.166 Class<? super T> mbeanInterface = null;
48.167 while (current != null) {
48.168 @@ -384,8 +318,6 @@
48.169 */
48.170 public static <T> Class<? super T> getMXBeanInterface(Class<T> baseClass)
48.171 throws NotCompliantMBeanException {
48.172 - if (hasMXBeanAnnotation(baseClass))
48.173 - return baseClass;
48.174 try {
48.175 return MXBeanSupport.findMXBeanInterface(baseClass);
48.176 } catch (Exception e) {
48.177 @@ -393,61 +325,12 @@
48.178 }
48.179 }
48.180
48.181 - public static <T> Class<? super T> getStandardOrMXBeanInterface(
48.182 - Class<T> baseClass, boolean mxbean)
48.183 - throws NotCompliantMBeanException {
48.184 - if (mxbean)
48.185 - return getMXBeanInterface(baseClass);
48.186 - else
48.187 - return getStandardMBeanInterface(baseClass);
48.188 - }
48.189 -
48.190 - public static ObjectName templateToObjectName(Descriptor descriptor,
48.191 - DynamicMBean mbean)
48.192 - throws NotCompliantMBeanException {
48.193 - String template = (String)
48.194 - descriptor.getFieldValue(JMX.OBJECT_NAME_TEMPLATE);
48.195 - if(template == null) return null;
48.196 - try {
48.197 - Matcher m = OBJECT_NAME_PATTERN_TEMPLATE.matcher(template);
48.198 - while (m.find()){
48.199 - String grp = m.group();
48.200 - System.out.println("GROUP " + grp);
48.201 - String attributeName = null;
48.202 - boolean quote = false;
48.203 - if(grp.startsWith("=\"{")) {
48.204 - attributeName = grp.substring(3, grp.length() - 2);
48.205 - quote = true;
48.206 - } else
48.207 - attributeName = grp.substring(1, grp.length() - 1);
48.208 -
48.209 - Object attributeValue = mbean.getAttribute(attributeName);
48.210 - String validValue = quote ?
48.211 - "=" + ObjectName.quote(attributeValue.toString()) :
48.212 - attributeValue.toString();
48.213 - template = template.replace(grp, validValue);
48.214 - }
48.215 - return new ObjectName(template);
48.216 - }catch(Exception ex) {
48.217 - NotCompliantMBeanException ncex = new
48.218 - NotCompliantMBeanException(ObjectNameTemplate.class.
48.219 - getSimpleName() + " annotation value [" + template + "] " +
48.220 - "is invalid. " + ex);
48.221 - ncex.initCause(ex);
48.222 - throw ncex;
48.223 - }
48.224 - }
48.225 -
48.226 /*
48.227 * ------------------------------------------
48.228 * PRIVATE METHODS
48.229 * ------------------------------------------
48.230 */
48.231
48.232 - static boolean hasMXBeanAnnotation(Class<?> c) {
48.233 - MXBean m = c.getAnnotation(MXBean.class);
48.234 - return (m != null && m.value());
48.235 - }
48.236
48.237 /**
48.238 * Try to find the MBean interface corresponding to the class aName
48.239 @@ -469,77 +352,11 @@
48.240 return null;
48.241 }
48.242
48.243 - public static String descriptionForElement(AnnotatedElement elmt) {
48.244 - if (elmt == null)
48.245 - return null;
48.246 - Description d = elmt.getAnnotation(Description.class);
48.247 - if (d == null)
48.248 - return null;
48.249 - return d.value();
48.250 - }
48.251 -
48.252 - public static String descriptionForParameter(
48.253 - Annotation[] parameterAnnotations) {
48.254 - for (Annotation a : parameterAnnotations) {
48.255 - if (a instanceof Description)
48.256 - return ((Description) a).value();
48.257 - }
48.258 - return null;
48.259 - }
48.260 -
48.261 - public static String nameForParameter(
48.262 - Annotation[] parameterAnnotations) {
48.263 - for (Annotation a : parameterAnnotations) {
48.264 - Class<? extends Annotation> ac = a.annotationType();
48.265 - // You'd really have to go out of your way to have more than
48.266 - // one @Name annotation, so we don't check for that.
48.267 - if (ac.getSimpleName().equals("Name")) {
48.268 - try {
48.269 - Method value = ac.getMethod("value");
48.270 - if (value.getReturnType() == String.class &&
48.271 - value.getParameterTypes().length == 0) {
48.272 - return (String) value.invoke(a);
48.273 - }
48.274 - } catch (Exception e) {
48.275 - MBEANSERVER_LOGGER.log(
48.276 - Level.WARNING,
48.277 - "Unexpected exception getting @" + ac.getName(),
48.278 - e);
48.279 - }
48.280 - }
48.281 - }
48.282 - return null;
48.283 - }
48.284 -
48.285 - public static Descriptor descriptorForElement(final AnnotatedElement elmt,
48.286 - boolean isSetter) {
48.287 + public static Descriptor descriptorForElement(final AnnotatedElement elmt) {
48.288 if (elmt == null)
48.289 return ImmutableDescriptor.EMPTY_DESCRIPTOR;
48.290 final Annotation[] annots = elmt.getAnnotations();
48.291 - Descriptor descr = descriptorForAnnotations(annots);
48.292 - String[] exceptions = {};
48.293 - if(elmt instanceof Method)
48.294 - exceptions = getAllExceptions(((Method) elmt).getExceptionTypes());
48.295 - else
48.296 - if(elmt instanceof Constructor<?>)
48.297 - exceptions = getAllExceptions(((Constructor<?>) elmt).
48.298 - getExceptionTypes());
48.299 -
48.300 - if(exceptions.length > 0 ) {
48.301 - String fieldName = isSetter ? JMX.SET_EXCEPTIONS_FIELD :
48.302 - JMX.EXCEPTIONS_FIELD;
48.303 -
48.304 - String[] fieldNames = {fieldName};
48.305 - Object[] fieldValues = {exceptions};
48.306 - descr = ImmutableDescriptor.union(descr,
48.307 - new ImmutableDescriptor(fieldNames, fieldValues));
48.308 - }
48.309 -
48.310 - return descr;
48.311 - }
48.312 -
48.313 - public static Descriptor descriptorForAnnotation(Annotation annot) {
48.314 - return descriptorForAnnotations(new Annotation[] {annot});
48.315 + return descriptorForAnnotations(annots);
48.316 }
48.317
48.318 public static Descriptor descriptorForAnnotations(Annotation[] annots) {
48.319 @@ -547,9 +364,36 @@
48.320 return ImmutableDescriptor.EMPTY_DESCRIPTOR;
48.321 Map<String, Object> descriptorMap = new HashMap<String, Object>();
48.322 for (Annotation a : annots) {
48.323 - if (a instanceof DescriptorFields)
48.324 - addDescriptorFieldsToMap(descriptorMap, (DescriptorFields) a);
48.325 - addAnnotationFieldsToMap(descriptorMap, a);
48.326 + Class<? extends Annotation> c = a.annotationType();
48.327 + Method[] elements = c.getMethods();
48.328 + for (Method element : elements) {
48.329 + DescriptorKey key = element.getAnnotation(DescriptorKey.class);
48.330 + if (key != null) {
48.331 + String name = key.value();
48.332 + Object value;
48.333 + try {
48.334 + value = element.invoke(a);
48.335 + } catch (RuntimeException e) {
48.336 + // we don't expect this - except for possibly
48.337 + // security exceptions?
48.338 + // RuntimeExceptions shouldn't be "UndeclaredThrowable".
48.339 + // anyway...
48.340 + //
48.341 + throw e;
48.342 + } catch (Exception e) {
48.343 + // we don't expect this
48.344 + throw new UndeclaredThrowableException(e);
48.345 + }
48.346 + value = annotationToField(value);
48.347 + Object oldValue = descriptorMap.put(name, value);
48.348 + if (oldValue != null && !equals(oldValue, value)) {
48.349 + final String msg =
48.350 + "Inconsistent values for descriptor field " + name +
48.351 + " from annotations: " + value + " :: " + oldValue;
48.352 + throw new IllegalArgumentException(msg);
48.353 + }
48.354 + }
48.355 + }
48.356 }
48.357
48.358 if (descriptorMap.isEmpty())
48.359 @@ -559,76 +403,6 @@
48.360 }
48.361
48.362 /**
48.363 - * Array of thrown excepions.
48.364 - * @param exceptions can be null;
48.365 - * @return An Array of Exception class names. Size is 0 if method is null.
48.366 - */
48.367 - private static String[] getAllExceptions(Class<?>[] exceptions) {
48.368 - Set<String> set = new LinkedHashSet<String>();
48.369 - for(Class<?>ex : exceptions)
48.370 - set.add(ex.getName());
48.371 -
48.372 - String[] arr = new String[set.size()];
48.373 - return set.toArray(arr);
48.374 - }
48.375 -
48.376 - private static void addDescriptorFieldsToMap(
48.377 - Map<String, Object> descriptorMap, DescriptorFields df) {
48.378 - for (String field : df.value()) {
48.379 - int eq = field.indexOf('=');
48.380 - if (eq < 0) {
48.381 - throw new IllegalArgumentException(
48.382 - "@DescriptorFields string must contain '=': " +
48.383 - field);
48.384 - }
48.385 - String name = field.substring(0, eq);
48.386 - String value = field.substring(eq + 1);
48.387 - addToMap(descriptorMap, name, value);
48.388 - }
48.389 - }
48.390 -
48.391 - private static void addAnnotationFieldsToMap(
48.392 - Map<String, Object> descriptorMap, Annotation a) {
48.393 - Class<? extends Annotation> c = a.annotationType();
48.394 - Method[] elements = c.getMethods();
48.395 - for (Method element : elements) {
48.396 - DescriptorKey key = element.getAnnotation(DescriptorKey.class);
48.397 - if (key != null) {
48.398 - String name = key.value();
48.399 - Object value;
48.400 - try {
48.401 - value = element.invoke(a);
48.402 - } catch (RuntimeException e) {
48.403 - // we don't expect this - except for possibly
48.404 - // security exceptions?
48.405 - // RuntimeExceptions shouldn't be "UndeclaredThrowable".
48.406 - // anyway...
48.407 - throw e;
48.408 - } catch (Exception e) {
48.409 - // we don't expect this
48.410 - throw new UndeclaredThrowableException(e);
48.411 - }
48.412 - if (!key.omitIfDefault() ||
48.413 - !equals(value, element.getDefaultValue())) {
48.414 - value = annotationToField(value);
48.415 - addToMap(descriptorMap, name, value);
48.416 - }
48.417 - }
48.418 - }
48.419 - }
48.420 -
48.421 - private static void addToMap(
48.422 - Map<String, Object> descriptorMap, String name, Object value) {
48.423 - Object oldValue = descriptorMap.put(name, value);
48.424 - if (oldValue != null && !equals(oldValue, value)) {
48.425 - final String msg =
48.426 - "Inconsistent values for descriptor field " + name +
48.427 - " from annotations: " + value + " :: " + oldValue;
48.428 - throw new IllegalArgumentException(msg);
48.429 - }
48.430 - }
48.431 -
48.432 - /**
48.433 * Throws a NotCompliantMBeanException or a SecurityException.
48.434 * @param notCompliant the class which was under examination
48.435 * @param cause the raeson why NotCompliantMBeanException should
49.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java Mon Nov 23 10:04:47 2009 +0000
49.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/JmxMBeanServer.java Wed Nov 25 11:08:25 2009 -0800
49.3 @@ -25,14 +25,14 @@
49.4
49.5 package com.sun.jmx.mbeanserver;
49.6
49.7 +import com.sun.jmx.interceptor.DefaultMBeanServerInterceptor;
49.8 +import com.sun.jmx.interceptor.MBeanServerInterceptor;
49.9 import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
49.10 -import com.sun.jmx.interceptor.NamespaceDispatchInterceptor;
49.11
49.12 import java.io.ObjectInputStream;
49.13 import java.security.AccessController;
49.14 import java.security.Permission;
49.15 import java.security.PrivilegedExceptionAction;
49.16 -import java.util.Iterator;
49.17 import java.util.List;
49.18 import java.util.Set;
49.19 import java.util.logging.Level;
49.20 @@ -108,8 +108,6 @@
49.21 /** The MBeanServerDelegate object representing the MBean Server */
49.22 private final MBeanServerDelegate mBeanServerDelegateObject;
49.23
49.24 - private final String mbeanServerName;
49.25 -
49.26 /**
49.27 * <b>Package:</b> Creates an MBeanServer with the
49.28 * specified default domain name, outer interface, and delegate.
49.29 @@ -241,10 +239,9 @@
49.30
49.31 final Repository repository = new Repository(domain);
49.32 this.mbsInterceptor =
49.33 - new NamespaceDispatchInterceptor(outer, delegate, instantiator,
49.34 + new DefaultMBeanServerInterceptor(outer, delegate, instantiator,
49.35 repository);
49.36 this.interceptorsEnabled = interceptors;
49.37 - this.mbeanServerName = Util.getMBeanServerSecurityName(delegate);
49.38 initialize();
49.39 }
49.40
49.41 @@ -940,8 +937,7 @@
49.42 throws ReflectionException, MBeanException {
49.43
49.44 /* Permission check */
49.45 - checkMBeanPermission(mbeanServerName, className, null, null,
49.46 - "instantiate");
49.47 + checkMBeanPermission(className, null, null, "instantiate");
49.48
49.49 return instantiator.instantiate(className);
49.50 }
49.51 @@ -978,8 +974,7 @@
49.52 InstanceNotFoundException {
49.53
49.54 /* Permission check */
49.55 - checkMBeanPermission(mbeanServerName, className, null,
49.56 - null, "instantiate");
49.57 + checkMBeanPermission(className, null, null, "instantiate");
49.58
49.59 ClassLoader myLoader = outerShell.getClass().getClassLoader();
49.60 return instantiator.instantiate(className, loaderName, myLoader);
49.61 @@ -1017,8 +1012,7 @@
49.62 throws ReflectionException, MBeanException {
49.63
49.64 /* Permission check */
49.65 - checkMBeanPermission(mbeanServerName, className, null, null,
49.66 - "instantiate");
49.67 + checkMBeanPermission(className, null, null, "instantiate");
49.68
49.69 ClassLoader myLoader = outerShell.getClass().getClassLoader();
49.70 return instantiator.instantiate(className, params, signature,
49.71 @@ -1061,8 +1055,7 @@
49.72 InstanceNotFoundException {
49.73
49.74 /* Permission check */
49.75 - checkMBeanPermission(mbeanServerName, className, null,
49.76 - null, "instantiate");
49.77 + checkMBeanPermission(className, null, null, "instantiate");
49.78
49.79 ClassLoader myLoader = outerShell.getClass().getClassLoader();
49.80 return instantiator.instantiate(className,loaderName,params,signature,
49.81 @@ -1333,8 +1326,7 @@
49.82 **/
49.83 public ClassLoaderRepository getClassLoaderRepository() {
49.84 /* Permission check */
49.85 - checkMBeanPermission(mbeanServerName, null, null,
49.86 - null, "getClassLoaderRepository");
49.87 + checkMBeanPermission(null, null, null, "getClassLoaderRepository");
49.88 return secureClr;
49.89 }
49.90
49.91 @@ -1487,16 +1479,14 @@
49.92 // SECURITY CHECKS
49.93 //----------------
49.94
49.95 - private static void checkMBeanPermission(String serverName,
49.96 - String classname,
49.97 + private static void checkMBeanPermission(String classname,
49.98 String member,
49.99 ObjectName objectName,
49.100 String actions)
49.101 throws SecurityException {
49.102 SecurityManager sm = System.getSecurityManager();
49.103 if (sm != null) {
49.104 - Permission perm = new MBeanPermission(serverName,
49.105 - classname,
49.106 + Permission perm = new MBeanPermission(classname,
49.107 member,
49.108 objectName,
49.109 actions);
50.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java Mon Nov 23 10:04:47 2009 +0000
50.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanAnalyzer.java Wed Nov 25 11:08:25 2009 -0800
50.3 @@ -33,10 +33,6 @@
50.4 import java.util.List;
50.5 import java.util.Map;
50.6 import java.util.Set;
50.7 -import javax.management.MBean;
50.8 -import javax.management.MXBean;
50.9 -import javax.management.ManagedAttribute;
50.10 -import javax.management.ManagedOperation;
50.11 import javax.management.NotCompliantMBeanException;
50.12
50.13 /**
50.14 @@ -55,15 +51,15 @@
50.15 */
50.16 class MBeanAnalyzer<M> {
50.17
50.18 - static interface MBeanVisitor<M, X extends Exception> {
50.19 + static interface MBeanVisitor<M> {
50.20 public void visitAttribute(String attributeName,
50.21 M getter,
50.22 - M setter) throws X;
50.23 + M setter);
50.24 public void visitOperation(String operationName,
50.25 - M operation) throws X;
50.26 + M operation);
50.27 }
50.28
50.29 - <X extends Exception> void visit(MBeanVisitor<M, X> visitor) throws X {
50.30 + void visit(MBeanVisitor<M> visitor) {
50.31 // visit attributes
50.32 for (Map.Entry<String, AttrMethods<M>> entry : attrMap.entrySet()) {
50.33 String name = entry.getKey();
50.34 @@ -108,7 +104,10 @@
50.35 private MBeanAnalyzer(Class<?> mbeanType,
50.36 MBeanIntrospector<M> introspector)
50.37 throws NotCompliantMBeanException {
50.38 - introspector.checkCompliance(mbeanType);
50.39 + if (!mbeanType.isInterface()) {
50.40 + throw new NotCompliantMBeanException("Not an interface: " +
50.41 + mbeanType.getName());
50.42 + }
50.43
50.44 try {
50.45 initMaps(mbeanType, introspector);
50.46 @@ -129,26 +128,18 @@
50.47 for (Method m : methods) {
50.48 final String name = m.getName();
50.49 final int nParams = m.getParameterTypes().length;
50.50 - final boolean managedOp = m.isAnnotationPresent(ManagedOperation.class);
50.51 - final boolean managedAttr = m.isAnnotationPresent(ManagedAttribute.class);
50.52 - if (managedOp && managedAttr) {
50.53 - throw new NotCompliantMBeanException("Method " + name +
50.54 - " has both @ManagedOperation and @ManagedAttribute");
50.55 - }
50.56
50.57 final M cm = introspector.mFrom(m);
50.58
50.59 String attrName = "";
50.60 - if (!managedOp) {
50.61 - if (name.startsWith("get"))
50.62 - attrName = name.substring(3);
50.63 - else if (name.startsWith("is")
50.64 - && m.getReturnType() == boolean.class)
50.65 - attrName = name.substring(2);
50.66 - }
50.67 + if (name.startsWith("get"))
50.68 + attrName = name.substring(3);
50.69 + else if (name.startsWith("is")
50.70 + && m.getReturnType() == boolean.class)
50.71 + attrName = name.substring(2);
50.72
50.73 if (attrName.length() != 0 && nParams == 0
50.74 - && m.getReturnType() != void.class && !managedOp) {
50.75 + && m.getReturnType() != void.class) {
50.76 // It's a getter
50.77 // Check we don't have both isX and getX
50.78 AttrMethods<M> am = attrMap.get(attrName);
50.79 @@ -165,7 +156,7 @@
50.80 attrMap.put(attrName, am);
50.81 } else if (name.startsWith("set") && name.length() > 3
50.82 && nParams == 1 &&
50.83 - m.getReturnType() == void.class && !managedOp) {
50.84 + m.getReturnType() == void.class) {
50.85 // It's a setter
50.86 attrName = name.substring(3);
50.87 AttrMethods<M> am = attrMap.get(attrName);
50.88 @@ -178,9 +169,6 @@
50.89 }
50.90 am.setter = cm;
50.91 attrMap.put(attrName, am);
50.92 - } else if (managedAttr) {
50.93 - throw new NotCompliantMBeanException("Method " + name +
50.94 - " has @ManagedAttribute but is not a valid getter or setter");
50.95 } else {
50.96 // It's an operation
50.97 List<M> cms = opMap.get(name);
51.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanInjector.java Mon Nov 23 10:04:47 2009 +0000
51.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
51.3 @@ -1,295 +0,0 @@
51.4 -/*
51.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
51.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
51.7 - *
51.8 - * This code is free software; you can redistribute it and/or modify it
51.9 - * under the terms of the GNU General Public License version 2 only, as
51.10 - * published by the Free Software Foundation. Sun designates this
51.11 - * particular file as subject to the "Classpath" exception as provided
51.12 - * by Sun in the LICENSE file that accompanied this code.
51.13 - *
51.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
51.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
51.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
51.17 - * version 2 for more details (a copy is included in the LICENSE file that
51.18 - * accompanied this code).
51.19 - *
51.20 - * You should have received a copy of the GNU General Public License version
51.21 - * 2 along with this work; if not, write to the Free Software Foundation,
51.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
51.23 - *
51.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
51.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
51.26 - * have any questions.
51.27 - */
51.28 -
51.29 -package com.sun.jmx.mbeanserver;
51.30 -
51.31 -import java.lang.ref.WeakReference;
51.32 -import java.security.PrivilegedAction;
51.33 -import java.util.Map;
51.34 -import java.util.WeakHashMap;
51.35 -import javax.annotation.Resource;
51.36 -import javax.management.MBeanServer;
51.37 -import javax.management.NotCompliantMBeanException;
51.38 -import javax.management.ObjectName;
51.39 -
51.40 -import static com.sun.jmx.mbeanserver.Util.newMap;
51.41 -import java.lang.reflect.AccessibleObject;
51.42 -import java.lang.reflect.Field;
51.43 -import java.lang.reflect.InvocationTargetException;
51.44 -import java.lang.reflect.Method;
51.45 -import java.lang.reflect.Modifier;
51.46 -import java.security.AccessController;
51.47 -import java.util.ArrayList;
51.48 -import java.util.Collections;
51.49 -import java.util.List;
51.50 -import javax.management.SendNotification;
51.51 -
51.52 -public class MBeanInjector {
51.53 - // There are no instances of this class
51.54 - private MBeanInjector() {
51.55 - }
51.56 -
51.57 - private static Class<?>[] injectedClasses = {
51.58 - MBeanServer.class, ObjectName.class, SendNotification.class,
51.59 - };
51.60 -
51.61 - public static void inject(Object mbean, MBeanServer mbs, ObjectName name)
51.62 - throws Exception {
51.63 - ClassInjector injector = injectorForClass(mbean.getClass());
51.64 - injector.inject(mbean, MBeanServer.class, mbs);
51.65 - injector.inject(mbean, ObjectName.class, name);
51.66 - }
51.67 -
51.68 - public static boolean injectsSendNotification(Object mbean)
51.69 - throws NotCompliantMBeanException {
51.70 - ClassInjector injector = injectorForClass(mbean.getClass());
51.71 - return injector.injects(SendNotification.class);
51.72 - }
51.73 -
51.74 - public static void injectSendNotification(Object mbean, SendNotification sn)
51.75 - throws Exception {
51.76 - ClassInjector injector = injectorForClass(mbean.getClass());
51.77 - injector.inject(mbean, SendNotification.class, sn);
51.78 - }
51.79 -
51.80 - public static void validate(Class<?> c) throws NotCompliantMBeanException {
51.81 - injectorForClass(c);
51.82 - }
51.83 -
51.84 - private static class ClassInjector {
51.85 - private Map<Class<?>, List<Field>> fields;
51.86 - private Map<Class<?>, List<Method>> methods;
51.87 -
51.88 - ClassInjector(Class<?> c) throws NotCompliantMBeanException {
51.89 - fields = newMap();
51.90 - methods = newMap();
51.91 -
51.92 - Class<?> sup = c.getSuperclass();
51.93 - ClassInjector supInjector;
51.94 - if (sup == null) {
51.95 - supInjector = null;
51.96 - } else {
51.97 - supInjector = injectorForClass(sup);
51.98 - fields.putAll(supInjector.fields);
51.99 - methods.putAll(supInjector.methods);
51.100 - }
51.101 -
51.102 - addMembers(c);
51.103 - eliminateOverriddenMethods();
51.104 -
51.105 - // If we haven't added any new fields or methods to what we
51.106 - // inherited, then we can share the parent's maps.
51.107 - if (supInjector != null) {
51.108 - if (fields.equals(supInjector.fields))
51.109 - fields = supInjector.fields;
51.110 - if (methods.equals(supInjector.methods))
51.111 - methods = supInjector.methods;
51.112 - }
51.113 - }
51.114 -
51.115 - boolean injects(Class<?> c) {
51.116 - return (fields.get(c) != null || methods.get(c) != null);
51.117 - }
51.118 -
51.119 - <T> void inject(Object instance, Class<T> type, T resource)
51.120 - throws Exception {
51.121 - List<Field> fs = fields.get(type);
51.122 - if (fs != null) {
51.123 - for (Field f : fs)
51.124 - f.set(instance, resource);
51.125 - }
51.126 - List<Method> ms = methods.get(type);
51.127 - if (ms != null) {
51.128 - for (Method m : ms) {
51.129 - try {
51.130 - m.invoke(instance, resource);
51.131 - } catch (InvocationTargetException e) {
51.132 - Throwable cause = e.getCause();
51.133 - if (cause instanceof Error)
51.134 - throw (Error) cause;
51.135 - else
51.136 - throw (Exception) cause;
51.137 - }
51.138 - }
51.139 - }
51.140 - }
51.141 -
51.142 - private void eliminateOverriddenMethods() {
51.143 - /* Covariant overriding is unlikely, but it is possible that the
51.144 - * parent has a @Resource method that we override with another
51.145 - * @Resource method. We don't want to invoke both methods,
51.146 - * because polymorphism means we would actually invoke the same
51.147 - * method twice.
51.148 - */
51.149 - for (Map.Entry<Class<?>, List<Method>> entry : methods.entrySet()) {
51.150 - List<Method> list = entry.getValue();
51.151 - list = MBeanAnalyzer.eliminateCovariantMethods(list);
51.152 - entry.setValue(list);
51.153 - }
51.154 - }
51.155 -
51.156 - /*
51.157 - * Find Fields or Methods within the given Class that we can inject
51.158 - * resource references into. Suppose we want to know if a Field can get
51.159 - * a reference to an ObjectName. We'll accept fields like this:
51.160 - *
51.161 - * @Resource
51.162 - * private transient ObjectName name;
51.163 - *
51.164 - * or like this:
51.165 - *
51.166 - * @Resource(type = ObjectName.class)
51.167 - * private transient Object name;
51.168 - *
51.169 - * but not like this:
51.170 - *
51.171 - * @Resource
51.172 - * private transient Object name;
51.173 - *
51.174 - * (Plain @Resource is equivalent to @Resource(type = Object.class).)
51.175 - *
51.176 - * We don't want to inject into everything that might possibly accept
51.177 - * an ObjectName reference, because examples like the last one above
51.178 - * could also accept an MBeanServer reference or any other sort of
51.179 - * reference.
51.180 - *
51.181 - * So we accept a Field if it has a @Resource annotation and either
51.182 - * (a) its type is exactly ObjectName and its @Resource type is
51.183 - * compatible with ObjectName (e.g. it is Object); or
51.184 - * (b) its type is compatible with ObjectName and its @Resource type
51.185 - * is exactly ObjectName. Fields that meet these criteria will not
51.186 - * meet the same criteria with respect to other types such as MBeanServer.
51.187 - *
51.188 - * The same logic applies mutatis mutandis to Methods such as this:
51.189 - *
51.190 - * @Resource
51.191 - * private void setObjectName1(ObjectName name)
51.192 - * @Resource(type = Object.class)
51.193 - * private void setObjectName2(Object name)
51.194 - */
51.195 - private void addMembers(final Class<?> c)
51.196 - throws NotCompliantMBeanException {
51.197 - AccessibleObject[][] memberArrays =
51.198 - AccessController.doPrivileged(
51.199 - new PrivilegedAction<AccessibleObject[][]>() {
51.200 - public AccessibleObject[][] run() {
51.201 - return new AccessibleObject[][] {
51.202 - c.getDeclaredFields(), c.getDeclaredMethods()
51.203 - };
51.204 - }
51.205 - });
51.206 - for (AccessibleObject[] members : memberArrays) {
51.207 - for (final AccessibleObject member : members) {
51.208 - Resource res = member.getAnnotation(Resource.class);
51.209 - if (res == null)
51.210 - continue;
51.211 -
51.212 - final Field field;
51.213 - final Method method;
51.214 - final Class<?> memberType;
51.215 - final int modifiers;
51.216 - if (member instanceof Field) {
51.217 - field = (Field) member;
51.218 - memberType = field.getType();
51.219 - modifiers = field.getModifiers();
51.220 - method = null;
51.221 - } else {
51.222 - field = null;
51.223 - method = (Method) member;
51.224 - Class<?>[] paramTypes = method.getParameterTypes();
51.225 - if (paramTypes.length != 1) {
51.226 - throw new NotCompliantMBeanException(
51.227 - "@Resource method must have exactly 1 " +
51.228 - "parameter: " + method);
51.229 - }
51.230 - if (method.getReturnType() != void.class) {
51.231 - throw new NotCompliantMBeanException(
51.232 - "@Resource method must return void: " +
51.233 - method);
51.234 - }
51.235 - memberType = paramTypes[0];
51.236 - modifiers = method.getModifiers();
51.237 - }
51.238 -
51.239 - if (Modifier.isStatic(modifiers)) {
51.240 - throw new NotCompliantMBeanException(
51.241 - "@Resource method or field cannot be static: " +
51.242 - member);
51.243 - }
51.244 -
51.245 - for (Class<?> injectedClass : injectedClasses) {
51.246 - Class<?>[] types = {memberType, res.type()};
51.247 - boolean accept = false;
51.248 - for (int i = 0; i < 2; i++) {
51.249 - if (types[i] == injectedClass &&
51.250 - types[1 - i].isAssignableFrom(injectedClass)) {
51.251 - accept = true;
51.252 - break;
51.253 - }
51.254 - }
51.255 - if (accept) {
51.256 - AccessController.doPrivileged(new PrivilegedAction<Void>() {
51.257 - public Void run() {
51.258 - member.setAccessible(true);
51.259 - return null;
51.260 - }
51.261 - });
51.262 - addToMap(fields, injectedClass, field);
51.263 - addToMap(methods, injectedClass, method);
51.264 - }
51.265 - }
51.266 - }
51.267 - }
51.268 - }
51.269 -
51.270 - private static <K, V> void addToMap(Map<K, List<V>> map, K key, V value) {
51.271 - if (value == null)
51.272 - return;
51.273 - List<V> list = map.get(key);
51.274 - if (list == null)
51.275 - list = Collections.singletonList(value);
51.276 - else {
51.277 - if (list.size() == 1)
51.278 - list = new ArrayList<V>(list);
51.279 - list.add(value);
51.280 - }
51.281 - map.put(key, list);
51.282 - }
51.283 - }
51.284 -
51.285 - private static synchronized ClassInjector injectorForClass(Class<?> c)
51.286 - throws NotCompliantMBeanException {
51.287 - WeakReference<ClassInjector> wr = injectorMap.get(c);
51.288 - ClassInjector ci = (wr == null) ? null : wr.get();
51.289 - if (ci == null) {
51.290 - ci = new ClassInjector(c);
51.291 - injectorMap.put(c, new WeakReference<ClassInjector>(ci));
51.292 - }
51.293 - return ci;
51.294 - }
51.295 -
51.296 - private static Map<Class<?>, WeakReference<ClassInjector>> injectorMap =
51.297 - new WeakHashMap<Class<?>, WeakReference<ClassInjector>>();
51.298 -}
52.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java Mon Nov 23 10:04:47 2009 +0000
52.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanInstantiator.java Wed Nov 25 11:08:25 2009 -0800
52.3 @@ -614,15 +614,6 @@
52.4 }
52.5
52.6 /**
52.7 - * Returns the class of a primitive type.
52.8 - * @param name The type for which we the associated class.
52.9 - * @return the class, or null if name is not primitive.
52.10 - */
52.11 - public static Class<?> primitiveType(String name) {
52.12 - return primitiveClasses.get(name);
52.13 - }
52.14 -
52.15 - /**
52.16 * Load a class with the specified loader, or with this object
52.17 * class loader if the specified loader is null.
52.18 **/
53.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java Mon Nov 23 10:04:47 2009 +0000
53.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanIntrospector.java Wed Nov 25 11:08:25 2009 -0800
53.3 @@ -36,28 +36,20 @@
53.4 import java.lang.reflect.Type;
53.5 import java.util.Arrays;
53.6 import java.util.List;
53.7 -import java.util.Map;
53.8 import java.util.WeakHashMap;
53.9 -import javax.management.Description;
53.10
53.11 import javax.management.Descriptor;
53.12 import javax.management.ImmutableDescriptor;
53.13 import javax.management.IntrospectionException;
53.14 import javax.management.InvalidAttributeValueException;
53.15 -import javax.management.MBean;
53.16 import javax.management.MBeanAttributeInfo;
53.17 import javax.management.MBeanConstructorInfo;
53.18 import javax.management.MBeanException;
53.19 import javax.management.MBeanInfo;
53.20 import javax.management.MBeanNotificationInfo;
53.21 import javax.management.MBeanOperationInfo;
53.22 -import javax.management.MXBean;
53.23 -import javax.management.ManagedAttribute;
53.24 -import javax.management.ManagedOperation;
53.25 import javax.management.NotCompliantMBeanException;
53.26 import javax.management.NotificationBroadcaster;
53.27 -import javax.management.NotificationInfo;
53.28 -import javax.management.NotificationInfos;
53.29 import javax.management.ReflectionException;
53.30
53.31 /**
53.32 @@ -79,7 +71,7 @@
53.33 * ancestor with ConvertingMethod. But that would mean an extra object
53.34 * for every Method in every Standard MBean interface.
53.35 */
53.36 -public abstract class MBeanIntrospector<M> {
53.37 +abstract class MBeanIntrospector<M> {
53.38 static final class PerInterfaceMap<M>
53.39 extends WeakHashMap<Class<?>, WeakReference<PerInterface<M>>> {}
53.40
53.41 @@ -159,27 +151,7 @@
53.42 * may be null.
53.43 */
53.44 abstract MBeanAttributeInfo getMBeanAttributeInfo(String attributeName,
53.45 - M getter, M setter) throws IntrospectionException;
53.46 -
53.47 - final String getAttributeDescription(
53.48 - String attributeName, String defaultDescription,
53.49 - Method getter, Method setter) throws IntrospectionException {
53.50 - String g = Introspector.descriptionForElement(getter);
53.51 - String s = Introspector.descriptionForElement(setter);
53.52 - if (g == null) {
53.53 - if (s == null)
53.54 - return defaultDescription;
53.55 - else
53.56 - return s;
53.57 - } else if (s == null || g.equals(s)) {
53.58 - return g;
53.59 - } else {
53.60 - throw new IntrospectionException(
53.61 - "Inconsistent @Description on getter and setter for " +
53.62 - "attribute " + attributeName);
53.63 - }
53.64 - }
53.65 -
53.66 + M getter, M setter);
53.67 /**
53.68 * Construct an MBeanOperationInfo for the given operation based on
53.69 * the M it was derived from.
53.70 @@ -201,36 +173,10 @@
53.71 abstract Descriptor getMBeanDescriptor(Class<?> resourceClass);
53.72
53.73 /**
53.74 - * Get any additional Descriptor entries for this introspector instance.
53.75 - * If there is a non-default MXBeanMappingFactory, it will appear in
53.76 - * this Descriptor.
53.77 - * @return Additional Descriptor entries, or an empty Descriptor if none.
53.78 - */
53.79 - Descriptor getSpecificMBeanDescriptor() {
53.80 - return ImmutableDescriptor.EMPTY_DESCRIPTOR;
53.81 - }
53.82 -
53.83 - void checkCompliance(Class<?> mbeanType) throws NotCompliantMBeanException {
53.84 - if (!mbeanType.isInterface() &&
53.85 - !mbeanType.isAnnotationPresent(MBean.class) &&
53.86 - !Introspector.hasMXBeanAnnotation(mbeanType)) {
53.87 - throw new NotCompliantMBeanException("Not an interface and " +
53.88 - "does not have @" + MBean.class.getSimpleName() +
53.89 - " or @" + MXBean.class.getSimpleName() + " annotation: " +
53.90 - mbeanType.getName());
53.91 - }
53.92 - }
53.93 -
53.94 - /**
53.95 * Get the methods to be analyzed to build the MBean interface.
53.96 */
53.97 List<Method> getMethods(final Class<?> mbeanType) throws Exception {
53.98 - if (mbeanType.isInterface())
53.99 - return Arrays.asList(mbeanType.getMethods());
53.100 -
53.101 - final List<Method> methods = newList();
53.102 - getAnnotatedMethods(mbeanType, methods);
53.103 - return methods;
53.104 + return Arrays.asList(mbeanType.getMethods());
53.105 }
53.106
53.107 final PerInterface<M> getPerInterface(Class<?> mbeanInterface)
53.108 @@ -265,14 +211,11 @@
53.109 * the MBeanInfo's Descriptor.
53.110 */
53.111 private MBeanInfo makeInterfaceMBeanInfo(Class<?> mbeanInterface,
53.112 - MBeanAnalyzer<M> analyzer) throws IntrospectionException {
53.113 + MBeanAnalyzer<M> analyzer) {
53.114 final MBeanInfoMaker maker = new MBeanInfoMaker();
53.115 analyzer.visit(maker);
53.116 - final String defaultDescription =
53.117 + final String description =
53.118 "Information on the management interface of the MBean";
53.119 - String description = Introspector.descriptionForElement(mbeanInterface);
53.120 - if (description == null)
53.121 - description = defaultDescription;
53.122 return maker.makeMBeanInfo(mbeanInterface, description);
53.123 }
53.124
53.125 @@ -370,11 +313,11 @@
53.126
53.127 /** A visitor that constructs the per-interface MBeanInfo. */
53.128 private class MBeanInfoMaker
53.129 - implements MBeanAnalyzer.MBeanVisitor<M, IntrospectionException> {
53.130 + implements MBeanAnalyzer.MBeanVisitor<M> {
53.131
53.132 public void visitAttribute(String attributeName,
53.133 M getter,
53.134 - M setter) throws IntrospectionException {
53.135 + M setter) {
53.136 MBeanAttributeInfo mbai =
53.137 getMBeanAttributeInfo(attributeName, getter, setter);
53.138
53.139 @@ -403,7 +346,7 @@
53.140 new ImmutableDescriptor(interfaceClassName);
53.141 final Descriptor mbeanDescriptor = getBasicMBeanDescriptor();
53.142 final Descriptor annotatedDescriptor =
53.143 - Introspector.descriptorForElement(mbeanInterface, false);
53.144 + Introspector.descriptorForElement(mbeanInterface);
53.145 final Descriptor descriptor =
53.146 DescriptorCache.getInstance().union(
53.147 classNameDescriptor,
53.148 @@ -442,32 +385,20 @@
53.149 * Return the MBeanInfo for the given resource, based on the given
53.150 * per-interface data.
53.151 */
53.152 - final MBeanInfo getMBeanInfo(Object resource, PerInterface<M> perInterface)
53.153 - throws NotCompliantMBeanException {
53.154 + final MBeanInfo getMBeanInfo(Object resource, PerInterface<M> perInterface) {
53.155 MBeanInfo mbi =
53.156 getClassMBeanInfo(resource.getClass(), perInterface);
53.157 - MBeanNotificationInfo[] notifs;
53.158 - try {
53.159 - notifs = findNotifications(resource);
53.160 - } catch (RuntimeException e) {
53.161 - NotCompliantMBeanException x =
53.162 - new NotCompliantMBeanException(e.getMessage());
53.163 - x.initCause(e);
53.164 - throw x;
53.165 - }
53.166 - Descriptor d = getSpecificMBeanDescriptor();
53.167 - boolean anyNotifs = (notifs != null && notifs.length > 0);
53.168 - if (!anyNotifs && ImmutableDescriptor.EMPTY_DESCRIPTOR.equals(d))
53.169 + MBeanNotificationInfo[] notifs = findNotifications(resource);
53.170 + if (notifs == null || notifs.length == 0)
53.171 return mbi;
53.172 else {
53.173 - d = ImmutableDescriptor.union(d, mbi.getDescriptor());
53.174 return new MBeanInfo(mbi.getClassName(),
53.175 mbi.getDescription(),
53.176 mbi.getAttributes(),
53.177 mbi.getConstructors(),
53.178 mbi.getOperations(),
53.179 notifs,
53.180 - d);
53.181 + mbi.getDescriptor());
53.182 }
53.183 }
53.184
53.185 @@ -507,145 +438,29 @@
53.186 }
53.187 }
53.188
53.189 - /*
53.190 - * Add to "methods" every public method that has the @ManagedAttribute
53.191 - * or @ManagedOperation annotation, in the given class or any of
53.192 - * its superclasses or superinterfaces.
53.193 - *
53.194 - * We always add superclass or superinterface methods first, so that
53.195 - * the stable sort used by eliminateCovariantMethods will put the
53.196 - * method from the most-derived class last. This means that we will
53.197 - * see the version of the @ManagedAttribute (or ...Operation) annotation
53.198 - * from that method, which might have a different description or whatever.
53.199 - */
53.200 - public static void getAnnotatedMethods(Class<?> c, List<Method> methods)
53.201 - throws Exception {
53.202 - Class<?> sup = c.getSuperclass();
53.203 - if (sup != null)
53.204 - getAnnotatedMethods(sup, methods);
53.205 - Class<?>[] intfs = c.getInterfaces();
53.206 - for (Class<?> intf : intfs)
53.207 - getAnnotatedMethods(intf, methods);
53.208 - for (Method m : c.getMethods()) {
53.209 - // We are careful not to add m if it is inherited from a parent
53.210 - // class or interface, because duplicate methods lead to nasty
53.211 - // behaviour in eliminateCovariantMethods.
53.212 - if (m.getDeclaringClass() == c &&
53.213 - (m.isAnnotationPresent(ManagedAttribute.class) ||
53.214 - m.isAnnotationPresent(ManagedOperation.class)))
53.215 - methods.add(m);
53.216 + static MBeanNotificationInfo[] findNotifications(Object moi) {
53.217 + if (!(moi instanceof NotificationBroadcaster))
53.218 + return null;
53.219 + MBeanNotificationInfo[] mbn =
53.220 + ((NotificationBroadcaster) moi).getNotificationInfo();
53.221 + if (mbn == null)
53.222 + return null;
53.223 + MBeanNotificationInfo[] result =
53.224 + new MBeanNotificationInfo[mbn.length];
53.225 + for (int i = 0; i < mbn.length; i++) {
53.226 + MBeanNotificationInfo ni = mbn[i];
53.227 + if (ni.getClass() != MBeanNotificationInfo.class)
53.228 + ni = (MBeanNotificationInfo) ni.clone();
53.229 + result[i] = ni;
53.230 }
53.231 - }
53.232 -
53.233 - /*
53.234 - * Return the array of MBeanNotificationInfo for the given MBean object.
53.235 - * If the object implements NotificationBroadcaster and its
53.236 - * getNotificationInfo() method returns a non-empty array, then that
53.237 - * is the result. Otherwise, if the object has a @NotificationInfo
53.238 - * or @NotificationInfos annotation, then its contents form the result.
53.239 - * Otherwise, the result is null.
53.240 - */
53.241 - static MBeanNotificationInfo[] findNotifications(Object moi) {
53.242 - if (moi instanceof NotificationBroadcaster) {
53.243 - MBeanNotificationInfo[] mbn =
53.244 - ((NotificationBroadcaster) moi).getNotificationInfo();
53.245 - if (mbn != null && mbn.length > 0) {
53.246 - MBeanNotificationInfo[] result =
53.247 - new MBeanNotificationInfo[mbn.length];
53.248 - for (int i = 0; i < mbn.length; i++) {
53.249 - MBeanNotificationInfo ni = mbn[i];
53.250 - if (ni.getClass() != MBeanNotificationInfo.class)
53.251 - ni = (MBeanNotificationInfo) ni.clone();
53.252 - result[i] = ni;
53.253 - }
53.254 - return result;
53.255 - }
53.256 - } else {
53.257 - try {
53.258 - if (!MBeanInjector.injectsSendNotification(moi))
53.259 - return null;
53.260 - } catch (NotCompliantMBeanException e) {
53.261 - throw new RuntimeException(e);
53.262 - }
53.263 - }
53.264 - return findNotificationsFromAnnotations(moi.getClass());
53.265 - }
53.266 -
53.267 - public static MBeanNotificationInfo[] findNotificationsFromAnnotations(
53.268 - Class<?> mbeanClass) {
53.269 - Class<?> c = getAnnotatedNotificationInfoClass(mbeanClass);
53.270 - if (c == null)
53.271 - return null;
53.272 - NotificationInfo ni = c.getAnnotation(NotificationInfo.class);
53.273 - NotificationInfos nis = c.getAnnotation(NotificationInfos.class);
53.274 - List<NotificationInfo> list = newList();
53.275 - if (ni != null)
53.276 - list.add(ni);
53.277 - if (nis != null)
53.278 - list.addAll(Arrays.asList(nis.value()));
53.279 - if (list.isEmpty())
53.280 - return null;
53.281 - List<MBeanNotificationInfo> mbnis = newList();
53.282 - for (NotificationInfo x : list) {
53.283 - // The Descriptor includes any fields explicitly specified by
53.284 - // x.descriptorFields(), plus any fields from the contained
53.285 - // @Description annotation.
53.286 - Descriptor d = new ImmutableDescriptor(x.descriptorFields());
53.287 - d = ImmutableDescriptor.union(
53.288 - d, Introspector.descriptorForAnnotation(x.description()));
53.289 - MBeanNotificationInfo mbni = new MBeanNotificationInfo(
53.290 - x.types(), x.notificationClass().getName(),
53.291 - x.description().value(), d);
53.292 - mbnis.add(mbni);
53.293 - }
53.294 - return mbnis.toArray(new MBeanNotificationInfo[mbnis.size()]);
53.295 - }
53.296 -
53.297 - private static final Map<Class<?>, WeakReference<Class<?>>>
53.298 - annotatedNotificationInfoClasses = newWeakHashMap();
53.299 -
53.300 - private static Class<?> getAnnotatedNotificationInfoClass(Class<?> baseClass) {
53.301 - synchronized (annotatedNotificationInfoClasses) {
53.302 - WeakReference<Class<?>> wr =
53.303 - annotatedNotificationInfoClasses.get(baseClass);
53.304 - if (wr != null)
53.305 - return wr.get();
53.306 - Class<?> c = null;
53.307 - if (baseClass.isAnnotationPresent(NotificationInfo.class) ||
53.308 - baseClass.isAnnotationPresent(NotificationInfos.class)) {
53.309 - c = baseClass;
53.310 - } else {
53.311 - Class<?>[] intfs = baseClass.getInterfaces();
53.312 - for (Class<?> intf : intfs) {
53.313 - Class<?> c1 = getAnnotatedNotificationInfoClass(intf);
53.314 - if (c1 != null) {
53.315 - if (c != null) {
53.316 - throw new IllegalArgumentException(
53.317 - "Class " + baseClass.getName() + " inherits " +
53.318 - "@NotificationInfo(s) from both " +
53.319 - c.getName() + " and " + c1.getName());
53.320 - }
53.321 - c = c1;
53.322 - }
53.323 - }
53.324 - }
53.325 - // Record the result of the search. If no @NotificationInfo(s)
53.326 - // were found, c is null, and we store a WeakReference(null).
53.327 - // This prevents us from having to search again and fail again.
53.328 - annotatedNotificationInfoClasses.put(baseClass,
53.329 - new WeakReference<Class<?>>(c));
53.330 - return c;
53.331 - }
53.332 + return result;
53.333 }
53.334
53.335 private static MBeanConstructorInfo[] findConstructors(Class<?> c) {
53.336 Constructor<?>[] cons = c.getConstructors();
53.337 MBeanConstructorInfo[] mbc = new MBeanConstructorInfo[cons.length];
53.338 for (int i = 0; i < cons.length; i++) {
53.339 - String descr = "Public constructor of the MBean";
53.340 - Description d = cons[i].getAnnotation(Description.class);
53.341 - if (d != null)
53.342 - descr = d.value();
53.343 + final String descr = "Public constructor of the MBean";
53.344 mbc[i] = new MBeanConstructorInfo(descr, cons[i]);
53.345 }
53.346 return mbc;
54.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java Mon Nov 23 10:04:47 2009 +0000
54.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MBeanSupport.java Wed Nov 25 11:08:25 2009 -0800
54.3 @@ -37,7 +37,7 @@
54.4 import javax.management.NotCompliantMBeanException;
54.5 import javax.management.ObjectName;
54.6 import javax.management.ReflectionException;
54.7 -import javax.management.openmbean.MXBeanMappingFactory;
54.8 +import com.sun.jmx.mbeanserver.MXBeanMappingFactory;
54.9
54.10 /**
54.11 * Base class for MBeans. There is one instance of this class for
54.12 @@ -121,8 +121,7 @@
54.13 public abstract class MBeanSupport<M>
54.14 implements DynamicMBean2, MBeanRegistration {
54.15
54.16 - <T> MBeanSupport(T resource, Class<T> mbeanInterfaceType,
54.17 - MXBeanMappingFactory mappingFactory)
54.18 + <T> MBeanSupport(T resource, Class<T> mbeanInterfaceType)
54.19 throws NotCompliantMBeanException {
54.20 if (mbeanInterfaceType == null)
54.21 throw new NotCompliantMBeanException("Null MBean interface");
54.22 @@ -133,14 +132,13 @@
54.23 throw new NotCompliantMBeanException(msg);
54.24 }
54.25 this.resource = resource;
54.26 - MBeanIntrospector<M> introspector = getMBeanIntrospector(mappingFactory);
54.27 + MBeanIntrospector<M> introspector = getMBeanIntrospector();
54.28 this.perInterface = introspector.getPerInterface(mbeanInterfaceType);
54.29 this.mbeanInfo = introspector.getMBeanInfo(resource, perInterface);
54.30 }
54.31
54.32 /** Return the appropriate introspector for this type of MBean. */
54.33 - abstract MBeanIntrospector<M>
54.34 - getMBeanIntrospector(MXBeanMappingFactory mappingFactory);
54.35 + abstract MBeanIntrospector<M> getMBeanIntrospector();
54.36
54.37 /**
54.38 * Return a cookie for this MBean. This cookie will be passed to
54.39 @@ -262,14 +260,10 @@
54.40 return resource.getClass().getName();
54.41 }
54.42
54.43 - public final Object getWrappedObject() {
54.44 + public final Object getResource() {
54.45 return resource;
54.46 }
54.47
54.48 - public final ClassLoader getWrappedClassLoader() {
54.49 - return resource.getClass().getClassLoader();
54.50 - }
54.51 -
54.52 public final Class<?> getMBeanInterface() {
54.53 return perInterface.getMBeanInterface();
54.54 }
55.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java Mon Nov 23 10:04:47 2009 +0000
55.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanIntrospector.java Wed Nov 25 11:08:25 2009 -0800
55.3 @@ -28,26 +28,18 @@
55.4 import com.sun.jmx.mbeanserver.MBeanIntrospector.MBeanInfoMap;
55.5 import com.sun.jmx.mbeanserver.MBeanIntrospector.PerInterfaceMap;
55.6 import java.lang.annotation.Annotation;
55.7 -import java.lang.ref.WeakReference;
55.8 import java.lang.reflect.GenericArrayType;
55.9 import java.lang.reflect.InvocationTargetException;
55.10 import java.lang.reflect.Method;
55.11 import java.lang.reflect.ParameterizedType;
55.12 import java.lang.reflect.Type;
55.13 -import java.util.Map;
55.14 -import java.util.WeakHashMap;
55.15 -import javax.management.Description;
55.16 import javax.management.Descriptor;
55.17 import javax.management.ImmutableDescriptor;
55.18 -import javax.management.IntrospectionException;
55.19 -import javax.management.JMX;
55.20 import javax.management.MBeanAttributeInfo;
55.21 import javax.management.MBeanException;
55.22 import javax.management.MBeanOperationInfo;
55.23 import javax.management.MBeanParameterInfo;
55.24 -import javax.management.ManagedOperation;
55.25 import javax.management.NotCompliantMBeanException;
55.26 -import javax.management.openmbean.MXBeanMappingFactory;
55.27 import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
55.28 import javax.management.openmbean.OpenMBeanOperationInfoSupport;
55.29 import javax.management.openmbean.OpenMBeanParameterInfo;
55.30 @@ -60,36 +52,10 @@
55.31 * @since 1.6
55.32 */
55.33 class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
55.34 - /* We keep one MXBeanIntrospector per MXBeanMappingFactory, since the results
55.35 - * of the introspection depend on the factory. The MXBeanIntrospector
55.36 - * has a reference back to the factory, so we wrap it in a WeakReference.
55.37 - * It will be strongly referenced by any MXBeanSupport instances using it;
55.38 - * if there are none then it is OK to gc it.
55.39 - */
55.40 - private static final
55.41 - Map<MXBeanMappingFactory, WeakReference<MXBeanIntrospector>> map =
55.42 - new WeakHashMap<MXBeanMappingFactory, WeakReference<MXBeanIntrospector>>();
55.43 + private static final MXBeanIntrospector instance = new MXBeanIntrospector();
55.44
55.45 - static MXBeanIntrospector getInstance(MXBeanMappingFactory factory) {
55.46 - if (factory == null)
55.47 - factory = MXBeanMappingFactory.DEFAULT;
55.48 - synchronized (map) {
55.49 - MXBeanIntrospector intro;
55.50 - WeakReference<MXBeanIntrospector> wr = map.get(factory);
55.51 - if (wr != null) {
55.52 - intro = wr.get();
55.53 - if (intro != null)
55.54 - return intro;
55.55 - }
55.56 - intro = new MXBeanIntrospector(factory);
55.57 - wr = new WeakReference<MXBeanIntrospector>(intro);
55.58 - map.put(factory, wr);
55.59 - return intro;
55.60 - }
55.61 - }
55.62 -
55.63 - private MXBeanIntrospector(MXBeanMappingFactory factory) {
55.64 - this.mappingFactory = factory;
55.65 + static MXBeanIntrospector getInstance() {
55.66 + return instance;
55.67 }
55.68
55.69 @Override
55.70 @@ -115,7 +81,7 @@
55.71
55.72 @Override
55.73 ConvertingMethod mFrom(Method m) {
55.74 - return ConvertingMethod.from(m, mappingFactory);
55.75 + return ConvertingMethod.from(m);
55.76 }
55.77
55.78 @Override
55.79 @@ -176,17 +142,13 @@
55.80
55.81 @Override
55.82 MBeanAttributeInfo getMBeanAttributeInfo(String attributeName,
55.83 - ConvertingMethod getter, ConvertingMethod setter)
55.84 - throws IntrospectionException {
55.85 + ConvertingMethod getter, ConvertingMethod setter) {
55.86
55.87 final boolean isReadable = (getter != null);
55.88 final boolean isWritable = (setter != null);
55.89 final boolean isIs = isReadable && getName(getter).startsWith("is");
55.90
55.91 - final String description = getAttributeDescription(
55.92 - attributeName, attributeName,
55.93 - getter == null ? null : getter.getMethod(),
55.94 - setter == null ? null : setter.getMethod());
55.95 + final String description = attributeName;
55.96
55.97 final OpenType<?> openType;
55.98 final Type originalType;
55.99 @@ -235,17 +197,13 @@
55.100 MBeanOperationInfo getMBeanOperationInfo(String operationName,
55.101 ConvertingMethod operation) {
55.102 final Method method = operation.getMethod();
55.103 - String description = operationName;
55.104 + final String description = operationName;
55.105 /* Ideally this would be an empty string, but
55.106 - OMBOperationInfo constructor forbids that. */
55.107 - Description d = method.getAnnotation(Description.class);
55.108 - if (d != null)
55.109 - description = d.value();
55.110 + OMBOperationInfo constructor forbids that. Also, we
55.111 + could consult an annotation to get a useful
55.112 + description. */
55.113
55.114 - int impact = MBeanOperationInfo.UNKNOWN;
55.115 - ManagedOperation annot = method.getAnnotation(ManagedOperation.class);
55.116 - if (annot != null)
55.117 - impact = annot.impact().getCode();
55.118 + final int impact = MBeanOperationInfo.UNKNOWN;
55.119
55.120 final OpenType<?> returnType = operation.getOpenReturnType();
55.121 final Type originalReturnType = operation.getGenericReturnType();
55.122 @@ -257,15 +215,8 @@
55.123 boolean openParameterTypes = true;
55.124 Annotation[][] annots = method.getParameterAnnotations();
55.125 for (int i = 0; i < paramTypes.length; i++) {
55.126 - String paramName = Introspector.nameForParameter(annots[i]);
55.127 - if (paramName == null)
55.128 - paramName = "p" + i;
55.129 -
55.130 - String paramDescription =
55.131 - Introspector.descriptionForParameter(annots[i]);
55.132 - if (paramDescription == null)
55.133 - paramDescription = paramName;
55.134 -
55.135 + final String paramName = "p" + i;
55.136 + final String paramDescription = paramName;
55.137 final OpenType<?> openType = paramTypes[i];
55.138 final Type originalType = originalParamTypes[i];
55.139 Descriptor descriptor =
55.140 @@ -292,7 +243,7 @@
55.141 Descriptor descriptor =
55.142 typeDescriptor(returnType, originalReturnType);
55.143 descriptor = ImmutableDescriptor.union(descriptor,
55.144 - Introspector.descriptorForElement(method, false));
55.145 + Introspector.descriptorForElement(method));
55.146 final MBeanOperationInfo oi;
55.147 if (openReturnType && openParameterTypes) {
55.148 /* If the return value and all the parameters can be faithfully
55.149 @@ -343,17 +294,6 @@
55.150 return ImmutableDescriptor.EMPTY_DESCRIPTOR;
55.151 }
55.152
55.153 - @Override
55.154 - Descriptor getSpecificMBeanDescriptor() {
55.155 - if (mappingFactory == MXBeanMappingFactory.DEFAULT)
55.156 - return ImmutableDescriptor.EMPTY_DESCRIPTOR;
55.157 - else {
55.158 - return new ImmutableDescriptor(
55.159 - JMX.MXBEAN_MAPPING_FACTORY_CLASS_FIELD + "=" +
55.160 - mappingFactory.getClass().getName());
55.161 - }
55.162 - }
55.163 -
55.164 private static Descriptor typeDescriptor(OpenType<?> openType,
55.165 Type originalType) {
55.166 return new ImmutableDescriptor(
55.167 @@ -421,7 +361,5 @@
55.168 private final PerInterfaceMap<ConvertingMethod>
55.169 perInterfaceMap = new PerInterfaceMap<ConvertingMethod>();
55.170
55.171 - private final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap();
55.172 -
55.173 - private final MXBeanMappingFactory mappingFactory;
55.174 + private static final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap();
55.175 }
56.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java Mon Nov 23 10:04:47 2009 +0000
56.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanLookup.java Wed Nov 25 11:08:25 2009 -0800
56.3 @@ -25,8 +25,6 @@
56.4
56.5 package com.sun.jmx.mbeanserver;
56.6
56.7 -import com.sun.jmx.remote.util.EnvHelp;
56.8 -import java.io.InvalidObjectException;
56.9 import static com.sun.jmx.mbeanserver.Util.*;
56.10 import java.util.Map;
56.11 import java.lang.ref.WeakReference;
56.12 @@ -85,181 +83,87 @@
56.13 *
56.14 * From the above, it is clear that the logic for getX on an MXBean is
56.15 * the same as for setX on a proxy, and vice versa.
56.16 - *
56.17 - * The above describes the logic for "plain" MXBeanLookup, represented
56.18 - * by MXBeanLookup.Plain. When namespaces enter the picture, we see
56.19 - * MXBeanLookup.Prefix. Here, the idea is that the name of the ModuleMXBean
56.20 - * might be a//m:m=m. In this case, we don't accept a reference to
56.21 - * an MXBean object, since that would require different namespaces to know
56.22 - * each others' objects. We only accept proxies. Suppose you have a proxy
56.23 - * for a//m:m=m, call it moduleProxy, and you call
56.24 - * moduleProxy.setProduct(productProxy). Then if productProxy is for
56.25 - * a//p:p=p we should convert this to just p:p=p. If productProxy is for
56.26 - * a//b//p:p=p we should convert it to b//p:p=p. Conversely, if getProduct
56.27 - * returns an ObjectName like b//p:p=p then we should convert it into a proxy
56.28 - * for a//b//p:p=p.
56.29 */
56.30 -public abstract class MXBeanLookup {
56.31 +public class MXBeanLookup {
56.32 private MXBeanLookup(MBeanServerConnection mbsc) {
56.33 this.mbsc = mbsc;
56.34 }
56.35
56.36 - static MXBeanLookup lookupFor(MBeanServerConnection mbsc, String prefix) {
56.37 - if (prefix == null)
56.38 - return Plain.lookupFor(mbsc);
56.39 - else
56.40 - return new Prefix(mbsc, prefix);
56.41 - }
56.42 -
56.43 - abstract <T> T objectNameToMXBean(ObjectName name, Class<T> type)
56.44 - throws InvalidObjectException;
56.45 -
56.46 - abstract ObjectName mxbeanToObjectName(Object mxbean)
56.47 - throws OpenDataException;
56.48 -
56.49 - static class Plain extends MXBeanLookup {
56.50 - Plain(MBeanServerConnection mbsc) {
56.51 - super(mbsc);
56.52 - }
56.53 -
56.54 - static Plain lookupFor(MBeanServerConnection mbsc) {
56.55 - synchronized (mbscToLookup) {
56.56 - WeakReference<Plain> weakLookup = mbscToLookup.get(mbsc);
56.57 - Plain lookup = (weakLookup == null) ? null : weakLookup.get();
56.58 - if (lookup == null) {
56.59 - lookup = new Plain(mbsc);
56.60 - mbscToLookup.put(mbsc, new WeakReference<Plain>(lookup));
56.61 - }
56.62 - return lookup;
56.63 + static MXBeanLookup lookupFor(MBeanServerConnection mbsc) {
56.64 + synchronized (mbscToLookup) {
56.65 + WeakReference<MXBeanLookup> weakLookup = mbscToLookup.get(mbsc);
56.66 + MXBeanLookup lookup = (weakLookup == null) ? null : weakLookup.get();
56.67 + if (lookup == null) {
56.68 + lookup = new MXBeanLookup(mbsc);
56.69 + mbscToLookup.put(mbsc, new WeakReference<MXBeanLookup>(lookup));
56.70 }
56.71 - }
56.72 -
56.73 - @Override
56.74 - synchronized <T> T objectNameToMXBean(ObjectName name, Class<T> type) {
56.75 - WeakReference<Object> wr = objectNameToProxy.get(name);
56.76 - if (wr != null) {
56.77 - Object proxy = wr.get();
56.78 - if (type.isInstance(proxy))
56.79 - return type.cast(proxy);
56.80 - }
56.81 - T proxy = JMX.newMXBeanProxy(mbsc, name, type);
56.82 - objectNameToProxy.put(name, new WeakReference<Object>(proxy));
56.83 - return proxy;
56.84 - }
56.85 -
56.86 - @Override
56.87 - synchronized ObjectName mxbeanToObjectName(Object mxbean)
56.88 - throws OpenDataException {
56.89 - String wrong;
56.90 - if (mxbean instanceof Proxy) {
56.91 - InvocationHandler ih = Proxy.getInvocationHandler(mxbean);
56.92 - if (ih instanceof MBeanServerInvocationHandler) {
56.93 - MBeanServerInvocationHandler mbsih =
56.94 - (MBeanServerInvocationHandler) ih;
56.95 - if (mbsih.getMBeanServerConnection().equals(mbsc))
56.96 - return mbsih.getObjectName();
56.97 - else
56.98 - wrong = "proxy for a different MBeanServer";
56.99 - } else
56.100 - wrong = "not a JMX proxy";
56.101 - } else {
56.102 - ObjectName name = mxbeanToObjectName.get(mxbean);
56.103 - if (name != null)
56.104 - return name;
56.105 - wrong = "not an MXBean registered in this MBeanServer";
56.106 - }
56.107 - String s = (mxbean == null) ?
56.108 - "null" : "object of type " + mxbean.getClass().getName();
56.109 - throw new OpenDataException(
56.110 - "Could not convert " + s + " to an ObjectName: " + wrong);
56.111 - // Message will be strange if mxbean is null but it is not
56.112 - // supposed to be.
56.113 - }
56.114 -
56.115 - synchronized void addReference(ObjectName name, Object mxbean)
56.116 - throws InstanceAlreadyExistsException {
56.117 - ObjectName existing = mxbeanToObjectName.get(mxbean);
56.118 - if (existing != null) {
56.119 - String multiname = AccessController.doPrivileged(
56.120 - new GetPropertyAction("jmx.mxbean.multiname"));
56.121 - if (!"true".equalsIgnoreCase(multiname)) {
56.122 - throw new InstanceAlreadyExistsException(
56.123 - "MXBean already registered with name " + existing);
56.124 - }
56.125 - }
56.126 - mxbeanToObjectName.put(mxbean, name);
56.127 - }
56.128 -
56.129 - synchronized boolean removeReference(ObjectName name, Object mxbean) {
56.130 - if (name.equals(mxbeanToObjectName.get(mxbean))) {
56.131 - mxbeanToObjectName.remove(mxbean);
56.132 - return true;
56.133 - } else
56.134 - return false;
56.135 - /* removeReference can be called when the above condition fails,
56.136 - * notably if you try to register the same MXBean twice.
56.137 - */
56.138 - }
56.139 -
56.140 - private final WeakIdentityHashMap<Object, ObjectName>
56.141 - mxbeanToObjectName = WeakIdentityHashMap.make();
56.142 - private final Map<ObjectName, WeakReference<Object>>
56.143 - objectNameToProxy = newMap();
56.144 - private static WeakIdentityHashMap<MBeanServerConnection,
56.145 - WeakReference<Plain>>
56.146 - mbscToLookup = WeakIdentityHashMap.make();
56.147 - }
56.148 -
56.149 - private static class Prefix extends MXBeanLookup {
56.150 - private final String prefix;
56.151 -
56.152 - Prefix(MBeanServerConnection mbsc, String prefix) {
56.153 - super(mbsc);
56.154 - this.prefix = prefix;
56.155 - }
56.156 -
56.157 - @Override
56.158 - <T> T objectNameToMXBean(ObjectName name, Class<T> type)
56.159 - throws InvalidObjectException {
56.160 - String domain = prefix + name.getDomain();
56.161 - try {
56.162 - name = name.withDomain(domain);
56.163 - } catch (IllegalArgumentException e) {
56.164 - throw EnvHelp.initCause(
56.165 - new InvalidObjectException(e.getMessage()), e);
56.166 - }
56.167 - return JMX.newMXBeanProxy(mbsc, name, type);
56.168 - }
56.169 -
56.170 - @Override
56.171 - ObjectName mxbeanToObjectName(Object mxbean)
56.172 - throws OpenDataException {
56.173 - ObjectName name = proxyToObjectName(mxbean);
56.174 - String domain = name.getDomain();
56.175 - if (!domain.startsWith(prefix)) {
56.176 - throw new OpenDataException(
56.177 - "Proxy's name does not start with " +
56.178 - prefix + ": " + name);
56.179 - }
56.180 - try {
56.181 - name = name.withDomain(domain.substring(prefix.length()));
56.182 - } catch (IllegalArgumentException e) {
56.183 - throw EnvHelp.initCause(
56.184 - new OpenDataException(e.getMessage()), e);
56.185 - }
56.186 - return name;
56.187 + return lookup;
56.188 }
56.189 }
56.190
56.191 - ObjectName proxyToObjectName(Object proxy) {
56.192 - InvocationHandler ih = Proxy.getInvocationHandler(proxy);
56.193 - if (ih instanceof MBeanServerInvocationHandler) {
56.194 - MBeanServerInvocationHandler mbsih =
56.195 - (MBeanServerInvocationHandler) ih;
56.196 - if (mbsih.getMBeanServerConnection().equals(mbsc))
56.197 - return mbsih.getObjectName();
56.198 + synchronized <T> T objectNameToMXBean(ObjectName name, Class<T> type) {
56.199 + WeakReference<Object> wr = objectNameToProxy.get(name);
56.200 + if (wr != null) {
56.201 + Object proxy = wr.get();
56.202 + if (type.isInstance(proxy))
56.203 + return type.cast(proxy);
56.204 }
56.205 - return null;
56.206 + T proxy = JMX.newMXBeanProxy(mbsc, name, type);
56.207 + objectNameToProxy.put(name, new WeakReference<Object>(proxy));
56.208 + return proxy;
56.209 + }
56.210 +
56.211 + synchronized ObjectName mxbeanToObjectName(Object mxbean)
56.212 + throws OpenDataException {
56.213 + String wrong;
56.214 + if (mxbean instanceof Proxy) {
56.215 + InvocationHandler ih = Proxy.getInvocationHandler(mxbean);
56.216 + if (ih instanceof MBeanServerInvocationHandler) {
56.217 + MBeanServerInvocationHandler mbsih =
56.218 + (MBeanServerInvocationHandler) ih;
56.219 + if (mbsih.getMBeanServerConnection().equals(mbsc))
56.220 + return mbsih.getObjectName();
56.221 + else
56.222 + wrong = "proxy for a different MBeanServer";
56.223 + } else
56.224 + wrong = "not a JMX proxy";
56.225 + } else {
56.226 + ObjectName name = mxbeanToObjectName.get(mxbean);
56.227 + if (name != null)
56.228 + return name;
56.229 + wrong = "not an MXBean registered in this MBeanServer";
56.230 + }
56.231 + String s = (mxbean == null) ?
56.232 + "null" : "object of type " + mxbean.getClass().getName();
56.233 + throw new OpenDataException(
56.234 + "Could not convert " + s + " to an ObjectName: " + wrong);
56.235 + // Message will be strange if mxbean is null but it is not
56.236 + // supposed to be.
56.237 + }
56.238 +
56.239 + synchronized void addReference(ObjectName name, Object mxbean)
56.240 + throws InstanceAlreadyExistsException {
56.241 + ObjectName existing = mxbeanToObjectName.get(mxbean);
56.242 + if (existing != null) {
56.243 + String multiname = AccessController.doPrivileged(
56.244 + new GetPropertyAction("jmx.mxbean.multiname"));
56.245 + if (!"true".equalsIgnoreCase(multiname)) {
56.246 + throw new InstanceAlreadyExistsException(
56.247 + "MXBean already registered with name " + existing);
56.248 + }
56.249 + }
56.250 + mxbeanToObjectName.put(mxbean, name);
56.251 + }
56.252 +
56.253 + synchronized boolean removeReference(ObjectName name, Object mxbean) {
56.254 + if (name.equals(mxbeanToObjectName.get(mxbean))) {
56.255 + mxbeanToObjectName.remove(mxbean);
56.256 + return true;
56.257 + } else
56.258 + return false;
56.259 + /* removeReference can be called when the above condition fails,
56.260 + * notably if you try to register the same MXBean twice.
56.261 + */
56.262 }
56.263
56.264 static MXBeanLookup getLookup() {
56.265 @@ -273,5 +177,12 @@
56.266 private static final ThreadLocal<MXBeanLookup> currentLookup =
56.267 new ThreadLocal<MXBeanLookup>();
56.268
56.269 - final MBeanServerConnection mbsc;
56.270 + private final MBeanServerConnection mbsc;
56.271 + private final WeakIdentityHashMap<Object, ObjectName>
56.272 + mxbeanToObjectName = WeakIdentityHashMap.make();
56.273 + private final Map<ObjectName, WeakReference<Object>>
56.274 + objectNameToProxy = newMap();
56.275 + private static final WeakIdentityHashMap<MBeanServerConnection,
56.276 + WeakReference<MXBeanLookup>>
56.277 + mbscToLookup = WeakIdentityHashMap.make();
56.278 }
57.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
57.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanMapping.java Wed Nov 25 11:08:25 2009 -0800
57.3 @@ -0,0 +1,210 @@
57.4 +/*
57.5 + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
57.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
57.7 + *
57.8 + * This code is free software; you can redistribute it and/or modify it
57.9 + * under the terms of the GNU General Public License version 2 only, as
57.10 + * published by the Free Software Foundation. Sun designates this
57.11 + * particular file as subject to the "Classpath" exception as provided
57.12 + * by Sun in the LICENSE file that accompanied this code.
57.13 + *
57.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
57.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
57.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
57.17 + * version 2 for more details (a copy is included in the LICENSE file that
57.18 + * accompanied this code).
57.19 + *
57.20 + * You should have received a copy of the GNU General Public License version
57.21 + * 2 along with this work; if not, write to the Free Software Foundation,
57.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
57.23 + *
57.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
57.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
57.26 + * have any questions.
57.27 + */
57.28 +
57.29 +package com.sun.jmx.mbeanserver;
57.30 +
57.31 +import java.io.InvalidObjectException;
57.32 +import java.lang.reflect.Type;
57.33 +import javax.management.openmbean.OpenDataException;
57.34 +import javax.management.openmbean.OpenType;
57.35 +
57.36 +/**
57.37 + * <p>A custom mapping between Java types and Open types for use in MXBeans.
57.38 + * To define such a mapping, subclass this class and define at least the
57.39 + * {@link #fromOpenValue fromOpenValue} and {@link #toOpenValue toOpenValue}
57.40 + * methods, and optionally the {@link #checkReconstructible} method.
57.41 + * Then either use an {@link MXBeanMappingClass} annotation on your custom
57.42 + * Java types, or include this MXBeanMapping in an
57.43 + * {@link MXBeanMappingFactory}.</p>
57.44 + *
57.45 + * <p>For example, suppose we have a class {@code MyLinkedList}, which looks
57.46 + * like this:</p>
57.47 + *
57.48 + * <pre>
57.49 + * public class MyLinkedList {
57.50 + * public MyLinkedList(String name, MyLinkedList next) {...}
57.51 + * public String getName() {...}
57.52 + * public MyLinkedList getNext() {...}
57.53 + * }
57.54 + * </pre>
57.55 + *
57.56 + * <p>This is not a valid type for MXBeans, because it contains a
57.57 + * self-referential property "next" defined by the {@code getNext()}
57.58 + * method. MXBeans do not support recursive types. So we would like
57.59 + * to specify a mapping for {@code MyLinkedList} explicitly. When an
57.60 + * MXBean interface contains {@code MyLinkedList}, that will be mapped
57.61 + * into a {@code String[]}, which is a valid Open Type.</p>
57.62 + *
57.63 + * <p>To define this mapping, we first subclass {@code MXBeanMapping}:</p>
57.64 + *
57.65 + * <pre>
57.66 + * public class MyLinkedListMapping extends MXBeanMapping {
57.67 + * public MyLinkedListMapping(Type type) throws OpenDataException {
57.68 + * super(MyLinkedList.class, ArrayType.getArrayType(SimpleType.STRING));
57.69 + * if (type != MyLinkedList.class)
57.70 + * throw new OpenDataException("Mapping only valid for MyLinkedList");
57.71 + * }
57.72 + *
57.73 + * {@literal @Override}
57.74 + * public Object fromOpenValue(Object openValue) throws InvalidObjectException {
57.75 + * String[] array = (String[]) openValue;
57.76 + * MyLinkedList list = null;
57.77 + * for (int i = array.length - 1; i >= 0; i--)
57.78 + * list = new MyLinkedList(array[i], list);
57.79 + * return list;
57.80 + * }
57.81 + *
57.82 + * {@literal @Override}
57.83 + * public Object toOpenValue(Object javaValue) throws OpenDataException {
57.84 + * ArrayList<String> array = new ArrayList<String>();
57.85 + * for (MyLinkedList list = (MyLinkedList) javaValue; list != null;
57.86 + * list = list.getNext())
57.87 + * array.add(list.getName());
57.88 + * return array.toArray(new String[0]);
57.89 + * }
57.90 + * }
57.91 + * </pre>
57.92 + *
57.93 + * <p>The call to the superclass constructor specifies what the
57.94 + * original Java type is ({@code MyLinkedList.class}) and what Open
57.95 + * Type it is mapped to ({@code
57.96 + * ArrayType.getArrayType(SimpleType.STRING)}). The {@code
57.97 + * fromOpenValue} method says how we go from the Open Type ({@code
57.98 + * String[]}) to the Java type ({@code MyLinkedList}), and the {@code
57.99 + * toOpenValue} method says how we go from the Java type to the Open
57.100 + * Type.</p>
57.101 + *
57.102 + * <p>With this mapping defined, we can annotate the {@code MyLinkedList}
57.103 + * class appropriately:</p>
57.104 + *
57.105 + * <pre>
57.106 + * {@literal @MXBeanMappingClass}(MyLinkedListMapping.class)
57.107 + * public class MyLinkedList {...}
57.108 + * </pre>
57.109 + *
57.110 + * <p>Now we can use {@code MyLinkedList} in an MXBean interface and it
57.111 + * will work.</p>
57.112 + *
57.113 + * <p>If we are unable to modify the {@code MyLinkedList} class,
57.114 + * we can define an {@link MXBeanMappingFactory}. See the documentation
57.115 + * of that class for further details.</p>
57.116 + *
57.117 + * @see <a href="../MXBean.html#custom">MXBean specification, section
57.118 + * "Custom MXBean type mappings"</a>
57.119 + */
57.120 +public abstract class MXBeanMapping {
57.121 + private final Type javaType;
57.122 + private final OpenType<?> openType;
57.123 + private final Class<?> openClass;
57.124 +
57.125 + /**
57.126 + * <p>Construct a mapping between the given Java type and the given
57.127 + * Open Type.</p>
57.128 + *
57.129 + * @param javaType the Java type (for example, {@code MyLinkedList}).
57.130 + * @param openType the Open Type (for example, {@code
57.131 + * ArrayType.getArrayType(SimpleType.STRING)})
57.132 + *
57.133 + * @throws NullPointerException if either argument is null.
57.134 + */
57.135 + protected MXBeanMapping(Type javaType, OpenType<?> openType) {
57.136 + if (javaType == null || openType == null)
57.137 + throw new NullPointerException("Null argument");
57.138 + this.javaType = javaType;
57.139 + this.openType = openType;
57.140 + this.openClass = makeOpenClass(javaType, openType);
57.141 + }
57.142 +
57.143 + /**
57.144 + * <p>The Java type that was supplied to the constructor.</p>
57.145 + * @return the Java type that was supplied to the constructor.
57.146 + */
57.147 + public final Type getJavaType() {
57.148 + return javaType;
57.149 + }
57.150 +
57.151 + /**
57.152 + * <p>The Open Type that was supplied to the constructor.</p>
57.153 + * @return the Open Type that was supplied to the constructor.
57.154 + */
57.155 + public final OpenType<?> getOpenType() {
57.156 + return openType;
57.157 + }
57.158 +
57.159 + /**
57.160 + * <p>The Java class that corresponds to instances of the
57.161 + * {@linkplain #getOpenType() Open Type} for this mapping.</p>
57.162 + * @return the Java class that corresponds to instances of the
57.163 + * Open Type for this mapping.
57.164 + * @see OpenType#getClassName
57.165 + */
57.166 + public final Class<?> getOpenClass() {
57.167 + return openClass;
57.168 + }
57.169 +
57.170 + private static Class<?> makeOpenClass(Type javaType, OpenType<?> openType) {
57.171 + if (javaType instanceof Class<?> && ((Class<?>) javaType).isPrimitive())
57.172 + return (Class<?>) javaType;
57.173 + try {
57.174 + String className = openType.getClassName();
57.175 + return Class.forName(className, false, null);
57.176 + } catch (ClassNotFoundException e) {
57.177 + throw new RuntimeException(e); // should not happen
57.178 + }
57.179 + }
57.180 +
57.181 + /**
57.182 + * <p>Convert an instance of the Open Type into the Java type.
57.183 + * @param openValue the value to be converted.
57.184 + * @return the converted value.
57.185 + * @throws InvalidObjectException if the value cannot be converted.
57.186 + */
57.187 + public abstract Object fromOpenValue(Object openValue)
57.188 + throws InvalidObjectException;
57.189 +
57.190 + /**
57.191 + * <p>Convert an instance of the Java type into the Open Type.
57.192 + * @param javaValue the value to be converted.
57.193 + * @return the converted value.
57.194 + * @throws OpenDataException if the value cannot be converted.
57.195 + */
57.196 + public abstract Object toOpenValue(Object javaValue)
57.197 + throws OpenDataException;
57.198 +
57.199 +
57.200 + /**
57.201 + * <p>Throw an appropriate InvalidObjectException if we will not
57.202 + * be able to convert back from the open data to the original Java
57.203 + * object. The {@link #fromOpenValue fromOpenValue} throws an
57.204 + * exception if a given open data value cannot be converted. This
57.205 + * method throws an exception if <em>no</em> open data values can
57.206 + * be converted. The default implementation of this method never
57.207 + * throws an exception. Subclasses can override it as
57.208 + * appropriate.</p>
57.209 + * @throws InvalidObjectException if {@code fromOpenValue} will throw
57.210 + * an exception no matter what its argument is.
57.211 + */
57.212 + public void checkReconstructible() throws InvalidObjectException {}
57.213 +}
58.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
58.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanMappingFactory.java Wed Nov 25 11:08:25 2009 -0800
58.3 @@ -0,0 +1,124 @@
58.4 +/*
58.5 + * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
58.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
58.7 + *
58.8 + * This code is free software; you can redistribute it and/or modify it
58.9 + * under the terms of the GNU General Public License version 2 only, as
58.10 + * published by the Free Software Foundation. Sun designates this
58.11 + * particular file as subject to the "Classpath" exception as provided
58.12 + * by Sun in the LICENSE file that accompanied this code.
58.13 + *
58.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
58.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
58.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
58.17 + * version 2 for more details (a copy is included in the LICENSE file that
58.18 + * accompanied this code).
58.19 + *
58.20 + * You should have received a copy of the GNU General Public License version
58.21 + * 2 along with this work; if not, write to the Free Software Foundation,
58.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
58.23 + *
58.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
58.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
58.26 + * have any questions.
58.27 + */
58.28 +
58.29 +package com.sun.jmx.mbeanserver;
58.30 +
58.31 +import javax.management.openmbean.*;
58.32 +import com.sun.jmx.mbeanserver.MXBeanMapping;
58.33 +import com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory;
58.34 +import java.lang.reflect.Type;
58.35 +
58.36 +/**
58.37 + * <p>Defines how types are mapped for a given MXBean or set of MXBeans.
58.38 + * An {@code MXBeanMappingFactory} can be specified either through the
58.39 + * {@link MXBeanMappingFactoryClass} annotation, or through the
58.40 + * {@link javax.management.JMX.MBeanOptions JMX.MBeanOptions} argument to a
58.41 + * {@link javax.management.StandardMBean StandardMBean} constructor or MXBean
58.42 + * proxy.</p>
58.43 + *
58.44 + * <p>An {@code MXBeanMappingFactory} must return an {@code MXBeanMapping}
58.45 + * for any Java type that appears in the MXBeans that the factory is being
58.46 + * used for. Usually it does that by handling any custom types, and
58.47 + * forwarding everything else to the {@linkplain #DEFAULT default mapping
58.48 + * factory}.</p>
58.49 + *
58.50 + * <p>Consider the {@code MyLinkedList} example from the {@link MXBeanMapping}
58.51 + * documentation. If we are unable to change the {@code MyLinkedList} class
58.52 + * to add an {@link MXBeanMappingClass} annotation, we could achieve the same
58.53 + * effect by defining {@code MyLinkedListMappingFactory} as follows:</p>
58.54 + *
58.55 + * <pre>
58.56 + * public class MyLinkedListMappingFactory extends MXBeanMappingFactory {
58.57 + * public MyLinkedListMappingFactory() {}
58.58 + *
58.59 + * public MXBeanMapping mappingForType(Type t, MXBeanMappingFactory f)
58.60 + * throws OpenDataException {
58.61 + * if (t == MyLinkedList.class)
58.62 + * return new MyLinkedListMapping(t);
58.63 + * else
58.64 + * return MXBeanMappingFactory.DEFAULT.mappingForType(t, f);
58.65 + * }
58.66 + * }
58.67 + * </pre>
58.68 + *
58.69 + * <p>The mapping factory handles only the {@code MyLinkedList} class.
58.70 + * Every other type is forwarded to the default mapping factory.
58.71 + * This includes types such as {@code MyLinkedList[]} and
58.72 + * {@code List<MyLinkedList>}; the default mapping factory will recursively
58.73 + * invoke {@code MyLinkedListMappingFactory} to map the contained
58.74 + * {@code MyLinkedList} type.</p>
58.75 + *
58.76 + * <p>Once we have defined {@code MyLinkedListMappingFactory}, we can use
58.77 + * it in an MXBean interface like this:</p>
58.78 + *
58.79 + * <pre>
58.80 + * {@literal @MXBeanMappingFactoryClass}(MyLinkedListMappingFactory.class)
58.81 + * public interface SomethingMXBean {
58.82 + * public MyLinkedList getSomething();
58.83 + * }
58.84 + * </pre>
58.85 + *
58.86 + * <p>Alternatively we can annotate the package that {@code SomethingMXBean}
58.87 + * appears in, or we can supply the factory to a {@link
58.88 + * javax.management.StandardMBean StandardMBean} constructor or MXBean
58.89 + * proxy.</p>
58.90 + *
58.91 + * @see <a href="../MXBean.html#custom">MXBean specification, section
58.92 + * "Custom MXBean type mappings"</a>
58.93 + */
58.94 +public abstract class MXBeanMappingFactory {
58.95 + /**
58.96 + * <p>Construct an instance of this class.</p>
58.97 + */
58.98 + protected MXBeanMappingFactory() {}
58.99 +
58.100 + /**
58.101 + * <p>Mapping factory that applies the default rules for MXBean
58.102 + * mappings, as described in the <a
58.103 + * href="../MXBean.html#MXBean-spec">MXBean specification</a>.</p>
58.104 + */
58.105 + public static final MXBeanMappingFactory DEFAULT =
58.106 + new DefaultMXBeanMappingFactory();
58.107 +
58.108 + /**
58.109 + * <p>Return the mapping for the given Java type. Typically, a
58.110 + * mapping factory will return mappings for types it handles, and
58.111 + * forward other types to another mapping factory, most often
58.112 + * the {@linkplain #DEFAULT default one}.</p>
58.113 + * @param t the Java type to be mapped.
58.114 + * @param f the original mapping factory that was consulted to do
58.115 + * the mapping. A mapping factory should pass this parameter intact
58.116 + * if it forwards a type to another mapping factory. In the example,
58.117 + * this is how {@code MyLinkedListMappingFactory} works for types
58.118 + * like {@code MyLinkedList[]} and {@code List<MyLinkedList>}.
58.119 + * @return the mapping for the given type.
58.120 + * @throws OpenDataException if this type cannot be mapped. This
58.121 + * exception is appropriate if the factory is supposed to handle
58.122 + * all types of this sort (for example, all linked lists), but
58.123 + * cannot handle this particular type.
58.124 + */
58.125 + public abstract MXBeanMapping mappingForType(Type t, MXBeanMappingFactory f)
58.126 + throws OpenDataException;
58.127 +}
59.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanProxy.java Mon Nov 23 10:04:47 2009 +0000
59.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanProxy.java Wed Nov 25 11:08:25 2009 -0800
59.3 @@ -32,10 +32,8 @@
59.4
59.5 import javax.management.Attribute;
59.6 import javax.management.MBeanServerConnection;
59.7 -import javax.management.MalformedObjectNameException;
59.8 import javax.management.NotCompliantMBeanException;
59.9 import javax.management.ObjectName;
59.10 -import javax.management.openmbean.MXBeanMappingFactory;
59.11
59.12 /**
59.13 <p>Helper class for an {@link InvocationHandler} that forwards methods from an
59.14 @@ -47,7 +45,7 @@
59.15 @since 1.6
59.16 */
59.17 public class MXBeanProxy {
59.18 - public MXBeanProxy(Class<?> mxbeanInterface, MXBeanMappingFactory factory) {
59.19 + public MXBeanProxy(Class<?> mxbeanInterface) {
59.20
59.21 if (mxbeanInterface == null)
59.22 throw new IllegalArgumentException("Null parameter");
59.23 @@ -55,7 +53,7 @@
59.24 final MBeanAnalyzer<ConvertingMethod> analyzer;
59.25 try {
59.26 analyzer =
59.27 - MXBeanIntrospector.getInstance(factory).getAnalyzer(mxbeanInterface);
59.28 + MXBeanIntrospector.getInstance().getAnalyzer(mxbeanInterface);
59.29 } catch (NotCompliantMBeanException e) {
59.30 throw new IllegalArgumentException(e);
59.31 }
59.32 @@ -63,7 +61,7 @@
59.33 }
59.34
59.35 private class Visitor
59.36 - implements MBeanAnalyzer.MBeanVisitor<ConvertingMethod, RuntimeException> {
59.37 + implements MBeanAnalyzer.MBeanVisitor<ConvertingMethod> {
59.38 public void visitAttribute(String attributeName,
59.39 ConvertingMethod getter,
59.40 ConvertingMethod setter) {
59.41 @@ -161,8 +159,7 @@
59.42
59.43 Handler handler = handlerMap.get(method);
59.44 ConvertingMethod cm = handler.getConvertingMethod();
59.45 - String prefix = extractPrefix(name);
59.46 - MXBeanLookup lookup = MXBeanLookup.lookupFor(mbsc, prefix);
59.47 + MXBeanLookup lookup = MXBeanLookup.lookupFor(mbsc);
59.48 MXBeanLookup oldLookup = MXBeanLookup.getLookup();
59.49 try {
59.50 MXBeanLookup.setLookup(lookup);
59.51 @@ -174,17 +171,5 @@
59.52 }
59.53 }
59.54
59.55 - private static String extractPrefix(ObjectName name)
59.56 - throws MalformedObjectNameException {
59.57 - String domain = name.getDomain();
59.58 - int slashslash = domain.lastIndexOf("//");
59.59 - if (slashslash > 0 && domain.charAt(slashslash - 1) == '/')
59.60 - slashslash--;
59.61 - if (slashslash >= 0)
59.62 - return domain.substring(0, slashslash + 2);
59.63 - else
59.64 - return null;
59.65 - }
59.66 -
59.67 private final Map<Method, Handler> handlerMap = newMap();
59.68 }
60.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/MXBeanSupport.java Mon Nov 23 10:04:47 2009 +0000
60.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/MXBeanSupport.java Wed Nov 25 11:08:25 2009 -0800
60.3 @@ -35,7 +35,6 @@
60.4 import javax.management.MBeanServer;
60.5 import javax.management.NotCompliantMBeanException;
60.6 import javax.management.ObjectName;
60.7 -import javax.management.openmbean.MXBeanMappingFactory;
60.8
60.9 /**
60.10 * Base class for MXBeans.
60.11 @@ -62,16 +61,14 @@
60.12 if it does not implement the class {@code mxbeanInterface} or if
60.13 that class is not a valid MXBean interface.
60.14 */
60.15 - public <T> MXBeanSupport(T resource, Class<T> mxbeanInterface,
60.16 - MXBeanMappingFactory mappingFactory)
60.17 + public <T> MXBeanSupport(T resource, Class<T> mxbeanInterface)
60.18 throws NotCompliantMBeanException {
60.19 - super(resource, mxbeanInterface, mappingFactory);
60.20 + super(resource, mxbeanInterface);
60.21 }
60.22
60.23 @Override
60.24 - MBeanIntrospector<ConvertingMethod>
60.25 - getMBeanIntrospector(MXBeanMappingFactory mappingFactory) {
60.26 - return MXBeanIntrospector.getInstance(mappingFactory);
60.27 + MBeanIntrospector<ConvertingMethod> getMBeanIntrospector() {
60.28 + return MXBeanIntrospector.getInstance();
60.29 }
60.30
60.31 @Override
60.32 @@ -159,8 +156,8 @@
60.33 // eventually we could have some logic to supply a default name
60.34
60.35 synchronized (lock) {
60.36 - this.mxbeanLookup = MXBeanLookup.Plain.lookupFor(server);
60.37 - this.mxbeanLookup.addReference(name, getWrappedObject());
60.38 + this.mxbeanLookup = MXBeanLookup.lookupFor(server);
60.39 + this.mxbeanLookup.addReference(name, getResource());
60.40 this.objectName = name;
60.41 }
60.42 }
60.43 @@ -169,19 +166,13 @@
60.44 public void unregister() {
60.45 synchronized (lock) {
60.46 if (mxbeanLookup != null) {
60.47 - if (mxbeanLookup.removeReference(objectName, getWrappedObject()))
60.48 + if (mxbeanLookup.removeReference(objectName, getResource()))
60.49 objectName = null;
60.50 }
60.51 - // XXX: need to revisit the whole register/unregister logic in
60.52 - // the face of wrapping. The mxbeanLookup!=null test is a hack.
60.53 - // If you wrap an MXBean in a MyWrapperMBean and register it,
60.54 - // the lookup table should contain the wrapped object. But that
60.55 - // implies that MyWrapperMBean calls register, which today it
60.56 - // can't within the public API.
60.57 }
60.58 }
60.59 private final Object lock = new Object(); // for mxbeanLookup and objectName
60.60
60.61 - private MXBeanLookup.Plain mxbeanLookup;
60.62 + private MXBeanLookup mxbeanLookup;
60.63 private ObjectName objectName;
60.64 }
61.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/NotificationMBeanSupport.java Mon Nov 23 10:04:47 2009 +0000
61.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
61.3 @@ -1,82 +0,0 @@
61.4 -/*
61.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
61.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
61.7 - *
61.8 - * This code is free software; you can redistribute it and/or modify it
61.9 - * under the terms of the GNU General Public License version 2 only, as
61.10 - * published by the Free Software Foundation. Sun designates this
61.11 - * particular file as subject to the "Classpath" exception as provided
61.12 - * by Sun in the LICENSE file that accompanied this code.
61.13 - *
61.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
61.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
61.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
61.17 - * version 2 for more details (a copy is included in the LICENSE file that
61.18 - * accompanied this code).
61.19 - *
61.20 - * You should have received a copy of the GNU General Public License version
61.21 - * 2 along with this work; if not, write to the Free Software Foundation,
61.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
61.23 - *
61.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
61.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
61.26 - * have any questions.
61.27 - */
61.28 -
61.29 -package com.sun.jmx.mbeanserver;
61.30 -
61.31 -import java.lang.reflect.Method;
61.32 -import java.util.ArrayList;
61.33 -import java.util.List;
61.34 -import javax.management.NotCompliantMBeanException;
61.35 -import javax.management.Notification;
61.36 -import javax.management.openmbean.MXBeanMappingFactory;
61.37 -
61.38 -/**
61.39 - * <p>A variant of {@code StandardMBeanSupport} where the only
61.40 - * methods included are public getters. This is used by
61.41 - * {@code QueryNotificationFilter} to pretend that a Notification is
61.42 - * an MBean so it can have a query evaluated on it. Standard queries
61.43 - * never set attributes or invoke methods but custom queries could and
61.44 - * we don't want to allow that. Also we don't want to fail if a
61.45 - * Notification happens to have inconsistent types in a pair of getX and
61.46 - * setX methods, and we want to include the Object.getClass() method.
61.47 - */
61.48 -public class NotificationMBeanSupport extends StandardMBeanSupport {
61.49 - public <T extends Notification> NotificationMBeanSupport(T n)
61.50 - throws NotCompliantMBeanException {
61.51 - super(n, Util.<Class<T>>cast(n.getClass()));
61.52 - }
61.53 -
61.54 - @Override
61.55 - MBeanIntrospector<Method> getMBeanIntrospector(MXBeanMappingFactory ignored) {
61.56 - return introspector;
61.57 - }
61.58 -
61.59 - private static class Introspector extends StandardMBeanIntrospector {
61.60 - @Override
61.61 - void checkCompliance(Class<?> mbeanType) {}
61.62 -
61.63 - @Override
61.64 - List<Method> getMethods(final Class<?> mbeanType)
61.65 - throws Exception {
61.66 - List<Method> methods = new ArrayList<Method>();
61.67 - for (Method m : mbeanType.getMethods()) {
61.68 - String name = m.getName();
61.69 - Class<?> ret = m.getReturnType();
61.70 - if (m.getParameterTypes().length == 0) {
61.71 - if ((name.startsWith("is") && name.length() > 2 &&
61.72 - ret == boolean.class) ||
61.73 - (name.startsWith("get") && name.length() > 3 &&
61.74 - ret != void.class)) {
61.75 - methods.add(m);
61.76 - }
61.77 - }
61.78 - }
61.79 - return methods;
61.80 - }
61.81 -
61.82 - }
61.83 - private static final MBeanIntrospector<Method> introspector =
61.84 - new Introspector();
61.85 -}
62.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/NotifySupport.java Mon Nov 23 10:04:47 2009 +0000
62.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
62.3 @@ -1,186 +0,0 @@
62.4 -/*
62.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
62.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
62.7 - *
62.8 - * This code is free software; you can redistribute it and/or modify it
62.9 - * under the terms of the GNU General Public License version 2 only, as
62.10 - * published by the Free Software Foundation. Sun designates this
62.11 - * particular file as subject to the "Classpath" exception as provided
62.12 - * by Sun in the LICENSE file that accompanied this code.
62.13 - *
62.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
62.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
62.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
62.17 - * version 2 for more details (a copy is included in the LICENSE file that
62.18 - * accompanied this code).
62.19 - *
62.20 - * You should have received a copy of the GNU General Public License version
62.21 - * 2 along with this work; if not, write to the Free Software Foundation,
62.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
62.23 - *
62.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
62.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
62.26 - * have any questions.
62.27 - */
62.28 -
62.29 -package com.sun.jmx.mbeanserver;
62.30 -
62.31 -import javax.management.Attribute;
62.32 -import javax.management.AttributeList;
62.33 -import javax.management.AttributeNotFoundException;
62.34 -import javax.management.DynamicMBean;
62.35 -import javax.management.DynamicWrapperMBean;
62.36 -import javax.management.InvalidAttributeValueException;
62.37 -import javax.management.ListenerNotFoundException;
62.38 -import javax.management.MBeanException;
62.39 -import javax.management.MBeanInfo;
62.40 -import javax.management.MBeanNotificationInfo;
62.41 -import javax.management.MBeanRegistration;
62.42 -import javax.management.MBeanServer;
62.43 -import javax.management.NotificationBroadcasterSupport;
62.44 -import javax.management.NotificationEmitter;
62.45 -import javax.management.NotificationFilter;
62.46 -import javax.management.NotificationListener;
62.47 -import javax.management.ObjectName;
62.48 -import javax.management.ReflectionException;
62.49 -
62.50 -/**
62.51 - * Create wrappers for DynamicMBean that implement NotificationEmitter
62.52 - * and SendNotification.
62.53 - */
62.54 -public class NotifySupport
62.55 - implements DynamicMBean2, NotificationEmitter, MBeanRegistration {
62.56 -
62.57 - private final DynamicMBean mbean;
62.58 - private final NotificationBroadcasterSupport nbs;
62.59 -
62.60 - public static DynamicMBean wrap(
62.61 - DynamicMBean mbean, NotificationBroadcasterSupport nbs) {
62.62 - return new NotifySupport(mbean, nbs);
62.63 - }
62.64 -
62.65 - private NotifySupport(DynamicMBean mbean, NotificationBroadcasterSupport nbs) {
62.66 - this.mbean = mbean;
62.67 - this.nbs = nbs;
62.68 - }
62.69 -
62.70 - public static NotificationBroadcasterSupport getNB(DynamicMBean mbean) {
62.71 - if (mbean instanceof NotifySupport)
62.72 - return ((NotifySupport) mbean).nbs;
62.73 - else
62.74 - return null;
62.75 - }
62.76 -
62.77 - public String getClassName() {
62.78 - if (mbean instanceof DynamicMBean2)
62.79 - return ((DynamicMBean2) mbean).getClassName();
62.80 - Object w = mbean;
62.81 - if (w instanceof DynamicWrapperMBean)
62.82 - w = ((DynamicWrapperMBean) w).getWrappedObject();
62.83 - return w.getClass().getName();
62.84 - }
62.85 -
62.86 - public void preRegister2(MBeanServer mbs, ObjectName name) throws Exception {
62.87 - if (mbean instanceof DynamicMBean2)
62.88 - ((DynamicMBean2) mbean).preRegister2(mbs, name);
62.89 - }
62.90 -
62.91 - public void registerFailed() {
62.92 - if (mbean instanceof DynamicMBean2)
62.93 - ((DynamicMBean2) mbean).registerFailed();
62.94 - }
62.95 -
62.96 - public Object getWrappedObject() {
62.97 - if (mbean instanceof DynamicWrapperMBean)
62.98 - return ((DynamicWrapperMBean) mbean).getWrappedObject();
62.99 - else
62.100 - return mbean;
62.101 - }
62.102 -
62.103 - public ClassLoader getWrappedClassLoader() {
62.104 - if (mbean instanceof DynamicWrapperMBean)
62.105 - return ((DynamicWrapperMBean) mbean).getWrappedClassLoader();
62.106 - else
62.107 - return mbean.getClass().getClassLoader();
62.108 - }
62.109 -
62.110 - public Object getAttribute(String attribute) throws AttributeNotFoundException,
62.111 - MBeanException,
62.112 - ReflectionException {
62.113 - return mbean.getAttribute(attribute);
62.114 - }
62.115 -
62.116 - public void setAttribute(Attribute attribute) throws AttributeNotFoundException,
62.117 - InvalidAttributeValueException,
62.118 - MBeanException,
62.119 - ReflectionException {
62.120 - mbean.setAttribute(attribute);
62.121 - }
62.122 -
62.123 - public AttributeList setAttributes(AttributeList attributes) {
62.124 - return mbean.setAttributes(attributes);
62.125 - }
62.126 -
62.127 - public Object invoke(String actionName, Object[] params, String[] signature)
62.128 - throws MBeanException, ReflectionException {
62.129 - return mbean.invoke(actionName, params, signature);
62.130 - }
62.131 -
62.132 - public MBeanInfo getMBeanInfo() {
62.133 - return mbean.getMBeanInfo();
62.134 - }
62.135 -
62.136 - public AttributeList getAttributes(String[] attributes) {
62.137 - return mbean.getAttributes(attributes);
62.138 - }
62.139 -
62.140 - public void removeNotificationListener(NotificationListener listener,
62.141 - NotificationFilter filter,
62.142 - Object handback) throws ListenerNotFoundException {
62.143 - nbs.removeNotificationListener(listener, filter, handback);
62.144 - }
62.145 -
62.146 - public void removeNotificationListener(NotificationListener listener)
62.147 - throws ListenerNotFoundException {
62.148 - nbs.removeNotificationListener(listener);
62.149 - }
62.150 -
62.151 - public MBeanNotificationInfo[] getNotificationInfo() {
62.152 - return nbs.getNotificationInfo();
62.153 - }
62.154 -
62.155 - public void addNotificationListener(NotificationListener listener,
62.156 - NotificationFilter filter,
62.157 - Object handback) {
62.158 - nbs.addNotificationListener(listener, filter, handback);
62.159 - }
62.160 -
62.161 - public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
62.162 - if (mbr() != null)
62.163 - return mbr().preRegister(server, name);
62.164 - else
62.165 - return name;
62.166 - }
62.167 -
62.168 - public void postRegister(Boolean registrationDone) {
62.169 - if (mbr() != null)
62.170 - mbr().postRegister(registrationDone);
62.171 - }
62.172 -
62.173 - public void preDeregister() throws Exception {
62.174 - if (mbr() != null)
62.175 - mbr().preDeregister();
62.176 - }
62.177 -
62.178 - public void postDeregister() {
62.179 - if (mbr() != null)
62.180 - mbr().postDeregister();
62.181 - }
62.182 -
62.183 - private MBeanRegistration mbr() {
62.184 - if (mbean instanceof MBeanRegistration)
62.185 - return (MBeanRegistration) mbean;
62.186 - else
62.187 - return null;
62.188 - }
62.189 -}
63.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/PerInterface.java Mon Nov 23 10:04:47 2009 +0000
63.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/PerInterface.java Wed Nov 25 11:08:25 2009 -0800
63.3 @@ -1,5 +1,5 @@
63.4 /*
63.5 - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
63.6 + * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
63.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
63.8 *
63.9 * This code is free software; you can redistribute it and/or modify it
63.10 @@ -231,7 +231,7 @@
63.11 /**
63.12 * Visitor that sets up the method maps (operations, getters, setters).
63.13 */
63.14 - private class InitMaps implements MBeanAnalyzer.MBeanVisitor<M, RuntimeException> {
63.15 + private class InitMaps implements MBeanAnalyzer.MBeanVisitor<M> {
63.16 public void visitAttribute(String attributeName,
63.17 M getter,
63.18 M setter) {
64.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/PerThreadGroupPool.java Mon Nov 23 10:04:47 2009 +0000
64.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
64.3 @@ -1,71 +0,0 @@
64.4 -/*
64.5 - * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
64.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
64.7 - *
64.8 - * This code is free software; you can redistribute it and/or modify it
64.9 - * under the terms of the GNU General Public License version 2 only, as
64.10 - * published by the Free Software Foundation. Sun designates this
64.11 - * particular file as subject to the "Classpath" exception as provided
64.12 - * by Sun in the LICENSE file that accompanied this code.
64.13 - *
64.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
64.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
64.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
64.17 - * version 2 for more details (a copy is included in the LICENSE file that
64.18 - * accompanied this code).
64.19 - *
64.20 - * You should have received a copy of the GNU General Public License version
64.21 - * 2 along with this work; if not, write to the Free Software Foundation,
64.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
64.23 - *
64.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
64.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
64.26 - * have any questions.
64.27 - */
64.28 -
64.29 -package com.sun.jmx.mbeanserver;
64.30 -
64.31 -import java.lang.ref.WeakReference;
64.32 -import java.util.concurrent.ThreadPoolExecutor;
64.33 -
64.34 -/**
64.35 - * <p>A factory for ThreadPoolExecutor objects that allows the same object to
64.36 - * be shared by all users of the factory that are in the same ThreadGroup.</p>
64.37 - */
64.38 -// We return a ThreadPoolExecutor rather than the more general ExecutorService
64.39 -// because we need to be able to call allowCoreThreadTimeout so that threads in
64.40 -// the pool will eventually be destroyed when the pool is no longer in use.
64.41 -// Otherwise these threads would keep the ThreadGroup alive forever.
64.42 -public class PerThreadGroupPool<T extends ThreadPoolExecutor> {
64.43 - private final WeakIdentityHashMap<ThreadGroup, WeakReference<T>> map =
64.44 - WeakIdentityHashMap.make();
64.45 -
64.46 - public static interface Create<T extends ThreadPoolExecutor> {
64.47 - public T createThreadPool(ThreadGroup group);
64.48 - }
64.49 -
64.50 - private PerThreadGroupPool() {}
64.51 -
64.52 - public static <T extends ThreadPoolExecutor> PerThreadGroupPool<T> make() {
64.53 - return new PerThreadGroupPool<T>();
64.54 - }
64.55 -
64.56 - public synchronized T getThreadPoolExecutor(Create<T> create) {
64.57 - // Find out if there's already an existing executor for the calling
64.58 - // thread and reuse it. Otherwise, create a new one and store it in
64.59 - // the executors map. If there is a SecurityManager, the group of
64.60 - // System.getSecurityManager() is used, else the group of the calling
64.61 - // thread.
64.62 - SecurityManager s = System.getSecurityManager();
64.63 - ThreadGroup group = (s != null) ? s.getThreadGroup() :
64.64 - Thread.currentThread().getThreadGroup();
64.65 - WeakReference<T> wr = map.get(group);
64.66 - T executor = (wr == null) ? null : wr.get();
64.67 - if (executor == null) {
64.68 - executor = create.createThreadPool(group);
64.69 - executor.allowCoreThreadTimeOut(true);
64.70 - map.put(group, new WeakReference<T>(executor));
64.71 - }
64.72 - return executor;
64.73 - }
64.74 -}
65.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/Repository.java Mon Nov 23 10:04:47 2009 +0000
65.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/Repository.java Wed Nov 25 11:08:25 2009 -0800
65.3 @@ -396,7 +396,7 @@
65.4
65.5 // Set domain to default if domain is empty and not already set
65.6 if (dom.length() == 0)
65.7 - name = ObjectName.valueOf(domain + name.toString());
65.8 + name = Util.newObjectName(domain + name.toString());
65.9
65.10 // Do we have default domain ?
65.11 if (dom == domain) { // ES: OK (dom & domain are interned)
65.12 @@ -573,7 +573,7 @@
65.13 // Pattern matching in the domain name (*, ?)
65.14 final String dom2Match = name.getDomain();
65.15 for (String dom : domainTb.keySet()) {
65.16 - if (Util.wildpathmatch(dom, dom2Match)) {
65.17 + if (Util.wildmatch(dom, dom2Match)) {
65.18 final Map<String,NamedObject> moiTb = domainTb.get(dom);
65.19 if (allNames)
65.20 result.addAll(moiTb.values());
66.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanIntrospector.java Mon Nov 23 10:04:47 2009 +0000
66.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanIntrospector.java Wed Nov 25 11:08:25 2009 -0800
66.3 @@ -1,5 +1,5 @@
66.4 /*
66.5 - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
66.6 + * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
66.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
66.8 *
66.9 * This code is free software; you can redistribute it and/or modify it
66.10 @@ -35,7 +35,6 @@
66.11 import javax.management.MBeanAttributeInfo;
66.12 import javax.management.MBeanException;
66.13 import javax.management.MBeanOperationInfo;
66.14 -import javax.management.ManagedOperation;
66.15 import javax.management.NotCompliantMBeanException;
66.16 import javax.management.NotificationBroadcaster;
66.17 import javax.management.NotificationBroadcasterSupport;
66.18 @@ -119,32 +118,22 @@
66.19
66.20 @Override
66.21 MBeanAttributeInfo getMBeanAttributeInfo(String attributeName,
66.22 - Method getter, Method setter) throws IntrospectionException {
66.23 + Method getter, Method setter) {
66.24
66.25 - String description = getAttributeDescription(
66.26 - attributeName, "Attribute exposed for management",
66.27 - getter, setter);
66.28 - return new MBeanAttributeInfo(attributeName, description,
66.29 - getter, setter);
66.30 + final String description = "Attribute exposed for management";
66.31 + try {
66.32 + return new MBeanAttributeInfo(attributeName, description,
66.33 + getter, setter);
66.34 + } catch (IntrospectionException e) {
66.35 + throw new RuntimeException(e); // should not happen
66.36 + }
66.37 }
66.38
66.39 @Override
66.40 MBeanOperationInfo getMBeanOperationInfo(String operationName,
66.41 Method operation) {
66.42 - final String defaultDescription = "Operation exposed for management";
66.43 - String description = Introspector.descriptionForElement(operation);
66.44 - if (description == null)
66.45 - description = defaultDescription;
66.46 -
66.47 - int impact = MBeanOperationInfo.UNKNOWN;
66.48 - ManagedOperation annot = operation.getAnnotation(ManagedOperation.class);
66.49 - if (annot != null)
66.50 - impact = annot.impact().getCode();
66.51 -
66.52 - MBeanOperationInfo mboi = new MBeanOperationInfo(description, operation);
66.53 - return new MBeanOperationInfo(
66.54 - mboi.getName(), mboi.getDescription(), mboi.getSignature(),
66.55 - mboi.getReturnType(), impact, mboi.getDescriptor());
66.56 + final String description = "Operation exposed for management";
66.57 + return new MBeanOperationInfo(description, operation);
66.58 }
66.59
66.60 @Override
67.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanSupport.java Mon Nov 23 10:04:47 2009 +0000
67.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/StandardMBeanSupport.java Wed Nov 25 11:08:25 2009 -0800
67.3 @@ -31,7 +31,6 @@
67.4 import javax.management.MBeanServer;
67.5 import javax.management.NotCompliantMBeanException;
67.6 import javax.management.ObjectName;
67.7 -import javax.management.openmbean.MXBeanMappingFactory;
67.8
67.9 /**
67.10 * Base class for Standard MBeans.
67.11 @@ -58,11 +57,11 @@
67.12 */
67.13 public <T> StandardMBeanSupport(T resource, Class<T> mbeanInterfaceType)
67.14 throws NotCompliantMBeanException {
67.15 - super(resource, mbeanInterfaceType, (MXBeanMappingFactory) null);
67.16 + super(resource, mbeanInterfaceType);
67.17 }
67.18
67.19 @Override
67.20 - MBeanIntrospector<Method> getMBeanIntrospector(MXBeanMappingFactory ignored) {
67.21 + MBeanIntrospector<Method> getMBeanIntrospector() {
67.22 return StandardMBeanIntrospector.getInstance();
67.23 }
67.24
67.25 @@ -84,14 +83,13 @@
67.26 @Override
67.27 public MBeanInfo getMBeanInfo() {
67.28 MBeanInfo mbi = super.getMBeanInfo();
67.29 - Class<?> resourceClass = getWrappedObject().getClass();
67.30 - if (!getMBeanInterface().isInterface() ||
67.31 - StandardMBeanIntrospector.isDefinitelyImmutableInfo(resourceClass))
67.32 + Class<?> resourceClass = getResource().getClass();
67.33 + if (StandardMBeanIntrospector.isDefinitelyImmutableInfo(resourceClass))
67.34 return mbi;
67.35 return new MBeanInfo(mbi.getClassName(), mbi.getDescription(),
67.36 mbi.getAttributes(), mbi.getConstructors(),
67.37 mbi.getOperations(),
67.38 - MBeanIntrospector.findNotifications(getWrappedObject()),
67.39 + MBeanIntrospector.findNotifications(getResource()),
67.40 mbi.getDescriptor());
67.41 }
67.42 }
68.1 --- a/src/share/classes/com/sun/jmx/mbeanserver/Util.java Mon Nov 23 10:04:47 2009 +0000
68.2 +++ b/src/share/classes/com/sun/jmx/mbeanserver/Util.java Wed Nov 25 11:08:25 2009 -0800
68.3 @@ -25,8 +25,6 @@
68.4
68.5 package com.sun.jmx.mbeanserver;
68.6
68.7 -import com.sun.jmx.defaults.JmxProperties;
68.8 -import java.io.IOException;
68.9 import java.util.ArrayList;
68.10 import java.util.Arrays;
68.11 import java.util.Collection;
68.12 @@ -40,25 +38,18 @@
68.13 import java.util.Map;
68.14 import java.util.Set;
68.15 import java.util.SortedMap;
68.16 -import java.util.SortedSet;
68.17 import java.util.TreeMap;
68.18 -import java.util.TreeSet;
68.19 -import java.util.WeakHashMap;
68.20 -import java.util.logging.Level;
68.21 -import javax.management.MBeanServer;
68.22 -import javax.management.MBeanServerDelegate;
68.23 -import javax.management.MBeanServerFactory;
68.24 -import javax.management.ObjectInstance;
68.25 +import javax.management.MalformedObjectNameException;
68.26 import javax.management.ObjectName;
68.27 -import javax.management.loading.ClassLoaderRepository;
68.28 -import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR;
68.29
68.30 public class Util {
68.31 - private final static int NAMESPACE_SEPARATOR_LENGTH =
68.32 - NAMESPACE_SEPARATOR.length();
68.33 - public final static char[] ILLEGAL_MBEANSERVER_NAME_CHARS=";:*?".
68.34 - toCharArray();
68.35 -
68.36 + public static ObjectName newObjectName(String string) {
68.37 + try {
68.38 + return new ObjectName(string);
68.39 + } catch (MalformedObjectNameException e) {
68.40 + throw new IllegalArgumentException(e);
68.41 + }
68.42 + }
68.43
68.44 static <K, V> Map<K, V> newMap() {
68.45 return new HashMap<K, V>();
68.46 @@ -89,10 +80,6 @@
68.47 return new LinkedHashMap<K, V>();
68.48 }
68.49
68.50 - static <K, V> WeakHashMap<K, V> newWeakHashMap() {
68.51 - return new WeakHashMap<K, V>();
68.52 - }
68.53 -
68.54 static <E> Set<E> newSet() {
68.55 return new HashSet<E>();
68.56 }
68.57 @@ -251,451 +238,4 @@
68.58 public static boolean wildmatch(String str, String pat) {
68.59 return wildmatch(str,pat,0,str.length(),0,pat.length());
68.60 }
68.61 -
68.62 - /**
68.63 - * Matches a string against a pattern, as a name space path.
68.64 - * This is a special matching where * and ?? don't match //.
68.65 - * The string is split in sub-strings separated by //, and the
68.66 - * pattern is split in sub-patterns separated by //. Each sub-string
68.67 - * is matched against its corresponding sub-pattern.
68.68 - * so <elt-1>//<elt2>//...//<elt-n> matches <pat-1>//<pat-2>//...//<pat-q>
68.69 - * only if n==q and for ( i = 1 => n) elt-i matches pat-i.
68.70 - *
68.71 - * In addition, if we encounter a pattern element which is exactly
68.72 - * **, it can match any number of path-elements - but it must match at
68.73 - * least one element.
68.74 - * When we encounter such a meta-wildcard, we remember its position
68.75 - * and the position in the string path, and we advance both the pattern
68.76 - * and the string. Later, if we encounter a mismatch in pattern & string,
68.77 - * we rewind the position in pattern to just after the meta-wildcard,
68.78 - * and we backtrack the string to i+1 element after the position
68.79 - * we had when we first encountered the meta-wildcard, i being the
68.80 - * position when we last backtracked the string.
68.81 - *
68.82 - * The backtracking logic is an adaptation of the logic in wildmatch
68.83 - * above.
68.84 - * See test/javax/mangement/ObjectName/ApplyWildcardTest.java
68.85 - *
68.86 - * Note: this thing is called 'wild' - and that's for a reason ;-)
68.87 - **/
68.88 - public static boolean wildpathmatch(String str, String pat) {
68.89 - final int strlen = str.length();
68.90 - final int patlen = pat.length();
68.91 - int stri = 0;
68.92 - int pati = 0;
68.93 -
68.94 - int starstri; // index for backtrack if "**" attempt fails
68.95 - int starpati; // index for backtrack if "**" attempt fails
68.96 -
68.97 - starstri = starpati = -1;
68.98 -
68.99 - while (true) {
68.100 - // System.out.println("pati="+pati+", stri="+stri);
68.101 - final int strend = str.indexOf(NAMESPACE_SEPARATOR, stri);
68.102 - final int patend = pat.indexOf(NAMESPACE_SEPARATOR, pati);
68.103 -
68.104 - // no // remaining in either string or pattern: simple wildmatch
68.105 - // until end of string.
68.106 - if (strend == -1 && patend == -1) {
68.107 - // System.out.println("last sub pattern, last sub element...");
68.108 - // System.out.println("wildmatch("+str.substring(stri,strlen)+
68.109 - // ","+pat.substring(pati,patlen)+")");
68.110 - return wildmatch(str,pat,stri,strlen,pati,patlen);
68.111 - }
68.112 -
68.113 - // no // remaining in string, but at least one remaining in
68.114 - // pattern
68.115 - // => no match
68.116 - if (strend == -1) {
68.117 - // System.out.println("pattern has more // than string...");
68.118 - return false;
68.119 - }
68.120 -
68.121 - // strend is != -1, but patend might.
68.122 - // detect wildcard **
68.123 - if (patend == pati+2 && pat.charAt(pati)=='*' &&
68.124 - pat.charAt(pati+1)=='*') {
68.125 - // if we reach here we know that neither strend nor patend are
68.126 - // equals to -1.
68.127 - stri = strend + NAMESPACE_SEPARATOR_LENGTH;
68.128 - pati = patend + NAMESPACE_SEPARATOR_LENGTH;
68.129 - starpati = pati; // position just after **// in pattern
68.130 - starstri = stri; // we eat 1 element in string, and remember
68.131 - // the position for backtracking and eating
68.132 - // one more element if needed.
68.133 - // System.out.println("starpati="+pati);
68.134 - continue;
68.135 - }
68.136 -
68.137 - // This is a bit hacky: * can match // when // is at the end
68.138 - // of the string, so we include the // delimiter in the pattern
68.139 - // matching. Either we're in the middle of the path, so including
68.140 - // // both at the end of the pattern and at the end of the string
68.141 - // has no effect - match(*//,dfsd//) is equivalent to match(*,dfsd)
68.142 - // or we're at the end of the pattern path, in which case
68.143 - // including // at the end of the string will have the desired
68.144 - // effect (provided that we detect the end of matching correctly,
68.145 - // see further on).
68.146 - //
68.147 - final int endpat =
68.148 - ((patend > -1)?patend+NAMESPACE_SEPARATOR_LENGTH:patlen);
68.149 - final int endstr =
68.150 - ((strend > -1)?strend+NAMESPACE_SEPARATOR_LENGTH:strlen);
68.151 -
68.152 - // if we reach the end of the pattern, or if elt-i & pat-i
68.153 - // don't match, we have a mismatch.
68.154 -
68.155 - // Note: we know that strend != -1, therefore patend==-1
68.156 - // indicates a mismatch unless pattern can match
68.157 - // a // at the end, and strend+2=strlen.
68.158 - // System.out.println("wildmatch("+str.substring(stri,endstr)+","+
68.159 - // pat.substring(pati,endpat)+")");
68.160 - if (!wildmatch(str,pat,stri,endstr,pati,endpat)) {
68.161 -
68.162 - // System.out.println("nomatch");
68.163 - // if we have a mismatch and didn't encounter any meta-wildcard,
68.164 - // we return false. String & pattern don't match.
68.165 - if (starpati < 0) return false;
68.166 -
68.167 - // If we reach here, we had a meta-wildcard.
68.168 - // We need to backtrack to the wildcard, and make it eat an
68.169 - // additional string element.
68.170 - //
68.171 - stri = str.indexOf(NAMESPACE_SEPARATOR, starstri);
68.172 - // System.out.println("eating one additional element? "+stri);
68.173 -
68.174 - // If there's no more elements to eat, string and pattern
68.175 - // don't match => return false.
68.176 - if (stri == -1) return false;
68.177 -
68.178 - // Backtrack to where we were when we last matched against
68.179 - // the meta-wildcard, make it eat an additional path element,
68.180 - // remember the new positions, and continue from there...
68.181 - //
68.182 - stri = stri + NAMESPACE_SEPARATOR_LENGTH;
68.183 - starstri = stri;
68.184 - pati = starpati;
68.185 - // System.out.println("skiping to stri="+stri);
68.186 - continue;
68.187 - }
68.188 -
68.189 - // Here we know that strend > -1 but we can have patend == -1.
68.190 - //
68.191 - // So if we reach here, we know pat-i+//? has matched
68.192 - // elt-i+//
68.193 - //
68.194 - // If patend==-1, we know that there was no delimiter
68.195 - // at the end of the pattern, that we are at the last pattern,
68.196 - // and therefore that pat-i has matched elt-i+//
68.197 - //
68.198 - // In that case we can consider that we have a match only if
68.199 - // elt-i is also the last path element in the string, which is
68.200 - // equivalent to saying that strend+2==strlen.
68.201 - //
68.202 - if (patend == -1 && starpati == -1)
68.203 - return (strend+NAMESPACE_SEPARATOR_LENGTH==strlen);
68.204 -
68.205 - // patend != -1, or starpati > -1 so there remains something
68.206 - // to match.
68.207 -
68.208 - // go to next pair: elt-(i+1) pat-(i+1);
68.209 - stri = strend + NAMESPACE_SEPARATOR_LENGTH;
68.210 - pati = (patend==-1)?pati:(patend + NAMESPACE_SEPARATOR_LENGTH);
68.211 - }
68.212 - }
68.213 -
68.214 - /**
68.215 - * Returns true if the ObjectName's {@code domain} is selected by the
68.216 - * given {@code pattern}.
68.217 - */
68.218 - public static boolean isDomainSelected(String domain, String pattern) {
68.219 - if (domain == null || pattern == null)
68.220 - throw new IllegalArgumentException("null");
68.221 - return Util.wildpathmatch(domain,pattern);
68.222 - }
68.223 -
68.224 - /**
68.225 - * Filters a set of ObjectName according to a given pattern.
68.226 - *
68.227 - * @param pattern the pattern that the returned names must match.
68.228 - * @param all the set of names to filter.
68.229 - * @return a set of ObjectName from which non matching names
68.230 - * have been removed.
68.231 - */
68.232 - public static Set<ObjectName> filterMatchingNames(ObjectName pattern,
68.233 - Set<ObjectName> all) {
68.234 - // If no pattern, just return all names
68.235 - if (pattern == null
68.236 - || all.isEmpty()
68.237 - || ObjectName.WILDCARD.equals(pattern))
68.238 - return all;
68.239 -
68.240 - // If there's a pattern, do the matching.
68.241 - final Set<ObjectName> res = equivalentEmptySet(all);
68.242 - for (ObjectName n : all) if (pattern.apply(n)) res.add(n);
68.243 - return res;
68.244 - }
68.245 -
68.246 -
68.247 - /**
68.248 - * Filters a set of ObjectInstance according to a given pattern.
68.249 - *
68.250 - * @param pattern the pattern that the returned names must match.
68.251 - * @param all the set of instances to filter.
68.252 - * @return a set of ObjectInstance from which non matching instances
68.253 - * have been removed.
68.254 - */
68.255 - public static Set<ObjectInstance>
68.256 - filterMatchingInstances(ObjectName pattern,
68.257 - Set<ObjectInstance> all) {
68.258 - // If no pattern, just return all names
68.259 - if (pattern == null
68.260 - || all.isEmpty()
68.261 - || ObjectName.WILDCARD.equals(pattern))
68.262 - return all;
68.263 -
68.264 - // If there's a pattern, do the matching.
68.265 - final Set<ObjectInstance> res = equivalentEmptySet(all);
68.266 - for (ObjectInstance n : all) {
68.267 - if (n == null) continue;
68.268 - if (pattern.apply(n.getObjectName()))
68.269 - res.add(n);
68.270 - }
68.271 - return res;
68.272 - }
68.273 -
68.274 - /**
68.275 - * An abstract ClassLoaderRepository that contains a single class loader.
68.276 - **/
68.277 - private final static class SingleClassLoaderRepository
68.278 - implements ClassLoaderRepository {
68.279 - private final ClassLoader singleLoader;
68.280 -
68.281 - SingleClassLoaderRepository(ClassLoader loader) {
68.282 - this.singleLoader = loader;
68.283 - }
68.284 -
68.285 - ClassLoader getSingleClassLoader() {
68.286 - return singleLoader;
68.287 - }
68.288 -
68.289 - private Class<?> loadClass(String className, ClassLoader loader)
68.290 - throws ClassNotFoundException {
68.291 - return Class.forName(className, false, loader);
68.292 - }
68.293 -
68.294 - public Class<?> loadClass(String className)
68.295 - throws ClassNotFoundException {
68.296 - return loadClass(className, getSingleClassLoader());
68.297 - }
68.298 -
68.299 - public Class<?> loadClassWithout(ClassLoader exclude,
68.300 - String className) throws ClassNotFoundException {
68.301 - final ClassLoader loader = getSingleClassLoader();
68.302 - if (exclude != null && exclude.equals(loader))
68.303 - throw new ClassNotFoundException(className);
68.304 - return loadClass(className, loader);
68.305 - }
68.306 -
68.307 - public Class<?> loadClassBefore(ClassLoader stop, String className)
68.308 - throws ClassNotFoundException {
68.309 - return loadClassWithout(stop, className);
68.310 - }
68.311 - }
68.312 -
68.313 - /**
68.314 - * Returns a ClassLoaderRepository that contains a single class loader.
68.315 - * @param loader the class loader contained in the returned repository.
68.316 - * @return a ClassLoaderRepository that contains the single loader.
68.317 - */
68.318 - public static ClassLoaderRepository getSingleClassLoaderRepository(
68.319 - final ClassLoader loader) {
68.320 - return new SingleClassLoaderRepository(loader);
68.321 - }
68.322 -
68.323 - /**
68.324 - * Returns the name of the given MBeanServer that should be put in a
68.325 - * permission you need.
68.326 - * This corresponds to the
68.327 - * {@code *[;mbeanServerName=<mbeanServerName>[;*]]} property
68.328 - * embedded in the MBeanServerId attribute of the
68.329 - * server's {@link MBeanServerDelegate}.
68.330 - *
68.331 - * @param server The MBean server
68.332 - * @return the name of the MBeanServer, or "*" if the name couldn't be
68.333 - * obtained, or {@value MBeanServerFactory#DEFAULT_MBEANSERVER_NAME}
68.334 - * if there was no name.
68.335 - */
68.336 - public static String getMBeanServerSecurityName(MBeanServer server) {
68.337 - final String notfound = "*";
68.338 - try {
68.339 - final String mbeanServerId = (String)
68.340 - server.getAttribute(MBeanServerDelegate.DELEGATE_NAME,
68.341 - "MBeanServerId");
68.342 - final String found = extractMBeanServerName(mbeanServerId);
68.343 - if (found.length()==0)
68.344 - return MBeanServerFactory.DEFAULT_MBEANSERVER_NAME;
68.345 - return found;
68.346 - } catch (Exception x) {
68.347 - logshort("Failed to retrieve MBeanServerName for server, " +
68.348 - "using \"*\"",x);
68.349 - return notfound;
68.350 - }
68.351 - }
68.352 -
68.353 - /**
68.354 - * Returns the name of the MBeanServer embedded in the given
68.355 - * mbeanServerId. If the given mbeanServerId doesn't contain any name,
68.356 - * an empty String is returned.
68.357 - * The MBeanServerId is expected to be of the form:
68.358 - * {@code *[;mbeanServerName=<mbeanServerName>[;*]]}
68.359 - * @param mbeanServerId The MBean server ID
68.360 - * @return the name of the MBeanServer if found, or "" if the name was
68.361 - * not present in the mbeanServerId.
68.362 - */
68.363 - public static String extractMBeanServerName(String mbeanServerId) {
68.364 - if (mbeanServerId==null) return "";
68.365 - final String beginMarker=";mbeanServerName=";
68.366 - final String endMarker=";";
68.367 - final int found = mbeanServerId.indexOf(beginMarker);
68.368 - if (found < 0) return "";
68.369 - final int start = found + beginMarker.length();
68.370 - final int stop = mbeanServerId.indexOf(endMarker, start);
68.371 - return mbeanServerId.substring(start,
68.372 - (stop < 0 ? mbeanServerId.length() : stop));
68.373 - }
68.374 -
68.375 - /**
68.376 - * Insert the given mbeanServerName into the given mbeanServerId.
68.377 - * If mbeanServerName is null, empty, or equals to "-", the returned
68.378 - * mbeanServerId will not contain any mbeanServerName.
68.379 - * @param mbeanServerId The mbeanServerId in which to insert
68.380 - * mbeanServerName
68.381 - * @param mbeanServerName The mbeanServerName
68.382 - * @return an mbeanServerId containing the given mbeanServerName
68.383 - * @throws IllegalArgumentException if mbeanServerId already contains
68.384 - * a different name, or if the given mbeanServerName is not valid.
68.385 - */
68.386 - public static String insertMBeanServerName(String mbeanServerId,
68.387 - String mbeanServerName) {
68.388 - final String found = extractMBeanServerName(mbeanServerId);
68.389 - if (found.length() > 0 &&
68.390 - found.equals(checkServerName(mbeanServerName)))
68.391 - return mbeanServerId;
68.392 - if (found.length() > 0 && !isMBeanServerNameUndefined(found))
68.393 - throw new IllegalArgumentException(
68.394 - "MBeanServerName already defined");
68.395 - if (isMBeanServerNameUndefined(mbeanServerName))
68.396 - return mbeanServerId;
68.397 - final String beginMarker=";mbeanServerName=";
68.398 - return mbeanServerId+beginMarker+checkServerName(mbeanServerName);
68.399 - }
68.400 -
68.401 - /**
68.402 - * Returns true if the given mbeanServerName corresponds to an
68.403 - * undefined MBeanServerName.
68.404 - * The mbeanServerName is considered undefined if it is one of:
68.405 - * {@code null} or {@value MBeanServerFactory#DEFAULT_MBEANSERVER_NAME}.
68.406 - * @param mbeanServerName The mbeanServerName, as returned by
68.407 - * {@link #extractMBeanServerName(String)}.
68.408 - * @return true if the given name corresponds to one of the forms that
68.409 - * denotes an undefined MBeanServerName.
68.410 - */
68.411 - public static boolean isMBeanServerNameUndefined(String mbeanServerName) {
68.412 - return mbeanServerName == null ||
68.413 - MBeanServerFactory.DEFAULT_MBEANSERVER_NAME.equals(mbeanServerName);
68.414 - }
68.415 - /**
68.416 - * Check that the provided mbeanServername is syntactically valid.
68.417 - * @param mbeanServerName An mbeanServerName, or {@code null}.
68.418 - * @return mbeanServerName, or {@value
68.419 - * MBeanServerFactory#DEFAULT_MBEANSERVER_NAME} if {@code mbeanServerName}
68.420 - * is {@code null}.
68.421 - * @throws IllegalArgumentException if mbeanServerName contains illegal
68.422 - * characters, or is empty, or is {@code "-"}.
68.423 - * Illegal characters are {@link #ILLEGAL_MBEANSERVER_NAME_CHARS}.
68.424 - */
68.425 - public static String checkServerName(String mbeanServerName) {
68.426 - if ("".equals(mbeanServerName))
68.427 - throw new IllegalArgumentException(
68.428 - "\"\" is not a valid MBean server name");
68.429 - if ("-".equals(mbeanServerName))
68.430 - throw new IllegalArgumentException(
68.431 - "\"-\" is not a valid MBean server name");
68.432 - if (isMBeanServerNameUndefined(mbeanServerName))
68.433 - return MBeanServerFactory.DEFAULT_MBEANSERVER_NAME;
68.434 - for (char c : ILLEGAL_MBEANSERVER_NAME_CHARS) {
68.435 - if (mbeanServerName.indexOf(c) >= 0)
68.436 - throw new IllegalArgumentException(
68.437 - "invalid character in MBeanServer name: "+c);
68.438 - }
68.439 - return mbeanServerName;
68.440 - }
68.441 -
68.442 - /**
68.443 - * Get the MBeanServer name that should be put in a permission you need.
68.444 - *
68.445 - * @param delegate The MBeanServerDelegate
68.446 - * @return The MBeanServer name - or {@value
68.447 - * MBeanServerFactory#DEFAULT_MBEANSERVER_NAME} if there was no name.
68.448 - */
68.449 - public static String getMBeanServerSecurityName(
68.450 - MBeanServerDelegate delegate) {
68.451 - try {
68.452 - final String serverName = delegate.getMBeanServerName();
68.453 - if (isMBeanServerNameUndefined(serverName))
68.454 - return MBeanServerFactory.DEFAULT_MBEANSERVER_NAME;
68.455 - return serverName;
68.456 - } catch (Exception x) {
68.457 - logshort("Failed to retrieve MBeanServerName from delegate, " +
68.458 - "using \"*\"",x);
68.459 - return "*";
68.460 - }
68.461 - }
68.462 -
68.463 - // Log the exception and its causes without logging the stack trace.
68.464 - // Use with care - it is usually preferable to log the whole stack trace!
68.465 - // We don't want to log the whole stack trace here: logshort() is
68.466 - // called in those cases where the exception might not be abnormal.
68.467 - private static void logshort(String msg, Throwable t) {
68.468 - if (JmxProperties.MISC_LOGGER.isLoggable(Level.FINE)) {
68.469 - StringBuilder toprint = new StringBuilder(msg);
68.470 - do {
68.471 - toprint.append("\nCaused By: ").append(String.valueOf(t));
68.472 - } while ((t=t.getCause())!=null);
68.473 - JmxProperties.MISC_LOGGER.fine(toprint.toString());
68.474 - }
68.475 - }
68.476 -
68.477 - public static <T> Set<T> cloneSet(Set<T> set) {
68.478 - if (set instanceof SortedSet<?>) {
68.479 - @SuppressWarnings("unchecked")
68.480 - SortedSet<T> sset = (SortedSet<T>) set;
68.481 - set = new TreeSet<T>(sset.comparator());
68.482 - set.addAll(sset);
68.483 - } else
68.484 - set = new HashSet<T>(set);
68.485 - return set;
68.486 - }
68.487 -
68.488 - public static <T> Set<T> equivalentEmptySet(Set<T> set) {
68.489 - if (set instanceof SortedSet<?>) {
68.490 - @SuppressWarnings("unchecked")
68.491 - SortedSet<T> sset = (SortedSet<T>) set;
68.492 - set = new TreeSet<T>(sset.comparator());
68.493 - } else
68.494 - set = new HashSet<T>();
68.495 - return set;
68.496 - }
68.497 -
68.498 - // This exception is used when wrapping a class that throws IOException
68.499 - // in a class that doesn't.
68.500 - // The typical example for this are JMXNamespaces, when the sub
68.501 - // MBeanServer can be remote.
68.502 - //
68.503 - public static RuntimeException newRuntimeIOException(IOException io) {
68.504 - final String msg = "Communication failed with underlying resource: "+
68.505 - io.getMessage();
68.506 - return new RuntimeException(msg,io);
68.507 - }
68.508 }
69.1 --- a/src/share/classes/com/sun/jmx/namespace/DomainInterceptor.java Mon Nov 23 10:04:47 2009 +0000
69.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
69.3 @@ -1,463 +0,0 @@
69.4 -/*
69.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
69.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
69.7 - *
69.8 - * This code is free software; you can redistribute it and/or modify it
69.9 - * under the terms of the GNU General Public License version 2 only, as
69.10 - * published by the Free Software Foundation. Sun designates this
69.11 - * particular file as subject to the "Classpath" exception as provided
69.12 - * by Sun in the LICENSE file that accompanied this code.
69.13 - *
69.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
69.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
69.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
69.17 - * version 2 for more details (a copy is included in the LICENSE file that
69.18 - * accompanied this code).
69.19 - *
69.20 - * You should have received a copy of the GNU General Public License version
69.21 - * 2 along with this work; if not, write to the Free Software Foundation,
69.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
69.23 - *
69.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
69.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
69.26 - * have any questions.
69.27 - */
69.28 -
69.29 -package com.sun.jmx.namespace;
69.30 -
69.31 -import com.sun.jmx.defaults.JmxProperties;
69.32 -import com.sun.jmx.mbeanserver.Util;
69.33 -import java.util.ArrayList;
69.34 -import java.util.Collections;
69.35 -import java.util.List;
69.36 -import java.util.Queue;
69.37 -import java.util.Set;
69.38 -import java.util.logging.Level;
69.39 -import java.util.logging.Logger;
69.40 -
69.41 -import javax.management.Attribute;
69.42 -import javax.management.AttributeList;
69.43 -import javax.management.InstanceNotFoundException;
69.44 -import javax.management.ListenerNotFoundException;
69.45 -import javax.management.MBeanPermission;
69.46 -import javax.management.MBeanServerDelegate;
69.47 -import javax.management.MBeanServerNotification;
69.48 -import javax.management.Notification;
69.49 -import javax.management.NotificationFilter;
69.50 -import javax.management.NotificationListener;
69.51 -import javax.management.ObjectInstance;
69.52 -import javax.management.ObjectName;
69.53 -import javax.management.QueryExp;
69.54 -import javax.management.namespace.JMXDomain;
69.55 -
69.56 -/**
69.57 - * A DomainInterceptor wraps a JMXDomain.
69.58 - * <p><b>
69.59 - * This API is a Sun internal API and is subject to changes without notice.
69.60 - * </b></p>
69.61 - * @since 1.7
69.62 - */
69.63 -public class DomainInterceptor extends HandlerInterceptor<JMXDomain> {
69.64 -
69.65 - // TODO: Ideally DomainInterceptor should be replaced by
69.66 - // something at Repository level.
69.67 - // The problem there will be that we may need to
69.68 - // reinstantiate the 'queryPerformedByRepos' boolean
69.69 - // [or we will need to wrap the repository in
69.70 - // a 'RepositoryInterceptor'?]
69.71 - // Also there's no real need for a DomainInterceptor to
69.72 - // extend RewritingMBeanServerConnection.
69.73 -
69.74 -
69.75 - /**
69.76 - * A logger for this class.
69.77 - **/
69.78 - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
69.79 -
69.80 - private final String domainName;
69.81 - private volatile ObjectName ALL;
69.82 - private final String serverName;
69.83 - private volatile NotificationListener mbsListener;
69.84 -
69.85 - private static class PatternNotificationFilter
69.86 - implements NotificationFilter {
69.87 -
69.88 - final ObjectName pattern;
69.89 - public PatternNotificationFilter(ObjectName pattern) {
69.90 - this.pattern = pattern==null?ObjectName.WILDCARD:pattern;
69.91 - }
69.92 -
69.93 - public boolean isNotificationEnabled(Notification notification) {
69.94 - if (!(notification instanceof MBeanServerNotification))
69.95 - return false;
69.96 - final MBeanServerNotification mbsn =
69.97 - (MBeanServerNotification) notification;
69.98 - if (pattern.apply(mbsn.getMBeanName()))
69.99 - return true;
69.100 - return false;
69.101 - }
69.102 -
69.103 - static final long serialVersionUID = 7409950927025262111L;
69.104 - }
69.105 -
69.106 - /**
69.107 - * Creates a new instance of NamespaceInterceptor
69.108 - */
69.109 - public DomainInterceptor(String serverName,
69.110 - JMXDomain handler,
69.111 - String domainName) {
69.112 - super(handler);
69.113 - this.domainName = domainName;
69.114 - this.serverName = serverName;
69.115 - ALL = ObjectName.valueOf(domainName+":*");
69.116 - }
69.117 -
69.118 - @Override
69.119 - public String toString() {
69.120 - return this.getClass().getName()+"(parent="+serverName+
69.121 - ", domain="+this.domainName+")";
69.122 - }
69.123 -
69.124 - final void connectDelegate(final MBeanServerDelegate delegate)
69.125 - throws InstanceNotFoundException {
69.126 - final NotificationFilter filter =
69.127 - new PatternNotificationFilter(getPatternFor(null));
69.128 - synchronized (this) {
69.129 - if (mbsListener == null) {
69.130 - mbsListener = new NotificationListener() {
69.131 - public void handleNotification(Notification notification,
69.132 - Object handback) {
69.133 - if (filter.isNotificationEnabled(notification))
69.134 - delegate.sendNotification(notification);
69.135 - }
69.136 - };
69.137 - }
69.138 - }
69.139 -
69.140 - getHandlerInterceptorMBean().
69.141 - addMBeanServerNotificationListener(mbsListener, filter);
69.142 - }
69.143 -
69.144 - final void disconnectDelegate()
69.145 - throws InstanceNotFoundException, ListenerNotFoundException {
69.146 - final NotificationListener l;
69.147 - synchronized (this) {
69.148 - l = mbsListener;
69.149 - if (l == null) return;
69.150 - mbsListener = null;
69.151 - }
69.152 - getHandlerInterceptorMBean().removeMBeanServerNotificationListener(l);
69.153 - }
69.154 -
69.155 - public final void addPostRegisterTask(Queue<Runnable> queue,
69.156 - final MBeanServerDelegate delegate) {
69.157 - if (queue == null)
69.158 - throw new IllegalArgumentException("task queue must not be null");
69.159 - final Runnable task1 = new Runnable() {
69.160 - public void run() {
69.161 - try {
69.162 - connectDelegate(delegate);
69.163 - } catch (Exception x) {
69.164 - throw new UnsupportedOperationException(
69.165 - "notification forwarding",x);
69.166 - }
69.167 - }
69.168 - };
69.169 - queue.add(task1);
69.170 - }
69.171 -
69.172 - public final void addPostDeregisterTask(Queue<Runnable> queue,
69.173 - final MBeanServerDelegate delegate) {
69.174 - if (queue == null)
69.175 - throw new IllegalArgumentException("task queue must not be null");
69.176 - final Runnable task1 = new Runnable() {
69.177 - public void run() {
69.178 - try {
69.179 - disconnectDelegate();
69.180 - } catch (Exception x) {
69.181 - throw new UnsupportedOperationException(
69.182 - "notification forwarding",x);
69.183 - }
69.184 - }
69.185 - };
69.186 - queue.add(task1);
69.187 - }
69.188 -
69.189 - // No name conversion for JMXDomains...
69.190 - // Throws IllegalArgumentException if targetName.getDomain() is not
69.191 - // in the domain handled.
69.192 - //
69.193 - @Override
69.194 - protected ObjectName toSource(ObjectName targetName) {
69.195 - if (targetName == null) return null;
69.196 - if (targetName.isDomainPattern()) return targetName;
69.197 - final String targetDomain = targetName.getDomain();
69.198 -
69.199 - // TODO: revisit this. RuntimeOperationsException may be better?
69.200 - //
69.201 - if (!targetDomain.equals(domainName))
69.202 - throw new IllegalArgumentException(targetName.toString());
69.203 - return targetName;
69.204 - }
69.205 -
69.206 - // No name conversion for JMXDomains...
69.207 - @Override
69.208 - protected ObjectName toTarget(ObjectName sourceName) {
69.209 - return sourceName;
69.210 - }
69.211 -
69.212 -
69.213 -
69.214 - /**
69.215 - * No rewriting: always return sources - stripping instances for which
69.216 - * the caller doesn't have permissions.
69.217 - **/
69.218 - @Override
69.219 - Set<ObjectInstance> processOutputInstances(Set<ObjectInstance> sources) {
69.220 - if (sources == null || sources.isEmpty() || !checkOn())
69.221 - return sources;
69.222 - final Set<ObjectInstance> res = Util.equivalentEmptySet(sources);
69.223 - for (ObjectInstance o : sources) {
69.224 - if (checkQuery(o.getObjectName(), "queryMBeans"))
69.225 - res.add(o);
69.226 - }
69.227 - return res;
69.228 - }
69.229 -
69.230 -
69.231 - /**
69.232 - * No rewriting: always return sourceNames - stripping names for which
69.233 - * the caller doesn't have permissions.
69.234 - **/
69.235 - @Override
69.236 - Set<ObjectName> processOutputNames(Set<ObjectName> sourceNames) {
69.237 - if (sourceNames == null || sourceNames.isEmpty() || !checkOn())
69.238 - return sourceNames;
69.239 - final Set<ObjectName> res = Util.equivalentEmptySet(sourceNames);
69.240 - for (ObjectName o : sourceNames) {
69.241 - if (checkQuery(o, "queryNames"))
69.242 - res.add(o);
69.243 - }
69.244 - return res;
69.245 - }
69.246 -
69.247 - /** No rewriting: always return source **/
69.248 - @Override
69.249 - ObjectInstance processOutputInstance(ObjectInstance source) {
69.250 - return source;
69.251 - }
69.252 -
69.253 - @Override
69.254 - public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
69.255 - try {
69.256 - // We don't trust the wrapped JMXDomain...
69.257 - final ObjectName pattern = getPatternFor(name);
69.258 - final Set<ObjectName> res = super.queryNames(pattern,query);
69.259 - return Util.filterMatchingNames(pattern,res);
69.260 - } catch (Exception x) {
69.261 - if (LOG.isLoggable(Level.FINE))
69.262 - LOG.fine("Unexpected exception raised in queryNames: "+x);
69.263 - LOG.log(Level.FINEST,"Unexpected exception raised in queryNames",x);
69.264 - return Collections.emptySet();
69.265 - }
69.266 - }
69.267 -
69.268 - // Compute a new pattern which is a sub pattern of 'name' but only selects
69.269 - // the MBeans in domain 'domainName'
69.270 - // When we reach here, it has been verified that 'name' matches our domain
69.271 - // name (done by DomainDispatchInterceptor)
69.272 - private ObjectName getPatternFor(final ObjectName name) {
69.273 - if (name == null) return ALL;
69.274 - if (name.getDomain().equals(domainName)) return name;
69.275 - return name.withDomain(domainName);
69.276 - }
69.277 -
69.278 - @Override
69.279 - public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
69.280 - try {
69.281 - // We don't trust the wrapped JMXDomain...
69.282 - final ObjectName pattern = getPatternFor(name);
69.283 - final Set<ObjectInstance> res = super.queryMBeans(pattern,query);
69.284 - return Util.filterMatchingInstances(pattern,res);
69.285 - } catch (Exception x) {
69.286 - if (LOG.isLoggable(Level.FINE))
69.287 - LOG.fine("Unexpected exception raised in queryNames: "+x);
69.288 - LOG.log(Level.FINEST,"Unexpected exception raised in queryNames",x);
69.289 - return Collections.emptySet();
69.290 - }
69.291 - }
69.292 -
69.293 - @Override
69.294 - public String getDefaultDomain() {
69.295 - return domainName;
69.296 - }
69.297 -
69.298 - @Override
69.299 - public String[] getDomains() {
69.300 - return new String[] {domainName};
69.301 - }
69.302 -
69.303 - // We call getMBeanCount() on the namespace rather than on the
69.304 - // source server in order to avoid counting MBeans which are not
69.305 - // in the domain.
69.306 - @Override
69.307 - public Integer getMBeanCount() {
69.308 - return getHandlerInterceptorMBean().getMBeanCount();
69.309 - }
69.310 -
69.311 - private boolean checkOn() {
69.312 - final SecurityManager sm = System.getSecurityManager();
69.313 - return (sm != null);
69.314 - }
69.315 -
69.316 - //
69.317 - // Implements permission checks.
69.318 - //
69.319 - @Override
69.320 - void check(ObjectName routingName, String member, String action) {
69.321 - if (!checkOn()) return;
69.322 - final String act = (action==null)?"-":action;
69.323 - if("queryMBeans".equals(act) || "queryNames".equals(act)) {
69.324 - // This is tricky. check with 3 parameters is called
69.325 - // by queryNames/queryMBeans before performing the query.
69.326 - // At this point we must check with no class name.
69.327 - // Therefore we pass a className of "-".
69.328 - // The filtering will be done later - processOutputNames and
69.329 - // processOutputInstance will call checkQuery.
69.330 - //
69.331 - check(routingName, "-", "-", act);
69.332 - } else {
69.333 - // This is also tricky:
69.334 - // passing null here will cause check to retrieve the classname,
69.335 - // if needed.
69.336 - check(routingName, null, member, act);
69.337 - }
69.338 - }
69.339 -
69.340 - //
69.341 - // Implements permission checks.
69.342 - //
69.343 - @Override
69.344 - void checkCreate(ObjectName routingName, String className, String action) {
69.345 - if (!checkOn()) return;
69.346 - check(routingName,className,"-",action);
69.347 - }
69.348 -
69.349 - //
69.350 - // Implements permission checks.
69.351 - //
69.352 - void check(ObjectName routingName, String className, String member,
69.353 - String action) {
69.354 - if (!checkOn()) return;
69.355 - final MBeanPermission perm;
69.356 -
69.357 - final String act = (action==null)?"-":action;
69.358 - if ("getDomains".equals(act)) { // ES: OK
69.359 - perm = new MBeanPermission(serverName,"-",member,
69.360 - routingName,act);
69.361 - } else {
69.362 - final String clazz =
69.363 - (className==null)?getClassName(routingName):className;
69.364 - perm = new MBeanPermission(serverName,clazz,member,
69.365 - routingName,act);
69.366 - }
69.367 - final SecurityManager sm = System.getSecurityManager();
69.368 - if (sm != null)
69.369 - sm.checkPermission(perm);
69.370 - }
69.371 -
69.372 - String getClassName(ObjectName routingName) {
69.373 - if (routingName == null || routingName.isPattern()) return "-";
69.374 - try {
69.375 - return getHandlerInterceptorMBean().getSourceServer().
69.376 - getObjectInstance(routingName).getClassName();
69.377 - } catch (InstanceNotFoundException ex) {
69.378 - LOG.finest("Can't get class name for "+routingName+
69.379 - ", using \"-\". Cause is: "+ex);
69.380 - return "-";
69.381 - }
69.382 - }
69.383 -
69.384 - //
69.385 - // Implements permission filters for attributes...
69.386 - //
69.387 - @Override
69.388 - AttributeList checkAttributes(ObjectName routingName,
69.389 - AttributeList attributes, String action) {
69.390 - if (!checkOn()) return attributes;
69.391 - final String className = getClassName(routingName);
69.392 - check(routingName,className,"-",action);
69.393 - if (attributes == null || attributes.isEmpty()) return attributes;
69.394 - final AttributeList res = new AttributeList();
69.395 - for (Attribute at : attributes.asList()) {
69.396 - try {
69.397 - check(routingName,className,at.getName(),action);
69.398 - res.add(at);
69.399 - } catch (SecurityException x) { // DLS: OK
69.400 - continue;
69.401 - }
69.402 - }
69.403 - return res;
69.404 - }
69.405 -
69.406 - //
69.407 - // Implements permission filters for attributes...
69.408 - //
69.409 - @Override
69.410 - String[] checkAttributes(ObjectName routingName, String[] attributes,
69.411 - String action) {
69.412 - if (!checkOn()) return attributes;
69.413 - final String className = getClassName(routingName);
69.414 - check(routingName,className,"-",action);
69.415 - if (attributes == null || attributes.length==0) return attributes;
69.416 - final List<String> res = new ArrayList<String>(attributes.length);
69.417 - for (String at : attributes) {
69.418 - try {
69.419 - check(routingName,className,at,action);
69.420 - res.add(at);
69.421 - } catch (SecurityException x) { // DLS: OK
69.422 - continue;
69.423 - }
69.424 - }
69.425 - return res.toArray(new String[res.size()]);
69.426 - }
69.427 -
69.428 - //
69.429 - // Implements permission filters for domains...
69.430 - //
69.431 - @Override
69.432 - String[] checkDomains(String[] domains, String action) {
69.433 - if (domains == null || domains.length==0 || !checkOn())
69.434 - return domains;
69.435 - int count=0;
69.436 - for (int i=0;i<domains.length;i++) {
69.437 - try {
69.438 - check(ObjectName.valueOf(domains[i]+":x=x"),"-",
69.439 - "-","getDomains");
69.440 - } catch (SecurityException x) { // DLS: OK
69.441 - count++;
69.442 - domains[i]=null;
69.443 - }
69.444 - }
69.445 - if (count == 0) return domains;
69.446 - final String[] res = new String[domains.length-count];
69.447 - count = 0;
69.448 - for (int i=0;i<domains.length;i++)
69.449 - if (domains[i]!=null) res[count++]=domains[i];
69.450 - return res;
69.451 - }
69.452 -
69.453 - //
69.454 - // Implements permission filters for queries...
69.455 - //
69.456 - @Override
69.457 - boolean checkQuery(ObjectName routingName, String action) {
69.458 - try {
69.459 - final String className = getClassName(routingName);
69.460 - check(routingName,className,"-",action);
69.461 - return true;
69.462 - } catch (SecurityException x) { // DLS: OK
69.463 - return false;
69.464 - }
69.465 - }
69.466 -}
70.1 --- a/src/share/classes/com/sun/jmx/namespace/HandlerInterceptor.java Mon Nov 23 10:04:47 2009 +0000
70.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
70.3 @@ -1,734 +0,0 @@
70.4 -/*
70.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
70.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
70.7 - *
70.8 - * This code is free software; you can redistribute it and/or modify it
70.9 - * under the terms of the GNU General Public License version 2 only, as
70.10 - * published by the Free Software Foundation. Sun designates this
70.11 - * particular file as subject to the "Classpath" exception as provided
70.12 - * by Sun in the LICENSE file that accompanied this code.
70.13 - *
70.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
70.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
70.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
70.17 - * version 2 for more details (a copy is included in the LICENSE file that
70.18 - * accompanied this code).
70.19 - *
70.20 - * You should have received a copy of the GNU General Public License version
70.21 - * 2 along with this work; if not, write to the Free Software Foundation,
70.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
70.23 - *
70.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
70.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
70.26 - * have any questions.
70.27 - */
70.28 -
70.29 -package com.sun.jmx.namespace;
70.30 -
70.31 -
70.32 -import com.sun.jmx.defaults.JmxProperties;
70.33 -import com.sun.jmx.interceptor.MBeanServerInterceptor;
70.34 -
70.35 -import com.sun.jmx.mbeanserver.Util;
70.36 -import java.io.IOException;
70.37 -import java.io.ObjectInputStream;
70.38 -import java.util.Set;
70.39 -import java.util.logging.Level;
70.40 -import java.util.logging.Logger;
70.41 -
70.42 -import javax.management.Attribute;
70.43 -import javax.management.AttributeList;
70.44 -import javax.management.AttributeNotFoundException;
70.45 -import javax.management.InstanceAlreadyExistsException;
70.46 -import javax.management.InstanceNotFoundException;
70.47 -import javax.management.IntrospectionException;
70.48 -import javax.management.InvalidAttributeValueException;
70.49 -import javax.management.ListenerNotFoundException;
70.50 -import javax.management.MBeanException;
70.51 -import javax.management.MBeanInfo;
70.52 -import javax.management.MBeanRegistrationException;
70.53 -import javax.management.MBeanServer;
70.54 -import javax.management.NotCompliantMBeanException;
70.55 -import javax.management.NotificationFilter;
70.56 -import javax.management.NotificationListener;
70.57 -import javax.management.ObjectInstance;
70.58 -import javax.management.ObjectName;
70.59 -import javax.management.OperationsException;
70.60 -import javax.management.QueryExp;
70.61 -import javax.management.ReflectionException;
70.62 -import javax.management.RuntimeOperationsException;
70.63 -import javax.management.loading.ClassLoaderRepository;
70.64 -import javax.management.namespace.JMXNamespace;
70.65 -
70.66 -/**
70.67 - * This interceptor wraps a JMXNamespace, and performs
70.68 - * {@code ObjectName} rewriting. {@code HandlerInterceptor} are
70.69 - * created and managed by a {@link NamespaceDispatchInterceptor} or a
70.70 - * {@link DomainDispatchInterceptor}.
70.71 - * <p><b>
70.72 - * This API is a Sun internal API and is subject to changes without notice.
70.73 - * </b></p>
70.74 - * @since 1.7
70.75 - */
70.76 -public abstract class HandlerInterceptor<T extends JMXNamespace>
70.77 - extends RoutingMBeanServerConnection<MBeanServer>
70.78 - implements MBeanServerInterceptor {
70.79 -
70.80 - /**
70.81 - * A logger for this class.
70.82 - **/
70.83 - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
70.84 -
70.85 - // The wrapped JMXNamespace
70.86 - private final T handler;
70.87 -
70.88 - /**
70.89 - * Creates a new instance of HandlerInterceptor
70.90 - */
70.91 - public HandlerInterceptor(T handler) {
70.92 - if (handler == null) throw new IllegalArgumentException("null");
70.93 - this.handler = handler;
70.94 - }
70.95 -
70.96 - //
70.97 - // The {@code source} connection is a connection to the MBeanServer
70.98 - // that contains the actual MBeans.
70.99 - // In the case of cascading, that would be a connection to the sub
70.100 - // agent. Practically, this is JMXNamespace.getSourceServer();
70.101 - //
70.102 - @Override
70.103 - protected MBeanServer source() {
70.104 - return handler.getSourceServer();
70.105 - }
70.106 -
70.107 - // The MBeanServer on which getClassLoader / getClassLoaderFor
70.108 - // will be called.
70.109 - // The NamespaceInterceptor overrides this method - so that it
70.110 - // getClassLoader / getClassLoaderFor don't trigger the loop
70.111 - // detection mechanism.
70.112 - //
70.113 - MBeanServer getServerForLoading() {
70.114 - return source();
70.115 - }
70.116 -
70.117 - // The namespace or domain handler - this either a JMXNamespace or a
70.118 - // a JMXDomain
70.119 - T getHandlerInterceptorMBean() {
70.120 - return handler;
70.121 - }
70.122 -
70.123 - // If the underlying JMXNamespace throws an IO, the IO will be
70.124 - // wrapped in a RuntimeOperationsException.
70.125 - RuntimeException handleIOException(IOException x,String fromMethodName,
70.126 - Object... params) {
70.127 - // Must do something here?
70.128 - if (LOG.isLoggable(Level.FINEST)) {
70.129 - LOG.finest("IO Exception in "+fromMethodName+": "+x+
70.130 - " - "+" rethrowing as RuntimeOperationsException.");
70.131 - }
70.132 - throw new RuntimeOperationsException(
70.133 - Util.newRuntimeIOException(x));
70.134 - }
70.135 -
70.136 - // From MBeanServerConnection: catch & handles IOException
70.137 - @Override
70.138 - public AttributeList getAttributes(ObjectName name, String[] attributes)
70.139 - throws InstanceNotFoundException, ReflectionException {
70.140 - try {
70.141 - final String[] authorized =
70.142 - checkAttributes(name,attributes,"getAttribute");
70.143 - final AttributeList attrList =
70.144 - super.getAttributes(name,authorized);
70.145 - return attrList;
70.146 - } catch (IOException ex) {
70.147 - throw handleIOException(ex,"getAttributes",name,attributes);
70.148 - }
70.149 - }
70.150 -
70.151 - // From MBeanServer
70.152 - public ClassLoader getClassLoaderFor(ObjectName mbeanName)
70.153 - throws InstanceNotFoundException {
70.154 - final ObjectName sourceName = toSourceOrRuntime(mbeanName);
70.155 - try {
70.156 - check(mbeanName,null,"getClassLoaderFor");
70.157 - return getServerForLoading().getClassLoaderFor(sourceName);
70.158 - } catch (RuntimeException ex) {
70.159 - throw makeCompliantRuntimeException(ex);
70.160 - }
70.161 - }
70.162 -
70.163 -
70.164 - // From MBeanServer
70.165 - public ClassLoader getClassLoader(ObjectName loaderName)
70.166 - throws InstanceNotFoundException {
70.167 - final ObjectName sourceName = toSourceOrRuntime(loaderName);
70.168 - try {
70.169 - check(loaderName,null,"getClassLoader");
70.170 - return getServerForLoading().getClassLoader(sourceName);
70.171 - } catch (RuntimeException ex) {
70.172 - throw makeCompliantRuntimeException(ex);
70.173 - }
70.174 - }
70.175 -
70.176 - // From MBeanServer
70.177 - public ObjectInstance registerMBean(Object object, ObjectName name)
70.178 - throws InstanceAlreadyExistsException, MBeanRegistrationException,
70.179 - NotCompliantMBeanException {
70.180 - final ObjectName sourceName = newSourceMBeanName(name);
70.181 - try {
70.182 - checkCreate(name,object.getClass().getName(),"registerMBean");
70.183 - return processOutputInstance(
70.184 - source().registerMBean(object,sourceName));
70.185 - } catch (RuntimeException ex) {
70.186 - throw makeCompliantRuntimeException(ex);
70.187 - }
70.188 - }
70.189 -
70.190 - // From MBeanServerConnection: catch & handles IOException
70.191 - @Override
70.192 - public void removeNotificationListener(ObjectName name, ObjectName listener)
70.193 - throws InstanceNotFoundException, ListenerNotFoundException {
70.194 - try {
70.195 - check(name,null,"removeNotificationListener");
70.196 - super.removeNotificationListener(name,listener);
70.197 - } catch (IOException ex) {
70.198 - throw handleIOException(ex,"removeNotificationListener",name,listener);
70.199 - }
70.200 - }
70.201 -
70.202 - // From MBeanServerConnection: catch & handles IOException
70.203 - @Override
70.204 - public String getDefaultDomain() {
70.205 - try {
70.206 - return super.getDefaultDomain();
70.207 - } catch (IOException ex) {
70.208 - throw handleIOException(ex,"getDefaultDomain");
70.209 - }
70.210 - }
70.211 -
70.212 - // From MBeanServerConnection: catch & handles IOException
70.213 - @Override
70.214 - public String[] getDomains() {
70.215 - try {
70.216 - check(null,null,"getDomains");
70.217 - final String[] domains = super.getDomains();
70.218 - return checkDomains(domains,"getDomains");
70.219 - } catch (IOException ex) {
70.220 - throw handleIOException(ex,"getDomains");
70.221 - }
70.222 - }
70.223 -
70.224 - // From MBeanServerConnection: catch & handles IOException
70.225 - @Override
70.226 - public Integer getMBeanCount() {
70.227 - try {
70.228 - return super.getMBeanCount();
70.229 - } catch (IOException ex) {
70.230 - throw handleIOException(ex,"getMBeanCount");
70.231 - }
70.232 - }
70.233 -
70.234 - // From MBeanServerConnection: catch & handles IOException
70.235 - @Override
70.236 - public void setAttribute(ObjectName name, Attribute attribute)
70.237 - throws InstanceNotFoundException, AttributeNotFoundException,
70.238 - InvalidAttributeValueException, MBeanException,
70.239 - ReflectionException {
70.240 - try {
70.241 - check(name,
70.242 - (attribute==null?null:attribute.getName()),
70.243 - "setAttribute");
70.244 - super.setAttribute(name,attribute);
70.245 - } catch (IOException ex) {
70.246 - throw handleIOException(ex,"setAttribute",name, attribute);
70.247 - }
70.248 - }
70.249 -
70.250 - // From MBeanServerConnection: catch & handles IOException
70.251 - @Override
70.252 - public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
70.253 - if (name == null) name=ObjectName.WILDCARD;
70.254 - try {
70.255 - checkPattern(name,null,"queryNames");
70.256 - return super.queryNames(name,query);
70.257 - } catch (IOException ex) {
70.258 - throw handleIOException(ex,"queryNames",name, query);
70.259 - }
70.260 - }
70.261 -
70.262 - // From MBeanServerConnection: catch & handles IOException
70.263 - @Override
70.264 - public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
70.265 - if (name == null) name=ObjectName.WILDCARD;
70.266 - try {
70.267 - checkPattern(name,null,"queryMBeans");
70.268 - return super.queryMBeans(name,query);
70.269 - } catch (IOException ex) {
70.270 - throw handleIOException(ex,"queryMBeans",name, query);
70.271 - }
70.272 - }
70.273 -
70.274 - // From MBeanServerConnection: catch & handles IOException
70.275 - @Override
70.276 - public boolean isInstanceOf(ObjectName name, String className)
70.277 - throws InstanceNotFoundException {
70.278 - try {
70.279 - check(name, null, "isInstanceOf");
70.280 - return super.isInstanceOf(name, className);
70.281 - } catch (IOException ex) {
70.282 - throw handleIOException(ex,"isInstanceOf",name, className);
70.283 - }
70.284 - }
70.285 -
70.286 - // From MBeanServerConnection: catch & handles IOException
70.287 - @Override
70.288 - public ObjectInstance createMBean(String className, ObjectName name)
70.289 - throws ReflectionException, InstanceAlreadyExistsException,
70.290 - MBeanRegistrationException, MBeanException,
70.291 - NotCompliantMBeanException {
70.292 - try {
70.293 - checkCreate(name, className, "instantiate");
70.294 - checkCreate(name, className, "registerMBean");
70.295 - return super.createMBean(className, name);
70.296 - } catch (IOException ex) {
70.297 - throw handleIOException(ex,"createMBean",className, name);
70.298 - }
70.299 - }
70.300 -
70.301 - // From MBeanServerConnection: catch & handles IOException
70.302 - @Override
70.303 - public ObjectInstance createMBean(String className, ObjectName name,
70.304 - ObjectName loaderName)
70.305 - throws ReflectionException, InstanceAlreadyExistsException,
70.306 - MBeanRegistrationException, MBeanException,
70.307 - NotCompliantMBeanException, InstanceNotFoundException {
70.308 - try {
70.309 - checkCreate(name, className, "instantiate");
70.310 - checkCreate(name, className, "registerMBean");
70.311 - return super.createMBean(className, name, loaderName);
70.312 - } catch (IOException ex) {
70.313 - throw handleIOException(ex,"createMBean",className, name, loaderName);
70.314 - }
70.315 - }
70.316 -
70.317 - // From MBeanServerConnection: catch & handles IOException
70.318 - @Override
70.319 - public Object getAttribute(ObjectName name, String attribute)
70.320 - throws MBeanException, AttributeNotFoundException,
70.321 - InstanceNotFoundException, ReflectionException {
70.322 - try {
70.323 - check(name, attribute, "getAttribute");
70.324 - return super.getAttribute(name, attribute);
70.325 - } catch (IOException ex) {
70.326 - throw handleIOException(ex,"getAttribute",name, attribute);
70.327 - }
70.328 - }
70.329 -
70.330 - // From MBeanServerConnection: catch & handles IOException
70.331 - @Override
70.332 - public void removeNotificationListener(ObjectName name, ObjectName listener,
70.333 - NotificationFilter filter, Object handback)
70.334 - throws InstanceNotFoundException, ListenerNotFoundException {
70.335 - try {
70.336 - check(name,null,"removeNotificationListener");
70.337 - super.removeNotificationListener(name, listener, filter, handback);
70.338 - } catch (IOException ex) {
70.339 - throw handleIOException(ex,"removeNotificationListener",name,
70.340 - listener, filter, handback);
70.341 - }
70.342 - }
70.343 -
70.344 - // From MBeanServerConnection: catch & handles IOException
70.345 - @Override
70.346 - public void removeNotificationListener(ObjectName name,
70.347 - NotificationListener listener, NotificationFilter filter,
70.348 - Object handback)
70.349 - throws InstanceNotFoundException, ListenerNotFoundException {
70.350 - try {
70.351 - check(name,null,"removeNotificationListener");
70.352 - super.removeNotificationListener(name, listener, filter, handback);
70.353 - } catch (IOException ex) {
70.354 - throw handleIOException(ex,"removeNotificationListener",name,
70.355 - listener, filter, handback);
70.356 - }
70.357 - }
70.358 -
70.359 - // From MBeanServerConnection: catch & handles IOException
70.360 - @Override
70.361 - public void removeNotificationListener(ObjectName name,
70.362 - NotificationListener listener)
70.363 - throws InstanceNotFoundException, ListenerNotFoundException {
70.364 - try {
70.365 - check(name,null,"removeNotificationListener");
70.366 - super.removeNotificationListener(name, listener);
70.367 - } catch (IOException ex) {
70.368 - throw handleIOException(ex,"removeNotificationListener",name,
70.369 - listener);
70.370 - }
70.371 - }
70.372 -
70.373 - // From MBeanServerConnection: catch & handles IOException
70.374 - @Override
70.375 - public void addNotificationListener(ObjectName name,
70.376 - NotificationListener listener, NotificationFilter filter,
70.377 - Object handback) throws InstanceNotFoundException {
70.378 - try {
70.379 - check(name,null,"addNotificationListener");
70.380 - super.addNotificationListener(name, listener, filter, handback);
70.381 - } catch (IOException ex) {
70.382 - throw handleIOException(ex,"addNotificationListener",name,
70.383 - listener, filter, handback);
70.384 - }
70.385 - }
70.386 -
70.387 - // From MBeanServerConnection: catch & handles IOException
70.388 - @Override
70.389 - public void addNotificationListener(ObjectName name, ObjectName listener,
70.390 - NotificationFilter filter, Object handback)
70.391 - throws InstanceNotFoundException {
70.392 - try {
70.393 - check(name,null,"addNotificationListener");
70.394 - super.addNotificationListener(name, listener, filter, handback);
70.395 - } catch (IOException ex) {
70.396 - throw handleIOException(ex,"addNotificationListener",name,
70.397 - listener, filter, handback);
70.398 - }
70.399 - }
70.400 -
70.401 - // From MBeanServerConnection: catch & handles IOException
70.402 - @Override
70.403 - public boolean isRegistered(ObjectName name) {
70.404 - try {
70.405 - return super.isRegistered(name);
70.406 - } catch (IOException ex) {
70.407 - throw handleIOException(ex,"isRegistered",name);
70.408 - }
70.409 - }
70.410 -
70.411 - // From MBeanServerConnection: catch & handles IOException
70.412 - @Override
70.413 - public void unregisterMBean(ObjectName name)
70.414 - throws InstanceNotFoundException, MBeanRegistrationException {
70.415 - try {
70.416 - check(name, null, "unregisterMBean");
70.417 - super.unregisterMBean(name);
70.418 - } catch (IOException ex) {
70.419 - throw handleIOException(ex,"unregisterMBean",name);
70.420 - }
70.421 - }
70.422 -
70.423 - // From MBeanServerConnection: catch & handles IOException
70.424 - @Override
70.425 - public MBeanInfo getMBeanInfo(ObjectName name)
70.426 - throws InstanceNotFoundException, IntrospectionException,
70.427 - ReflectionException {
70.428 - try {
70.429 - check(name, null, "getMBeanInfo");
70.430 - return super.getMBeanInfo(name);
70.431 - } catch (IOException ex) {
70.432 - throw handleIOException(ex,"getMBeanInfo",name);
70.433 - }
70.434 - }
70.435 -
70.436 - // From MBeanServerConnection: catch & handles IOException
70.437 - @Override
70.438 - public ObjectInstance getObjectInstance(ObjectName name)
70.439 - throws InstanceNotFoundException {
70.440 - try {
70.441 - check(name, null, "getObjectInstance");
70.442 - return super.getObjectInstance(name);
70.443 - } catch (IOException ex) {
70.444 - throw handleIOException(ex,"getObjectInstance",name);
70.445 - }
70.446 - }
70.447 -
70.448 - // From MBeanServerConnection: catch & handles IOException
70.449 - @Override
70.450 - public ObjectInstance createMBean(String className, ObjectName name,
70.451 - Object[] params, String[] signature)
70.452 - throws ReflectionException, InstanceAlreadyExistsException,
70.453 - MBeanRegistrationException, MBeanException,
70.454 - NotCompliantMBeanException {
70.455 - try {
70.456 - checkCreate(name, className, "instantiate");
70.457 - checkCreate(name, className, "registerMBean");
70.458 - return super.createMBean(className, name, params, signature);
70.459 - } catch (IOException ex) {
70.460 - throw handleIOException(ex,"createMBean",className, name,
70.461 - params, signature);
70.462 - }
70.463 - }
70.464 -
70.465 - // From MBeanServerConnection: catch & handles IOException
70.466 - @Override
70.467 - public ObjectInstance createMBean(String className, ObjectName name,
70.468 - ObjectName loaderName, Object[] params, String[] signature)
70.469 - throws ReflectionException, InstanceAlreadyExistsException,
70.470 - MBeanRegistrationException, MBeanException,
70.471 - NotCompliantMBeanException, InstanceNotFoundException {
70.472 - try {
70.473 - checkCreate(name, className, "instantiate");
70.474 - checkCreate(name, className, "registerMBean");
70.475 - return super.createMBean(className, name, loaderName, params,
70.476 - signature);
70.477 - } catch (IOException ex) {
70.478 - throw handleIOException(ex,"createMBean",className, name,loaderName,
70.479 - params, signature);
70.480 - }
70.481 - }
70.482 -
70.483 - // From MBeanServerConnection: catch & handles IOException
70.484 - @Override
70.485 - public AttributeList setAttributes(ObjectName name,AttributeList attributes)
70.486 - throws InstanceNotFoundException, ReflectionException {
70.487 - try {
70.488 - final AttributeList authorized =
70.489 - checkAttributes(name, attributes, "setAttribute");
70.490 - return super.setAttributes(name, authorized);
70.491 - } catch (IOException ex) {
70.492 - throw handleIOException(ex,"setAttributes",name, attributes);
70.493 - }
70.494 - }
70.495 -
70.496 - // From MBeanServerConnection: catch & handles IOException
70.497 - @Override
70.498 - public Object invoke(ObjectName name, String operationName, Object[] params,
70.499 - String[] signature)
70.500 - throws InstanceNotFoundException, MBeanException, ReflectionException {
70.501 - try {
70.502 - check(name, operationName, "invoke");
70.503 - return super.invoke(name, operationName, params, signature);
70.504 - } catch (IOException ex) {
70.505 - throw handleIOException(ex,"invoke",name, operationName,
70.506 - params, signature);
70.507 - }
70.508 - }
70.509 -
70.510 - //
70.511 - // These methods are inherited from MBeanServer....
70.512 - //
70.513 -
70.514 - /**
70.515 - * This method should never be called.
70.516 - * Throws UnsupportedOperationException.
70.517 - */
70.518 - public Object instantiate(String className)
70.519 - throws ReflectionException, MBeanException {
70.520 - if (LOG.isLoggable(Level.FINE))
70.521 - LOG.fine("call to unsupported instantiate method: " +
70.522 - "trowing UnsupportedOperationException");
70.523 - throw new UnsupportedOperationException("Not applicable.");
70.524 - }
70.525 -
70.526 - /**
70.527 - * This method should never be called.
70.528 - * Throws UnsupportedOperationException.
70.529 - */
70.530 - public Object instantiate(String className, ObjectName loaderName)
70.531 - throws ReflectionException, MBeanException,
70.532 - InstanceNotFoundException {
70.533 - if (LOG.isLoggable(Level.FINE))
70.534 - LOG.fine("call to unsupported method: instantiate(...) -" +
70.535 - "throwing UnsupportedOperationException");
70.536 - throw new UnsupportedOperationException("Not applicable.");
70.537 - }
70.538 -
70.539 - /**
70.540 - * This method should never be called.
70.541 - * Throws UnsupportedOperationException.
70.542 - */
70.543 - public Object instantiate(String className, Object[] params,
70.544 - String[] signature) throws ReflectionException, MBeanException {
70.545 - if (LOG.isLoggable(Level.FINE))
70.546 - LOG.fine("call to unsupported method: instantiate(...) -" +
70.547 - "throwing UnsupportedOperationException");
70.548 - throw new UnsupportedOperationException("Not applicable.");
70.549 - }
70.550 -
70.551 - /**
70.552 - * This method should never be called.
70.553 - * Throws UnsupportedOperationException.
70.554 - */
70.555 - public Object instantiate(String className, ObjectName loaderName,
70.556 - Object[] params, String[] signature)
70.557 - throws ReflectionException, MBeanException,
70.558 - InstanceNotFoundException {
70.559 - if (LOG.isLoggable(Level.FINE))
70.560 - LOG.fine("call to unsupported method: instantiate(...) -" +
70.561 - "throwing UnsupportedOperationException");
70.562 - throw new UnsupportedOperationException("Not applicable.");
70.563 - }
70.564 -
70.565 - /**
70.566 - * This method should never be called.
70.567 - * Throws UnsupportedOperationException.
70.568 - */
70.569 - @Deprecated
70.570 - public ObjectInputStream deserialize(ObjectName name, byte[] data)
70.571 - throws InstanceNotFoundException, OperationsException {
70.572 - if (LOG.isLoggable(Level.FINE))
70.573 - LOG.fine("call to unsupported method: deserialize(...) -" +
70.574 - "throwing UnsupportedOperationException");
70.575 - throw new UnsupportedOperationException("Not applicable.");
70.576 - }
70.577 -
70.578 - /**
70.579 - * This method should never be called.
70.580 - * Throws UnsupportedOperationException.
70.581 - */
70.582 - @Deprecated
70.583 - public ObjectInputStream deserialize(String className, byte[] data)
70.584 - throws OperationsException, ReflectionException {
70.585 - if (LOG.isLoggable(Level.FINE))
70.586 - LOG.fine("call to unsupported method: deserialize(...) -" +
70.587 - "throwing UnsupportedOperationException");
70.588 - throw new UnsupportedOperationException("Not applicable.");
70.589 - }
70.590 -
70.591 - /**
70.592 - * This method should never be called.
70.593 - * Throws UnsupportedOperationException.
70.594 - */
70.595 - @Deprecated
70.596 - public ObjectInputStream deserialize(String className,
70.597 - ObjectName loaderName, byte[] data)
70.598 - throws InstanceNotFoundException, OperationsException,
70.599 - ReflectionException {
70.600 - if (LOG.isLoggable(Level.FINE))
70.601 - LOG.fine("call to unsupported method: deserialize(...) -" +
70.602 - "throwing UnsupportedOperationException");
70.603 - throw new UnsupportedOperationException("Not applicable.");
70.604 - }
70.605 -
70.606 - /**
70.607 - * This method should never be called.
70.608 - * Throws UnsupportedOperationException.
70.609 - */
70.610 - public ClassLoaderRepository getClassLoaderRepository() {
70.611 - if (LOG.isLoggable(Level.FINE))
70.612 - LOG.fine("call to unsupported method: getClassLoaderRepository() -" +
70.613 - "throwing UnsupportedOperationException");
70.614 - throw new UnsupportedOperationException("Not applicable.");
70.615 - }
70.616 -
70.617 - static RuntimeException newUnsupportedException(String namespace) {
70.618 - return new RuntimeOperationsException(
70.619 - new UnsupportedOperationException(
70.620 - "Not supported in this namespace: "+namespace));
70.621 - }
70.622 -
70.623 - /**
70.624 - * A result might be excluded for security reasons.
70.625 - */
70.626 - @Override
70.627 - boolean excludesFromResult(ObjectName targetName, String queryMethod) {
70.628 - return !checkQuery(targetName, queryMethod);
70.629 - }
70.630 -
70.631 -
70.632 - //----------------------------------------------------------------------
70.633 - // Hooks for checking permissions
70.634 - //----------------------------------------------------------------------
70.635 -
70.636 - /**
70.637 - * This method is a hook to implement permission checking in subclasses.
70.638 - * A subclass may override this method and throw a {@link
70.639 - * SecurityException} if the permission is denied.
70.640 - *
70.641 - * @param routingName The name of the MBean in the enclosing context.
70.642 - * This is of the form {@code <namespace>//<ObjectName>}.
70.643 - * @param member The {@link
70.644 - * javax.management.namespace.JMXNamespacePermission#getMember member}
70.645 - * name.
70.646 - * @param action The {@link
70.647 - * javax.management.namespace.JMXNamespacePermission#getActions action}
70.648 - * name.
70.649 - * @throws SecurityException if the caller doesn't have the permission
70.650 - * to perform the given action on the MBean pointed to
70.651 - * by routingName.
70.652 - */
70.653 - abstract void check(ObjectName routingName,
70.654 - String member, String action);
70.655 -
70.656 - // called in createMBean and registerMBean
70.657 - abstract void checkCreate(ObjectName routingName, String className,
70.658 - String action);
70.659 -
70.660 - /**
70.661 - * This is a hook to implement permission checking in subclasses.
70.662 - *
70.663 - * Checks that the caller has sufficient permission for returning
70.664 - * information about {@code sourceName} in {@code action}.
70.665 - *
70.666 - * Subclass may override this method and return false if the caller
70.667 - * doesn't have sufficient permissions.
70.668 - *
70.669 - * @param routingName The name of the MBean to include or exclude from
70.670 - * the query, expressed in the enclosing context.
70.671 - * This is of the form {@code <namespace>//<ObjectName>}.
70.672 - * @param action one of "queryNames" or "queryMBeans"
70.673 - * @return true if {@code sourceName} can be returned.
70.674 - */
70.675 - abstract boolean checkQuery(ObjectName routingName, String action);
70.676 -
70.677 - /**
70.678 - * This method is a hook to implement permission checking in subclasses.
70.679 - *
70.680 - * @param routingName The name of the MBean in the enclosing context.
70.681 - * This is of the form {@code <namespace>//<ObjectName>}.
70.682 - * @param attributes The list of attributes to check permission for.
70.683 - * @param action one of "getAttribute" or "setAttribute"
70.684 - * @return The list of attributes for which the callers has the
70.685 - * appropriate {@link
70.686 - * javax.management.namespace.JMXNamespacePermission}.
70.687 - * @throws SecurityException if the caller doesn't have the permission
70.688 - * to perform {@code action} on the MBean pointed to by routingName.
70.689 - */
70.690 - abstract String[] checkAttributes(ObjectName routingName,
70.691 - String[] attributes, String action);
70.692 -
70.693 - /**
70.694 - * This method is a hook to implement permission checking in subclasses.
70.695 - *
70.696 - * @param routingName The name of the MBean in the enclosing context.
70.697 - * This is of the form {@code <namespace>//<ObjectName>}.
70.698 - * @param attributes The list of attributes to check permission for.
70.699 - * @param action one of "getAttribute" or "setAttribute"
70.700 - * @return The list of attributes for which the callers has the
70.701 - * appropriate {@link
70.702 - * javax.management.namespace.JMXNamespacePermission}.
70.703 - * @throws SecurityException if the caller doesn't have the permission
70.704 - * to perform {@code action} on the MBean pointed to by routingName.
70.705 - */
70.706 - abstract AttributeList checkAttributes(ObjectName routingName,
70.707 - AttributeList attributes, String action);
70.708 -
70.709 - /**
70.710 - * This method is a hook to implement permission checking in subclasses.
70.711 - * Checks that the caller as the necessary permissions to view the
70.712 - * given domain. If not remove the domains for which the caller doesn't
70.713 - * have permission from the list.
70.714 - * <p>
70.715 - * By default, this method always returns {@code domains}
70.716 - *
70.717 - * @param domains The domains to return.
70.718 - * @param action "getDomains"
70.719 - * @return a filtered list of domains.
70.720 - */
70.721 - String[] checkDomains(String[] domains, String action) {
70.722 - return domains;
70.723 - }
70.724 -
70.725 - // A priori check for queryNames/queryMBeans/
70.726 - void checkPattern(ObjectName routingPattern,
70.727 - String member, String action) {
70.728 - // pattern is checked only at posteriori by checkQuery.
70.729 - // checking it a priori usually doesn't work, because ObjectName.apply
70.730 - // does not work between two patterns.
70.731 - // We only check that we have the permission requested for 'action'.
70.732 - check(null,null,action);
70.733 - }
70.734 -
70.735 -
70.736 -
70.737 -}
71.1 --- a/src/share/classes/com/sun/jmx/namespace/NamespaceInterceptor.java Mon Nov 23 10:04:47 2009 +0000
71.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
71.3 @@ -1,220 +0,0 @@
71.4 -/*
71.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
71.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
71.7 - *
71.8 - * This code is free software; you can redistribute it and/or modify it
71.9 - * under the terms of the GNU General Public License version 2 only, as
71.10 - * published by the Free Software Foundation. Sun designates this
71.11 - * particular file as subject to the "Classpath" exception as provided
71.12 - * by Sun in the LICENSE file that accompanied this code.
71.13 - *
71.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
71.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
71.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
71.17 - * version 2 for more details (a copy is included in the LICENSE file that
71.18 - * accompanied this code).
71.19 - *
71.20 - * You should have received a copy of the GNU General Public License version
71.21 - * 2 along with this work; if not, write to the Free Software Foundation,
71.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
71.23 - *
71.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
71.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
71.26 - * have any questions.
71.27 - */
71.28 -package com.sun.jmx.namespace;
71.29 -
71.30 -import java.util.ArrayList;
71.31 -import java.util.List;
71.32 -
71.33 -import javax.management.Attribute;
71.34 -import javax.management.AttributeList;
71.35 -import javax.management.MBeanServer;
71.36 -import javax.management.ObjectName;
71.37 -import javax.management.namespace.JMXNamespace;
71.38 -import javax.management.namespace.JMXNamespacePermission;
71.39 -
71.40 -/**
71.41 - * A NamespaceInterceptor wraps a JMXNamespace, performing
71.42 - * ObjectName rewriting.
71.43 - * <p><b>
71.44 - * This API is a Sun internal API and is subject to changes without notice.
71.45 - * </b></p>
71.46 - * @since 1.7
71.47 - */
71.48 -public class NamespaceInterceptor extends HandlerInterceptor<JMXNamespace> {
71.49 -
71.50 -
71.51 - // The target name space in which the NamepsaceHandler is mounted.
71.52 - private final String targetNs;
71.53 -
71.54 - private final String serverName;
71.55 -
71.56 - private final ObjectNameRouter proc;
71.57 -
71.58 - /**
71.59 - * Creates a new instance of NamespaceInterceptor
71.60 - */
71.61 - public NamespaceInterceptor(
71.62 - String serverName,
71.63 - JMXNamespace handler,
71.64 - String targetNamespace) {
71.65 - super(handler);
71.66 - this.serverName = serverName;
71.67 - this.targetNs =
71.68 - ObjectNameRouter.normalizeNamespacePath(targetNamespace,
71.69 - true, true, false);
71.70 - proc = new ObjectNameRouter(targetNamespace, "");
71.71 - }
71.72 -
71.73 - @Override
71.74 - public String toString() {
71.75 - return this.getClass().getName()+"(parent="+serverName+
71.76 - ", namespace="+this.targetNs+")";
71.77 - }
71.78 -
71.79 - /**
71.80 - * This method will send a probe to detect self-linking name spaces.
71.81 - * A self linking namespace is a namespace that links back directly
71.82 - * on itslef. Calling a method on such a name space always results
71.83 - * in an infinite loop going through:
71.84 - * [1]MBeanServer -> [2]NamespaceDispatcher -> [3]NamespaceInterceptor
71.85 - * [4]JMXNamespace -> { network // or cd // or ... } -> [5]MBeanServer
71.86 - * with exactly the same request than [1]...
71.87 - *
71.88 - * The namespace interceptor [2] tries to detect such condition the
71.89 - * *first time* that the connection is used. It does so by setting
71.90 - * a flag, and sending a queryNames() through the name space. If the
71.91 - * queryNames comes back, it knows that there's a loop.
71.92 - *
71.93 - * The DynamicProbe interface can also be used by a Sun JMXNamespace
71.94 - * implementation to request the emission of a probe at any time
71.95 - * (see JMXRemoteNamespace implementation).
71.96 - */
71.97 - private MBeanServer connection() {
71.98 - final MBeanServer c = super.source();
71.99 - if (c != null) return c;
71.100 - // should not come here
71.101 - throw new NullPointerException("getMBeanServerConnection");
71.102 - }
71.103 -
71.104 -
71.105 - @Override
71.106 - protected MBeanServer source() {
71.107 - return connection();
71.108 - }
71.109 -
71.110 - @Override
71.111 - protected MBeanServer getServerForLoading() {
71.112 - // don't want to send probe on getClassLoader/getClassLoaderFor
71.113 - return super.source();
71.114 - }
71.115 -
71.116 - @Override
71.117 - protected ObjectName toSource(ObjectName targetName) {
71.118 - return proc.toSourceContext(targetName, true);
71.119 - }
71.120 -
71.121 - @Override
71.122 - protected ObjectName toTarget(ObjectName sourceName) {
71.123 - return proc.toTargetContext(sourceName, false);
71.124 - }
71.125 -
71.126 - //
71.127 - // Implements permission checks.
71.128 - //
71.129 - @Override
71.130 - void check(ObjectName routingName, String member, String action) {
71.131 - final SecurityManager sm = System.getSecurityManager();
71.132 - if (sm == null) return;
71.133 - if ("getDomains".equals(action)) return;
71.134 - final JMXNamespacePermission perm =
71.135 - new JMXNamespacePermission(serverName,member,
71.136 - routingName,action);
71.137 - sm.checkPermission(perm);
71.138 - }
71.139 -
71.140 - @Override
71.141 - void checkCreate(ObjectName routingName, String className, String action) {
71.142 - final SecurityManager sm = System.getSecurityManager();
71.143 - if (sm == null) return;
71.144 - final JMXNamespacePermission perm =
71.145 - new JMXNamespacePermission(serverName,className,
71.146 - routingName,action);
71.147 - sm.checkPermission(perm);
71.148 - }
71.149 -
71.150 - //
71.151 - // Implements permission filters for attributes...
71.152 - //
71.153 - @Override
71.154 - AttributeList checkAttributes(ObjectName routingName,
71.155 - AttributeList attributes, String action) {
71.156 - check(routingName,null,action);
71.157 - if (attributes == null || attributes.isEmpty()) return attributes;
71.158 - final SecurityManager sm = System.getSecurityManager();
71.159 - if (sm == null) return attributes;
71.160 - final AttributeList res = new AttributeList();
71.161 - for (Attribute at : attributes.asList()) {
71.162 - try {
71.163 - check(routingName,at.getName(),action);
71.164 - res.add(at);
71.165 - } catch (SecurityException x) { // DLS: OK
71.166 - continue;
71.167 - }
71.168 - }
71.169 - return res;
71.170 - }
71.171 -
71.172 - //
71.173 - // Implements permission filters for attributes...
71.174 - //
71.175 - @Override
71.176 - String[] checkAttributes(ObjectName routingName, String[] attributes,
71.177 - String action) {
71.178 - check(routingName,null,action);
71.179 - if (attributes == null || attributes.length==0) return attributes;
71.180 - final SecurityManager sm = System.getSecurityManager();
71.181 - if (sm == null) return attributes;
71.182 - final List<String> res = new ArrayList<String>(attributes.length);
71.183 - for (String at : attributes) {
71.184 - try {
71.185 - check(routingName,at,action);
71.186 - res.add(at);
71.187 - } catch (SecurityException x) { // DLS: OK
71.188 - continue;
71.189 - }
71.190 - }
71.191 - return res.toArray(new String[res.size()]);
71.192 - }
71.193 -
71.194 - //
71.195 - // Implements permission filters for domains...
71.196 - //
71.197 - @Override
71.198 - String[] checkDomains(String[] domains, String action) {
71.199 - // in principle, this method is never called because
71.200 - // getDomains() will never be called - since there's
71.201 - // no way that MBeanServer.getDomains() can be routed
71.202 - // to a NamespaceInterceptor.
71.203 - //
71.204 - // This is also why there's no getDomains() in a
71.205 - // JMXNamespacePermission...
71.206 - //
71.207 - return super.checkDomains(domains, action);
71.208 - }
71.209 -
71.210 - //
71.211 - // Implements permission filters for queries...
71.212 - //
71.213 - @Override
71.214 - boolean checkQuery(ObjectName routingName, String action) {
71.215 - try {
71.216 - check(routingName,null,action);
71.217 - return true;
71.218 - } catch (SecurityException x) { // DLS: OK
71.219 - return false;
71.220 - }
71.221 - }
71.222 -
71.223 -}
72.1 --- a/src/share/classes/com/sun/jmx/namespace/ObjectNameRouter.java Mon Nov 23 10:04:47 2009 +0000
72.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
72.3 @@ -1,175 +0,0 @@
72.4 -/*
72.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
72.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
72.7 - *
72.8 - * This code is free software; you can redistribute it and/or modify it
72.9 - * under the terms of the GNU General Public License version 2 only, as
72.10 - * published by the Free Software Foundation. Sun designates this
72.11 - * particular file as subject to the "Classpath" exception as provided
72.12 - * by Sun in the LICENSE file that accompanied this code.
72.13 - *
72.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
72.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
72.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
72.17 - * version 2 for more details (a copy is included in the LICENSE file that
72.18 - * accompanied this code).
72.19 - *
72.20 - * You should have received a copy of the GNU General Public License version
72.21 - * 2 along with this work; if not, write to the Free Software Foundation,
72.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
72.23 - *
72.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
72.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
72.26 - * have any questions.
72.27 - */
72.28 -
72.29 -package com.sun.jmx.namespace;
72.30 -
72.31 -import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR;
72.32 -
72.33 -import javax.management.ObjectInstance;
72.34 -import javax.management.ObjectName;
72.35 -
72.36 -/**
72.37 - * The ObjectNameRouter is used to rewrite routing object names.
72.38 - * <p><b>
72.39 - * This API is a Sun internal API and is subject to changes without notice.
72.40 - * </b></p>
72.41 - * @since 1.7
72.42 - */
72.43 -public class ObjectNameRouter {
72.44 -
72.45 - private static final int NAMESPACE_SEPARATOR_LENGTH =
72.46 - NAMESPACE_SEPARATOR.length();
72.47 -
72.48 - final String targetPrefix;
72.49 - final String sourcePrefix;
72.50 - final int slen;
72.51 - final int tlen;
72.52 - final boolean identity;
72.53 -
72.54 - /** Creates a new instance of ObjectNameRouter */
72.55 - public ObjectNameRouter(final String remove, final String add) {
72.56 - this.targetPrefix = (remove==null?"":remove);
72.57 - this.sourcePrefix = (add==null?"":add);
72.58 - tlen = targetPrefix.length();
72.59 - slen = sourcePrefix.length();
72.60 - identity = targetPrefix.equals(sourcePrefix);
72.61 - }
72.62 -
72.63 - public final ObjectName toTargetContext(ObjectName sourceName,
72.64 - boolean removeLeadingSeparators) {
72.65 - if (sourceName == null) return null;
72.66 - if (identity) return sourceName;
72.67 - String srcDomain = sourceName.getDomain();
72.68 -
72.69 - // if the ObjectName starts with // and removeLeadingSeparators is
72.70 - // true, then recursively strip leading //.
72.71 - // Otherwise, do not rewrite ObjectName.
72.72 - //
72.73 - if (srcDomain.startsWith(NAMESPACE_SEPARATOR)) {
72.74 - if (!removeLeadingSeparators) return sourceName;
72.75 - else srcDomain = normalizeDomain(srcDomain,true);
72.76 - }
72.77 - if (slen != 0) {
72.78 - if (!srcDomain.startsWith(sourcePrefix) ||
72.79 - !srcDomain.startsWith(NAMESPACE_SEPARATOR,slen))
72.80 - throw new IllegalArgumentException(
72.81 - "ObjectName does not start with expected prefix "
72.82 - + sourcePrefix + ": " +
72.83 - String.valueOf(sourceName));
72.84 - srcDomain = srcDomain.substring(slen+NAMESPACE_SEPARATOR_LENGTH);
72.85 - }
72.86 - final String targetDomain =
72.87 - (tlen>0?targetPrefix+NAMESPACE_SEPARATOR+srcDomain:srcDomain);
72.88 - return sourceName.withDomain(targetDomain);
72.89 - }
72.90 -
72.91 - public final ObjectName toSourceContext(ObjectName targetName,
72.92 - boolean removeLeadingSeparators) {
72.93 - if (targetName == null) return null;
72.94 - if (identity) return targetName;
72.95 - String targetDomain = targetName.getDomain();
72.96 - if (targetDomain.startsWith(NAMESPACE_SEPARATOR)) {
72.97 - if (!removeLeadingSeparators) return targetName;
72.98 - else targetDomain =
72.99 - normalizeDomain(targetDomain,true);
72.100 - }
72.101 - if (tlen != 0) {
72.102 - if (!targetDomain.startsWith(targetPrefix) ||
72.103 - !targetDomain.startsWith(NAMESPACE_SEPARATOR,tlen))
72.104 - throw new IllegalArgumentException(
72.105 - "ObjectName does not start with expected prefix "
72.106 - + targetPrefix + ": " +
72.107 - String.valueOf(targetName));
72.108 - targetDomain = targetDomain.
72.109 - substring(tlen+NAMESPACE_SEPARATOR_LENGTH);
72.110 - }
72.111 - final String sourceDomain =
72.112 - (slen>0?sourcePrefix+NAMESPACE_SEPARATOR+targetDomain:
72.113 - targetDomain);
72.114 - return targetName.withDomain(sourceDomain);
72.115 - }
72.116 -
72.117 - public final ObjectInstance toTargetContext(ObjectInstance sourceMoi,
72.118 - boolean removeLeadingSeparators) {
72.119 - if (sourceMoi == null) return null;
72.120 - if (identity) return sourceMoi;
72.121 - return new ObjectInstance(
72.122 - toTargetContext(sourceMoi.getObjectName(),
72.123 - removeLeadingSeparators),
72.124 - sourceMoi.getClassName());
72.125 - }
72.126 -
72.127 - /**
72.128 - * Removes leading, trailing, or duplicate // in a name space path.
72.129 - **/
72.130 - public static String normalizeDomain(String domain,
72.131 - boolean removeLeadingSep) {
72.132 - return normalizeNamespacePath(domain,removeLeadingSep,false,true);
72.133 - }
72.134 -
72.135 - /**
72.136 - * Removes leading, trailing, or duplicate // in a name space path.
72.137 - **/
72.138 - public static String normalizeNamespacePath(String namespacePath,
72.139 - boolean removeLeadingSep,
72.140 - boolean removeTrailingSep,
72.141 - boolean endsWithDomain) {
72.142 - if (namespacePath.equals(""))
72.143 - return "";
72.144 - final String[] components = namespacePath.split(NAMESPACE_SEPARATOR);
72.145 - final StringBuilder b =
72.146 - new StringBuilder(namespacePath.length()+NAMESPACE_SEPARATOR_LENGTH);
72.147 - String sep = null;
72.148 - if (!removeLeadingSep && namespacePath.startsWith(NAMESPACE_SEPARATOR))
72.149 - b.append(NAMESPACE_SEPARATOR);
72.150 - int count = 0;
72.151 - for (int i=0; i<components.length; i++) {
72.152 - final String n=components[i];
72.153 - if (n.equals("")) continue;
72.154 - if (n.startsWith("/")||n.endsWith("/")) {
72.155 - // throw exception unless we're looking at the last domain
72.156 - // part of the ObjectName
72.157 - if (! (endsWithDomain && i==(components.length-1))) {
72.158 - throw new IllegalArgumentException(n+
72.159 - " is not a valid name space identifier");
72.160 - } else {
72.161 - // There's a dirty little corner case when the domain
72.162 - // part (last item) is exactly '/' - in that case we must
72.163 - // not append '//'
72.164 - //
72.165 - removeTrailingSep = removeTrailingSep || n.equals("/");
72.166 - }
72.167 - }
72.168 - if (sep != null) b.append(sep);
72.169 - b.append(n);
72.170 - sep = NAMESPACE_SEPARATOR;
72.171 - count++;
72.172 - }
72.173 - if (!removeTrailingSep && namespacePath.endsWith(NAMESPACE_SEPARATOR)
72.174 - && count > 0)
72.175 - b.append(NAMESPACE_SEPARATOR);
72.176 - return b.toString();
72.177 - }
72.178 -}
73.1 --- a/src/share/classes/com/sun/jmx/namespace/RoutingConnectionProxy.java Mon Nov 23 10:04:47 2009 +0000
73.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
73.3 @@ -1,106 +0,0 @@
73.4 -/*
73.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
73.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
73.7 - *
73.8 - * This code is free software; you can redistribute it and/or modify it
73.9 - * under the terms of the GNU General Public License version 2 only, as
73.10 - * published by the Free Software Foundation. Sun designates this
73.11 - * particular file as subject to the "Classpath" exception as provided
73.12 - * by Sun in the LICENSE file that accompanied this code.
73.13 - *
73.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
73.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
73.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
73.17 - * version 2 for more details (a copy is included in the LICENSE file that
73.18 - * accompanied this code).
73.19 - *
73.20 - * You should have received a copy of the GNU General Public License version
73.21 - * 2 along with this work; if not, write to the Free Software Foundation,
73.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
73.23 - *
73.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
73.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
73.26 - * have any questions.
73.27 - */
73.28 -
73.29 -package com.sun.jmx.namespace;
73.30 -
73.31 -
73.32 -import com.sun.jmx.defaults.JmxProperties;
73.33 -import java.util.logging.Level;
73.34 -import java.util.logging.Logger;
73.35 -
73.36 -import javax.management.MBeanServerConnection;
73.37 -
73.38 -
73.39 -/**
73.40 - * A RoutingConnectionProxy is an MBeanServerConnection proxy that proxies a
73.41 - * source name space in a source MBeanServerConnection.
73.42 - * It wraps a source MBeanServerConnection, and rewrites routing
73.43 - * ObjectNames. It is used to implement
73.44 - * {@code JMXNamespaces.narrowToNamespace(MBeanServerConnection)}.
73.45 - * <p><b>
73.46 - * This API is a Sun internal API and is subject to changes without notice.
73.47 - * </b></p>
73.48 - * @since 1.7
73.49 - */
73.50 -// See class hierarchy and detailled explanations in RoutingProxy in this
73.51 -// package.
73.52 -//
73.53 -public class RoutingConnectionProxy
73.54 - extends RoutingProxy<MBeanServerConnection> {
73.55 -
73.56 - /**
73.57 - * A logger for this class.
73.58 - **/
73.59 - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
73.60 -
73.61 -
73.62 - /**
73.63 - * Creates a new instance of RoutingConnectionProxy
73.64 - */
73.65 - public RoutingConnectionProxy(MBeanServerConnection source,
73.66 - String sourceDir,
73.67 - String targetDir,
73.68 - boolean probe) {
73.69 - super(source, sourceDir, targetDir, probe);
73.70 -
73.71 - if (LOG.isLoggable(Level.FINER))
73.72 - LOG.finer("RoutingConnectionProxy for " + getSourceNamespace() +
73.73 - " created");
73.74 - }
73.75 -
73.76 - @Override
73.77 - public String toString() {
73.78 - final String targetNs = getTargetNamespace();
73.79 - final String sourceNs = getSourceNamespace();
73.80 - String wrapped = String.valueOf(source());
73.81 - if ("".equals(targetNs)) {
73.82 - return "JMXNamespaces.narrowToNamespace("+
73.83 - wrapped+", \""+
73.84 - sourceNs+"\")";
73.85 - }
73.86 - return this.getClass().getSimpleName()+"("+wrapped+", \""+
73.87 - sourceNs+"\", \""+
73.88 - targetNs+"\")";
73.89 - }
73.90 -
73.91 - static final RoutingProxyFactory
73.92 - <MBeanServerConnection,RoutingConnectionProxy>
73.93 - FACTORY = new RoutingProxyFactory
73.94 - <MBeanServerConnection,RoutingConnectionProxy>() {
73.95 -
73.96 - public RoutingConnectionProxy newInstance(MBeanServerConnection source,
73.97 - String sourcePath, String targetPath, boolean probe) {
73.98 - return new RoutingConnectionProxy(source,sourcePath,
73.99 - targetPath, probe);
73.100 - }
73.101 - };
73.102 -
73.103 - public static MBeanServerConnection cd(
73.104 - MBeanServerConnection source, String sourcePath, boolean probe) {
73.105 - return RoutingProxy.cd(RoutingConnectionProxy.class, FACTORY,
73.106 - source, sourcePath, probe);
73.107 - }
73.108 -
73.109 -}
74.1 --- a/src/share/classes/com/sun/jmx/namespace/RoutingMBeanServerConnection.java Mon Nov 23 10:04:47 2009 +0000
74.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
74.3 @@ -1,556 +0,0 @@
74.4 -/*
74.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
74.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
74.7 - *
74.8 - * This code is free software; you can redistribute it and/or modify it
74.9 - * under the terms of the GNU General Public License version 2 only, as
74.10 - * published by the Free Software Foundation. Sun designates this
74.11 - * particular file as subject to the "Classpath" exception as provided
74.12 - * by Sun in the LICENSE file that accompanied this code.
74.13 - *
74.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
74.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
74.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
74.17 - * version 2 for more details (a copy is included in the LICENSE file that
74.18 - * accompanied this code).
74.19 - *
74.20 - * You should have received a copy of the GNU General Public License version
74.21 - * 2 along with this work; if not, write to the Free Software Foundation,
74.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
74.23 - *
74.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
74.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
74.26 - * have any questions.
74.27 - */
74.28 -
74.29 -package com.sun.jmx.namespace;
74.30 -
74.31 -import com.sun.jmx.defaults.JmxProperties;
74.32 -import com.sun.jmx.mbeanserver.Util;
74.33 -import java.io.IOException;
74.34 -import java.lang.reflect.UndeclaredThrowableException;
74.35 -import java.util.Set;
74.36 -import java.util.logging.Level;
74.37 -import java.util.logging.Logger;
74.38 -
74.39 -import javax.management.Attribute;
74.40 -import javax.management.AttributeList;
74.41 -import javax.management.AttributeNotFoundException;
74.42 -import javax.management.InstanceAlreadyExistsException;
74.43 -import javax.management.InstanceNotFoundException;
74.44 -import javax.management.IntrospectionException;
74.45 -import javax.management.InvalidAttributeValueException;
74.46 -import javax.management.JMRuntimeException;
74.47 -import javax.management.ListenerNotFoundException;
74.48 -import javax.management.MBeanException;
74.49 -import javax.management.MBeanInfo;
74.50 -import javax.management.MBeanRegistrationException;
74.51 -import javax.management.MBeanServerConnection;
74.52 -import javax.management.NotCompliantMBeanException;
74.53 -import javax.management.NotificationFilter;
74.54 -import javax.management.NotificationListener;
74.55 -import javax.management.ObjectInstance;
74.56 -import javax.management.ObjectName;
74.57 -import javax.management.QueryExp;
74.58 -import javax.management.ReflectionException;
74.59 -import javax.management.RuntimeMBeanException;
74.60 -import javax.management.RuntimeOperationsException;
74.61 -
74.62 -/**
74.63 - * A RoutingMBeanServerConnection wraps a MBeanServerConnection, defining
74.64 - * abstract methods that can be implemented by subclasses to rewrite
74.65 - * routing ObjectNames. It is used to implement
74.66 - * HandlerInterceptors (wrapping JMXNamespace instances) and routing
74.67 - * proxies (used to implement cd operations).
74.68 - * <p><b>
74.69 - * This API is a Sun internal API and is subject to changes without notice.
74.70 - * </b></p>
74.71 - * @since 1.7
74.72 - */
74.73 -public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnection>
74.74 - implements MBeanServerConnection {
74.75 -
74.76 - /**
74.77 - * A logger for this class.
74.78 - **/
74.79 - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
74.80 -
74.81 - /**
74.82 - * Creates a new instance of RoutingMBeanServerConnection
74.83 - */
74.84 - public RoutingMBeanServerConnection() {
74.85 - }
74.86 -
74.87 - /**
74.88 - * Returns the wrapped source connection. The {@code source} connection
74.89 - * is a connection to the MBeanServer that contains the actual MBean.
74.90 - * In the case of cascading, that would be a connection to the sub
74.91 - * agent.
74.92 - **/
74.93 - protected abstract T source() throws IOException;
74.94 -
74.95 - /**
74.96 - * Converts a target ObjectName to a source ObjectName.
74.97 - * The target ObjectName is the name of the MBean in the mount point
74.98 - * target. In the case of cascading, that would be the name of the
74.99 - * MBean in the master agent. So if a subagent S containing an MBean
74.100 - * named "X" is mounted in the target namespace "foo//" of a master agent M,
74.101 - * the source is S, the target is "foo//" in M, the source name is "X", and
74.102 - * the target name is "foo//X".
74.103 - * In the case of cascading - such as in NamespaceInterceptor, this method
74.104 - * will convert "foo//X" (the targetName) into "X", the source name.
74.105 - * @throws IllegalArgumentException if the name cannot be converted.
74.106 - **/
74.107 - protected abstract ObjectName toSource(ObjectName targetName);
74.108 - /**
74.109 - * Converts a source ObjectName to a target ObjectName.
74.110 - * (see description of toSource above for explanations)
74.111 - * In the case of cascading - such as in NamespaceInterceptor, this method
74.112 - * will convert "X" (the sourceName) into "foo//X", the target name.
74.113 - * @throws IllegalArgumentException if the name cannot be converted.
74.114 - **/
74.115 - protected abstract ObjectName toTarget(ObjectName sourceName);
74.116 -
74.117 - /**
74.118 - * Can be overridden by subclasses to check the validity of a new
74.119 - * ObjectName used in createMBean or registerMBean.
74.120 - * This method is typically used by subclasses which might require
74.121 - * special handling for "null";
74.122 - **/
74.123 - protected ObjectName newSourceMBeanName(ObjectName targetName)
74.124 - throws MBeanRegistrationException {
74.125 - try {
74.126 - return toSource(targetName);
74.127 - } catch (Exception x) {
74.128 - throw new MBeanRegistrationException(x,"Illegal MBean Name");
74.129 - }
74.130 - }
74.131 -
74.132 - // Calls toSource(), Wraps IllegalArgumentException.
74.133 - ObjectName toSourceOrRuntime(ObjectName targetName) {
74.134 - try {
74.135 - return toSource(targetName);
74.136 - } catch (RuntimeException x) {
74.137 - throw makeCompliantRuntimeException(x);
74.138 - }
74.139 - }
74.140 -
74.141 -
74.142 - // Wraps given exception if needed.
74.143 - RuntimeException makeCompliantRuntimeException(Exception x) {
74.144 - if (x instanceof SecurityException) return (SecurityException)x;
74.145 - if (x instanceof JMRuntimeException) return (JMRuntimeException)x;
74.146 - if (x instanceof RuntimeException)
74.147 - return new RuntimeOperationsException((RuntimeException)x);
74.148 - if (x instanceof IOException)
74.149 - return Util.newRuntimeIOException((IOException)x);
74.150 - // shouldn't come here...
74.151 - final RuntimeException x2 = new UndeclaredThrowableException(x);
74.152 - return new RuntimeOperationsException(x2);
74.153 - }
74.154 -
74.155 - // from MBeanServerConnection
74.156 - public AttributeList getAttributes(ObjectName name, String[] attributes)
74.157 - throws InstanceNotFoundException, ReflectionException, IOException {
74.158 - final ObjectName sourceName = toSourceOrRuntime(name);
74.159 - try {
74.160 - return source().getAttributes(sourceName, attributes);
74.161 - } catch (RuntimeException ex) {
74.162 - throw makeCompliantRuntimeException(ex);
74.163 - }
74.164 - }
74.165 -
74.166 - // from MBeanServerConnection
74.167 - public Object invoke(ObjectName name, String operationName, Object[] params,
74.168 - String[] signature)
74.169 - throws InstanceNotFoundException, MBeanException, ReflectionException,
74.170 - IOException {
74.171 - final ObjectName sourceName = toSourceOrRuntime(name);
74.172 - try {
74.173 - final Object result =
74.174 - source().invoke(sourceName,operationName,params,
74.175 - signature);
74.176 - return result;
74.177 - } catch (RuntimeException ex) {
74.178 - throw makeCompliantRuntimeException(ex);
74.179 - }
74.180 - }
74.181 -
74.182 - // from MBeanServerConnection
74.183 - public void unregisterMBean(ObjectName name)
74.184 - throws InstanceNotFoundException, MBeanRegistrationException,
74.185 - IOException {
74.186 - final ObjectName sourceName = toSourceOrRuntime(name);
74.187 - try {
74.188 - source().unregisterMBean(sourceName);
74.189 - } catch (RuntimeException ex) {
74.190 - throw makeCompliantRuntimeException(ex);
74.191 - }
74.192 - }
74.193 -
74.194 - // from MBeanServerConnection
74.195 - public MBeanInfo getMBeanInfo(ObjectName name)
74.196 - throws InstanceNotFoundException, IntrospectionException,
74.197 - ReflectionException, IOException {
74.198 - final ObjectName sourceName = toSourceOrRuntime(name);
74.199 - try {
74.200 - return source().getMBeanInfo(sourceName);
74.201 - } catch (RuntimeException ex) {
74.202 - throw makeCompliantRuntimeException(ex);
74.203 - }
74.204 - }
74.205 -
74.206 - // from MBeanServerConnection
74.207 - public ObjectInstance getObjectInstance(ObjectName name)
74.208 - throws InstanceNotFoundException, IOException {
74.209 - final ObjectName sourceName = toSourceOrRuntime(name);
74.210 - try {
74.211 - return processOutputInstance(
74.212 - source().getObjectInstance(sourceName));
74.213 - } catch (RuntimeException ex) {
74.214 - throw makeCompliantRuntimeException(ex);
74.215 - }
74.216 - }
74.217 -
74.218 - // from MBeanServerConnection
74.219 - public boolean isRegistered(ObjectName name) throws IOException {
74.220 - final ObjectName sourceName = toSourceOrRuntime(name);
74.221 - try {
74.222 - return source().isRegistered(sourceName);
74.223 - } catch (RuntimeMBeanException x) {
74.224 - throw new RuntimeOperationsException(x.getTargetException());
74.225 - } catch (RuntimeException x) {
74.226 - throw makeCompliantRuntimeException(x);
74.227 - }
74.228 - }
74.229 -
74.230 - // from MBeanServerConnection
74.231 - public void setAttribute(ObjectName name, Attribute attribute)
74.232 - throws InstanceNotFoundException, AttributeNotFoundException,
74.233 - InvalidAttributeValueException, MBeanException,
74.234 - ReflectionException, IOException {
74.235 - final ObjectName sourceName = toSourceOrRuntime(name);
74.236 - try {
74.237 - source().setAttribute(sourceName,attribute);
74.238 - } catch (RuntimeException ex) {
74.239 - throw makeCompliantRuntimeException(ex);
74.240 - }
74.241 - }
74.242 -
74.243 - // from MBeanServerConnection
74.244 - public ObjectInstance createMBean(String className,
74.245 - ObjectName name, ObjectName loaderName,
74.246 - Object[] params, String[] signature)
74.247 - throws ReflectionException, InstanceAlreadyExistsException,
74.248 - MBeanRegistrationException, MBeanException,
74.249 - NotCompliantMBeanException, InstanceNotFoundException, IOException {
74.250 - final ObjectName sourceName = newSourceMBeanName(name);
74.251 - // Loader Name is already a sourceLoaderName.
74.252 - final ObjectName sourceLoaderName = loaderName;
74.253 - try {
74.254 - final ObjectInstance instance =
74.255 - source().createMBean(className,sourceName,
74.256 - sourceLoaderName,
74.257 - params,signature);
74.258 - return processOutputInstance(instance);
74.259 - } catch (RuntimeException ex) {
74.260 - throw makeCompliantRuntimeException(ex);
74.261 - }
74.262 - }
74.263 -
74.264 - // from MBeanServerConnection
74.265 - public ObjectInstance createMBean(String className, ObjectName name,
74.266 - Object[] params, String[] signature)
74.267 - throws ReflectionException, InstanceAlreadyExistsException,
74.268 - MBeanRegistrationException, MBeanException,
74.269 - NotCompliantMBeanException, IOException {
74.270 - final ObjectName sourceName = newSourceMBeanName(name);
74.271 - try {
74.272 - return processOutputInstance(source().createMBean(className,
74.273 - sourceName,params,signature));
74.274 - } catch (RuntimeException ex) {
74.275 - throw makeCompliantRuntimeException(ex);
74.276 - }
74.277 - }
74.278 -
74.279 - // from MBeanServerConnection
74.280 - public ObjectInstance createMBean(String className, ObjectName name,
74.281 - ObjectName loaderName)
74.282 - throws ReflectionException, InstanceAlreadyExistsException,
74.283 - MBeanRegistrationException, MBeanException,
74.284 - NotCompliantMBeanException, InstanceNotFoundException, IOException {
74.285 - final ObjectName sourceName = newSourceMBeanName(name);
74.286 - // Loader Name is already a source Loader Name.
74.287 - final ObjectName sourceLoaderName = loaderName;
74.288 - try {
74.289 - return processOutputInstance(source().createMBean(className,
74.290 - sourceName,sourceLoaderName));
74.291 - } catch (RuntimeException ex) {
74.292 - throw makeCompliantRuntimeException(ex);
74.293 - }
74.294 - }
74.295 -
74.296 - // from MBeanServerConnection
74.297 - public ObjectInstance createMBean(String className, ObjectName name)
74.298 - throws ReflectionException, InstanceAlreadyExistsException,
74.299 - MBeanRegistrationException, MBeanException,
74.300 - NotCompliantMBeanException, IOException {
74.301 - final ObjectName sourceName = newSourceMBeanName(name);
74.302 - try {
74.303 - return processOutputInstance(source().
74.304 - createMBean(className,sourceName));
74.305 - } catch (RuntimeException ex) {
74.306 - throw makeCompliantRuntimeException(ex);
74.307 - }
74.308 - }
74.309 -
74.310 - // from MBeanServerConnection
74.311 - public Object getAttribute(ObjectName name, String attribute)
74.312 - throws MBeanException, AttributeNotFoundException,
74.313 - InstanceNotFoundException, ReflectionException, IOException {
74.314 - final ObjectName sourceName = toSourceOrRuntime(name);
74.315 - try {
74.316 - return source().getAttribute(sourceName,attribute);
74.317 - } catch (RuntimeException ex) {
74.318 - throw makeCompliantRuntimeException(ex);
74.319 - }
74.320 - }
74.321 -
74.322 - // from MBeanServerConnection
74.323 - public boolean isInstanceOf(ObjectName name, String className)
74.324 - throws InstanceNotFoundException, IOException {
74.325 - final ObjectName sourceName = toSourceOrRuntime(name);
74.326 - try {
74.327 - return source().isInstanceOf(sourceName,className);
74.328 - } catch (RuntimeException ex) {
74.329 - throw makeCompliantRuntimeException(ex);
74.330 - }
74.331 - }
74.332 -
74.333 - // from MBeanServerConnection
74.334 - public AttributeList setAttributes(ObjectName name, AttributeList attributes)
74.335 - throws InstanceNotFoundException, ReflectionException, IOException {
74.336 - final ObjectName sourceName = toSourceOrRuntime(name);
74.337 - try {
74.338 - return source().
74.339 - setAttributes(sourceName,attributes);
74.340 - } catch (RuntimeException ex) {
74.341 - throw makeCompliantRuntimeException(ex);
74.342 - }
74.343 - }
74.344 -
74.345 - // Return names in the target's context.
74.346 - Set<ObjectInstance> processOutputInstances(Set<ObjectInstance> sources) {
74.347 -
74.348 - final Set<ObjectInstance> result = Util.equivalentEmptySet(sources);
74.349 - for (ObjectInstance i : sources) {
74.350 - try {
74.351 - final ObjectInstance target = processOutputInstance(i);
74.352 - if (excludesFromResult(target.getObjectName(), "queryMBeans"))
74.353 - continue;
74.354 - result.add(target);
74.355 - } catch (Exception x) {
74.356 - if (LOG.isLoggable(Level.FINE)) {
74.357 - LOG.fine("Skiping returned item: " +
74.358 - "Unexpected exception while processing " +
74.359 - "ObjectInstance: " + x);
74.360 - }
74.361 - continue;
74.362 - }
74.363 - }
74.364 - return result;
74.365 - }
74.366 -
74.367 -
74.368 - // Return names in the target's context.
74.369 - ObjectInstance processOutputInstance(ObjectInstance source) {
74.370 - if (source == null) return null;
74.371 - final ObjectName sourceName = source.getObjectName();
74.372 - try {
74.373 - final ObjectName targetName = toTarget(sourceName);
74.374 - return new ObjectInstance(targetName,source.getClassName());
74.375 - } catch (RuntimeException x) {
74.376 - throw makeCompliantRuntimeException(x);
74.377 - }
74.378 - }
74.379 -
74.380 - // Returns names in the target's context.
74.381 - Set<ObjectName> processOutputNames(Set<ObjectName> sourceNames) {
74.382 -
74.383 - final Set<ObjectName> names = Util.equivalentEmptySet(sourceNames);
74.384 - for (ObjectName n : sourceNames) {
74.385 - try {
74.386 - final ObjectName targetName = toTarget(n);
74.387 - if (excludesFromResult(targetName, "queryNames")) continue;
74.388 - names.add(targetName);
74.389 - } catch (Exception x) {
74.390 - if (LOG.isLoggable(Level.FINE)) {
74.391 - LOG.fine("Skiping returned item: " +
74.392 - "Unexpected exception while processing " +
74.393 - "ObjectInstance: " + x);
74.394 - }
74.395 - continue;
74.396 - }
74.397 - }
74.398 - return names;
74.399 - }
74.400 -
74.401 - // from MBeanServerConnection
74.402 - public Set<ObjectInstance> queryMBeans(ObjectName name,
74.403 - QueryExp query) throws IOException {
74.404 - if (name == null) name=ObjectName.WILDCARD;
74.405 - final ObjectName sourceName = toSourceOrRuntime(name);
74.406 - try {
74.407 - return processOutputInstances(
74.408 - source().queryMBeans(sourceName,query));
74.409 - } catch (RuntimeException ex) {
74.410 - throw makeCompliantRuntimeException(ex);
74.411 - }
74.412 - }
74.413 -
74.414 - // from MBeanServerConnection
74.415 -
74.416 - public Set<ObjectName> queryNames(ObjectName name, QueryExp query)
74.417 - throws IOException {
74.418 - if (name == null) name=ObjectName.WILDCARD;
74.419 - final ObjectName sourceName = toSourceOrRuntime(name);
74.420 - try {
74.421 - final Set<ObjectName> tmp = source().queryNames(sourceName,query);
74.422 - final Set<ObjectName> out = processOutputNames(tmp);
74.423 - //System.err.println("queryNames: out: "+out);
74.424 - return out;
74.425 - } catch (RuntimeException ex) {
74.426 - throw makeCompliantRuntimeException(ex);
74.427 - }
74.428 - }
74.429 -
74.430 - // from MBeanServerConnection
74.431 - public void removeNotificationListener(ObjectName name,
74.432 - NotificationListener listener)
74.433 - throws InstanceNotFoundException,
74.434 - ListenerNotFoundException, IOException {
74.435 - final ObjectName sourceName = toSourceOrRuntime(name);
74.436 - try {
74.437 - source().removeNotificationListener(sourceName,listener);
74.438 - } catch (RuntimeException ex) {
74.439 - throw makeCompliantRuntimeException(ex);
74.440 - }
74.441 - }
74.442 -
74.443 - // from MBeanServerConnection
74.444 - public void addNotificationListener(ObjectName name, ObjectName listener,
74.445 - NotificationFilter filter, Object handback)
74.446 - throws InstanceNotFoundException, IOException {
74.447 - final ObjectName sourceName = toSourceOrRuntime(name);
74.448 - // Listener name is already a source listener name.
74.449 - try {
74.450 - source().addNotificationListener(sourceName,listener,
74.451 - filter,handback);
74.452 - } catch (RuntimeException ex) {
74.453 - throw makeCompliantRuntimeException(ex);
74.454 - }
74.455 - }
74.456 -
74.457 - // from MBeanServerConnection
74.458 - public void addNotificationListener(ObjectName name,
74.459 - NotificationListener listener, NotificationFilter filter,
74.460 - Object handback) throws InstanceNotFoundException, IOException {
74.461 - final ObjectName sourceName = toSourceOrRuntime(name);
74.462 - try {
74.463 - source().addNotificationListener(sourceName, listener, filter,
74.464 - handback);
74.465 - } catch (RuntimeException ex) {
74.466 - throw makeCompliantRuntimeException(ex);
74.467 - }
74.468 - }
74.469 -
74.470 -
74.471 - // from MBeanServerConnection
74.472 - public void removeNotificationListener(ObjectName name,
74.473 - NotificationListener listener, NotificationFilter filter,
74.474 - Object handback)
74.475 - throws InstanceNotFoundException, ListenerNotFoundException,
74.476 - IOException {
74.477 - final ObjectName sourceName = toSourceOrRuntime(name);
74.478 - try {
74.479 - source().removeNotificationListener(sourceName,listener,filter,
74.480 - handback);
74.481 - } catch (RuntimeException ex) {
74.482 - throw makeCompliantRuntimeException(ex);
74.483 - }
74.484 - }
74.485 -
74.486 - // from MBeanServerConnection
74.487 - public void removeNotificationListener(ObjectName name, ObjectName listener,
74.488 - NotificationFilter filter, Object handback)
74.489 - throws InstanceNotFoundException, ListenerNotFoundException,
74.490 - IOException {
74.491 - final ObjectName sourceName = toSourceOrRuntime(name);
74.492 - try {
74.493 - source().removeNotificationListener(sourceName,listener,
74.494 - filter,handback);
74.495 - } catch (RuntimeException ex) {
74.496 - throw makeCompliantRuntimeException(ex);
74.497 - }
74.498 - }
74.499 -
74.500 - // from MBeanServerConnection
74.501 - public void removeNotificationListener(ObjectName name, ObjectName listener)
74.502 - throws InstanceNotFoundException, ListenerNotFoundException,
74.503 - IOException {
74.504 - final ObjectName sourceName = toSourceOrRuntime(name);
74.505 - // listener name is already a source name...
74.506 - final ObjectName sourceListener = listener;
74.507 - try {
74.508 - source().removeNotificationListener(sourceName,sourceListener);
74.509 - } catch (RuntimeException ex) {
74.510 - throw makeCompliantRuntimeException(ex);
74.511 - }
74.512 - }
74.513 -
74.514 - // from MBeanServerConnection
74.515 - public Integer getMBeanCount() throws IOException {
74.516 - try {
74.517 - return source().getMBeanCount();
74.518 - } catch (RuntimeException ex) {
74.519 - throw makeCompliantRuntimeException(ex);
74.520 - }
74.521 - }
74.522 -
74.523 - // from MBeanServerConnection
74.524 - public String[] getDomains() throws IOException {
74.525 - try {
74.526 - return source().getDomains();
74.527 - } catch (RuntimeException ex) {
74.528 - throw makeCompliantRuntimeException(ex);
74.529 - }
74.530 - }
74.531 -
74.532 - // from MBeanServerConnection
74.533 - public String getDefaultDomain() throws IOException {
74.534 - try {
74.535 - return source().getDefaultDomain();
74.536 - } catch (RuntimeException ex) {
74.537 - throw makeCompliantRuntimeException(ex);
74.538 - }
74.539 - }
74.540 -
74.541 - /**
74.542 - * Returns true if the given targetName must be excluded from the
74.543 - * query result.
74.544 - * In this base class, always return {@code false}.
74.545 - * By default all object names returned by the sources are
74.546 - * transmitted to the caller - there is no filtering.
74.547 - *
74.548 - * @param name A target object name expressed in the caller's
74.549 - * context. In the case of cascading, where the source
74.550 - * is a sub agent mounted on e.g. namespace "foo",
74.551 - * that would be a name prefixed by "foo//"...
74.552 - * @param queryMethod either "queryNames" or "queryMBeans".
74.553 - * @return true if the name must be excluded.
74.554 - */
74.555 - boolean excludesFromResult(ObjectName targetName, String queryMethod) {
74.556 - return false;
74.557 - }
74.558 -
74.559 -}
75.1 --- a/src/share/classes/com/sun/jmx/namespace/RoutingProxy.java Mon Nov 23 10:04:47 2009 +0000
75.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
75.3 @@ -1,395 +0,0 @@
75.4 -/*
75.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
75.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
75.7 - *
75.8 - * This code is free software; you can redistribute it and/or modify it
75.9 - * under the terms of the GNU General Public License version 2 only, as
75.10 - * published by the Free Software Foundation. Sun designates this
75.11 - * particular file as subject to the "Classpath" exception as provided
75.12 - * by Sun in the LICENSE file that accompanied this code.
75.13 - *
75.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
75.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
75.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
75.17 - * version 2 for more details (a copy is included in the LICENSE file that
75.18 - * accompanied this code).
75.19 - *
75.20 - * You should have received a copy of the GNU General Public License version
75.21 - * 2 along with this work; if not, write to the Free Software Foundation,
75.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
75.23 - *
75.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
75.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
75.26 - * have any questions.
75.27 - */
75.28 -
75.29 -package com.sun.jmx.namespace;
75.30 -
75.31 -import com.sun.jmx.defaults.JmxProperties;
75.32 -import java.io.IOException;
75.33 -import java.util.logging.Level;
75.34 -import java.util.logging.Logger;
75.35 -
75.36 -import javax.management.InstanceNotFoundException;
75.37 -import javax.management.MBeanException;
75.38 -import javax.management.MBeanRegistrationException;
75.39 -
75.40 -import javax.management.MBeanServerConnection;
75.41 -import javax.management.MalformedObjectNameException;
75.42 -import javax.management.ObjectName;
75.43 -import javax.management.namespace.JMXNamespaces;
75.44 -
75.45 -
75.46 -/**
75.47 - * A RoutingProxy narrows on a given name space in a
75.48 - * source object implementing MBeanServerConnection.
75.49 - * It is used to implement
75.50 - * {@code JMXNamespaces.narrowToNamespace(...)}.
75.51 - * This abstract class has two concrete subclasses:
75.52 - * <p>{@link RoutingConnectionProxy}: to narrow down into an
75.53 - * MBeanServerConnection.</p>
75.54 - * <p>{@link RoutingServerProxy}: to narrow down into an MBeanServer.</p>
75.55 - *
75.56 - * <p>This class can also be used to "broaden" from a namespace. The same
75.57 - * class is used for both purposes because in both cases all that happens
75.58 - * is that ObjectNames are rewritten in one way on the way in (e.g. the
75.59 - * parameter of getMBeanInfo) and another way on the way out (e.g. the
75.60 - * return value of queryNames).</p>
75.61 - *
75.62 - * <p>Specifically, if you narrow into "a//" then you want to add the
75.63 - * "a//" prefix to ObjectNames on the way in and subtract it on the way
75.64 - * out. But ClientContext uses this class to subtract the
75.65 - * "jmx.context//foo=bar//" prefix on the way in and add it back on the
75.66 - * way out.</p>
75.67 - *
75.68 - * <p><b>
75.69 - * This API is a Sun internal API and is subject to changes without notice.
75.70 - * </b></p>
75.71 - * @since 1.7
75.72 - */
75.73 -//
75.74 -// RoutingProxies are client side objects which are used to narrow down
75.75 -// into a namespace. They are used to perform ObjectName translation,
75.76 -// adding the namespace to the routing ObjectName before sending it over
75.77 -// to the source connection, and removing that prefix from results of
75.78 -// queries, createMBean, registerMBean, and getObjectInstance.
75.79 -// This translation is the opposite to that which is performed by
75.80 -// NamespaceInterceptors.
75.81 -//
75.82 -// There is however a special case where routing proxies are used on the
75.83 -// 'server' side to remove a namespace - rather than to add it:
75.84 -// This the case of ClientContext.
75.85 -// When an ObjectName like "jmx.context//c1=v1,c2=v2//D:k=v" reaches the
75.86 -// jmx.context namespace, a routing proxy is used to remove the prefix
75.87 -// c1=v1,c2=v2// from the routing objectname.
75.88 -//
75.89 -// For a RoutingProxy used in a narrowDownToNamespace operation, we have:
75.90 -// targetNs="" // targetNS is the namespace 'to remove'
75.91 -// sourceNS=<namespace-we-narrow-down-to> // namespace 'to add'
75.92 -//
75.93 -// For a RoutingProxy used in a ClientContext operation, we have:
75.94 -// targetNs=<encoded-context> // context must be removed from object name
75.95 -// sourceNs="" // nothing to add...
75.96 -//
75.97 -// Finally, in order to avoid too many layers of wrapping,
75.98 -// RoutingConnectionProxy and RoutingServerProxy can be created through a
75.99 -// factory method that can concatenate namespace paths in order to
75.100 -// return a single RoutingProxy - rather than wrapping a RoutingProxy inside
75.101 -// another RoutingProxy. See RoutingConnectionProxy.cd and
75.102 -// RoutingServerProxy.cd
75.103 -//
75.104 -// The class hierarchy is as follows:
75.105 -//
75.106 -// RoutingMBeanServerConnection
75.107 -// [abstract class for all routing interceptors,
75.108 -// such as RoutingProxies and HandlerInterceptors]
75.109 -// / \
75.110 -// / \
75.111 -// RoutingProxy HandlerInterceptor
75.112 -// [base class for [base class for server side
75.113 -// client-side objects used objects, created by
75.114 -// in narrowDownTo] DispatchInterceptors]
75.115 -// / \ | \
75.116 -// RoutingConnectionProxy \ | NamespaceInterceptor
75.117 -// [wraps MBeanServerConnection \ | [used to remove
75.118 -// objects] \ | namespace prefix and
75.119 -// RoutingServerProxy | wrap JMXNamespace]
75.120 -// [wraps MBeanServer |
75.121 -// Objects] |
75.122 -// DomainInterceptor
75.123 -// [used to wrap JMXDomain]
75.124 -//
75.125 -// RoutingProxies also differ from HandlerInterceptors in that they transform
75.126 -// calls to MBeanServerConnection operations that do not have any parameters
75.127 -// into a call to the underlying JMXNamespace MBean.
75.128 -// So for instance a call to:
75.129 -// JMXNamespaces.narrowDownToNamespace(conn,"foo").getDomains()
75.130 -// is transformed into
75.131 -// conn.getAttribute("foo//type=JMXNamespace","Domains");
75.132 -//
75.133 -public abstract class RoutingProxy<T extends MBeanServerConnection>
75.134 - extends RoutingMBeanServerConnection<T> {
75.135 -
75.136 - /**
75.137 - * A logger for this class.
75.138 - **/
75.139 - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
75.140 -
75.141 - // The source MBeanServerConnection
75.142 - private final T source;
75.143 -
75.144 - // The name space we're narrowing to (usually some name space in
75.145 - // the source MBeanServerConnection), e.g. "a" for the namespace
75.146 - // "a//". This is empty in the case of ClientContext described above.
75.147 - private final String sourceNs;
75.148 -
75.149 - // The name space we pretend to be mounted in. This is empty except
75.150 - // in the case of ClientContext described above (where it will be
75.151 - // something like "jmx.context//foo=bar".
75.152 - private final String targetNs;
75.153 -
75.154 - // The name of the JMXNamespace that handles the source name space
75.155 - private final ObjectName handlerName;
75.156 - private final ObjectNameRouter router;
75.157 - private volatile String defaultDomain = null;
75.158 -
75.159 - /**
75.160 - * Creates a new instance of RoutingProxy
75.161 - */
75.162 - protected RoutingProxy(T source,
75.163 - String sourceNs,
75.164 - String targetNs,
75.165 - boolean probe) {
75.166 - if (source == null) throw new IllegalArgumentException("null");
75.167 - this.sourceNs = JMXNamespaces.normalizeNamespaceName(sourceNs);
75.168 -
75.169 - // Usually sourceNs is not null, except when implementing
75.170 - // Client Contexts
75.171 - //
75.172 - if (sourceNs.equals("")) {
75.173 - this.handlerName = null;
75.174 - } else {
75.175 - // System.err.println("sourceNs: "+sourceNs);
75.176 - this.handlerName =
75.177 - JMXNamespaces.getNamespaceObjectName(this.sourceNs);
75.178 - if (probe) {
75.179 - try {
75.180 - if (!source.isRegistered(handlerName)) {
75.181 - InstanceNotFoundException infe =
75.182 - new InstanceNotFoundException(handlerName);
75.183 - throw new IllegalArgumentException(sourceNs +
75.184 - ": no such name space", infe);
75.185 - }
75.186 - } catch (IOException x) {
75.187 - throw new IllegalArgumentException("source stale: "+x,x);
75.188 - }
75.189 - }
75.190 - }
75.191 - this.source = source;
75.192 - this.targetNs = (targetNs==null?"":
75.193 - JMXNamespaces.normalizeNamespaceName(targetNs));
75.194 - this.router =
75.195 - new ObjectNameRouter(this.targetNs,this.sourceNs);
75.196 -
75.197 - if (LOG.isLoggable(Level.FINER))
75.198 - LOG.finer("RoutingProxy for " + this.sourceNs + " created");
75.199 - }
75.200 -
75.201 - @Override
75.202 - public T source() { return source; }
75.203 -
75.204 - @Override
75.205 - public ObjectName toSource(ObjectName targetName) {
75.206 - if (targetName == null) return null;
75.207 - if (targetName.getDomain().equals("") && targetNs.equals("")) {
75.208 - try {
75.209 - if (defaultDomain == null)
75.210 - defaultDomain = getDefaultDomain();
75.211 - } catch(Exception x) {
75.212 - LOG.log(Level.FINEST,"Failed to get default domain",x);
75.213 - }
75.214 - if (defaultDomain != null)
75.215 - targetName = targetName.withDomain(defaultDomain);
75.216 - }
75.217 - return router.toSourceContext(targetName,true);
75.218 - }
75.219 -
75.220 - @Override
75.221 - protected ObjectName newSourceMBeanName(ObjectName targetName)
75.222 - throws MBeanRegistrationException {
75.223 - if (targetName != null) return super.newSourceMBeanName(targetName);
75.224 -
75.225 - // OK => we can accept null if sourceNs is empty.
75.226 - if (sourceNs.equals("")) return null;
75.227 -
75.228 - throw new MBeanRegistrationException(
75.229 - new IllegalArgumentException(
75.230 - "Can't use null ObjectName with namespaces"));
75.231 - }
75.232 -
75.233 - @Override
75.234 - public ObjectName toTarget(ObjectName sourceName) {
75.235 - if (sourceName == null) return null;
75.236 - return router.toTargetContext(sourceName,false);
75.237 - }
75.238 -
75.239 - private Object getAttributeFromHandler(String attributeName)
75.240 - throws IOException {
75.241 -
75.242 - try {
75.243 - return source().getAttribute(handlerName,attributeName);
75.244 - } catch (RuntimeException ex) {
75.245 - throw makeCompliantRuntimeException(ex);
75.246 - } catch (IOException x) {
75.247 - throw x;
75.248 - } catch (MBeanException ex) {
75.249 - throw new IOException("Failed to get "+attributeName+": "+
75.250 - ex.getCause(),
75.251 - ex.getCause());
75.252 - } catch (Exception ex) {
75.253 - throw new IOException("Failed to get "+attributeName+": "+
75.254 - ex,ex);
75.255 - }
75.256 - }
75.257 -
75.258 - // We cannot call getMBeanCount() on the underlying
75.259 - // MBeanServerConnection, because it would return the number of
75.260 - // 'top-level' MBeans, not the number of MBeans in the name space
75.261 - // we are narrowing to. Instead we're calling getMBeanCount() on
75.262 - // the JMXNamespace that handles the source name space.
75.263 - //
75.264 - // There is however one particular case when the sourceNs is empty.
75.265 - // In that case, there's no handler - and the 'source' is the top
75.266 - // level namespace. In that particular case, handlerName will be null,
75.267 - // and we directly invoke the top level source().
75.268 - // This later complex case is only used when implementing ClientContexts.
75.269 - //
75.270 - @Override
75.271 - public Integer getMBeanCount() throws IOException {
75.272 - try {
75.273 - if (handlerName == null) return source().getMBeanCount();
75.274 - return (Integer) getAttributeFromHandler("MBeanCount");
75.275 - } catch (RuntimeException ex) {
75.276 - throw makeCompliantRuntimeException(ex);
75.277 - }
75.278 - }
75.279 -
75.280 - // We cannot call getDomains() on the underlying
75.281 - // MBeanServerConnection, because it would return the domains of
75.282 - // 'top-level' MBeans, not the domains of MBeans in the name space
75.283 - // we are narrowing to. Instead we're calling getDomains() on
75.284 - // the JMXNamespace that handles the source name space.
75.285 - //
75.286 - // There is however one particular case when the sourceNs is empty.
75.287 - // In that case, there's no handler - and the 'source' is the top
75.288 - // level namespace. In that particular case, handlerName will be null,
75.289 - // and we directly invoke the top level source().
75.290 - // This later complex case is only used when implementing ClientContexts.
75.291 - //
75.292 - @Override
75.293 - public String[] getDomains() throws IOException {
75.294 - try {
75.295 - if (handlerName == null) return source().getDomains();
75.296 - return (String[]) getAttributeFromHandler("Domains");
75.297 - } catch (RuntimeException ex) {
75.298 - throw makeCompliantRuntimeException(ex);
75.299 - }
75.300 - }
75.301 -
75.302 - // We cannot call getDefaultDomain() on the underlying
75.303 - // MBeanServerConnection, because it would return the default domain of
75.304 - // 'top-level' namespace, not the default domain in the name space
75.305 - // we are narrowing to. Instead we're calling getDefaultDomain() on
75.306 - // the JMXNamespace that handles the source name space.
75.307 - //
75.308 - // There is however one particular case when the sourceNs is empty.
75.309 - // In that case, there's no handler - and the 'source' is the top
75.310 - // level namespace. In that particular case, handlerName will be null,
75.311 - // and we directly invoke the top level source().
75.312 - // This later complex case is only used when implementing ClientContexts.
75.313 - //
75.314 - @Override
75.315 - public String getDefaultDomain() throws IOException {
75.316 - try {
75.317 - if (handlerName == null) {
75.318 - defaultDomain = source().getDefaultDomain();
75.319 - } else {
75.320 - defaultDomain =(String)
75.321 - getAttributeFromHandler("DefaultDomain");
75.322 - }
75.323 - return defaultDomain;
75.324 - } catch (RuntimeException ex) {
75.325 - throw makeCompliantRuntimeException(ex);
75.326 - }
75.327 - }
75.328 -
75.329 - public String getSourceNamespace() {
75.330 - return sourceNs;
75.331 - }
75.332 -
75.333 - public String getTargetNamespace() {
75.334 - return targetNs;
75.335 - }
75.336 -
75.337 - @Override
75.338 - public String toString() {
75.339 - return super.toString()+", sourceNs="+
75.340 - sourceNs + (targetNs.equals("")?"":
75.341 - (" mounted on targetNs="+targetNs));
75.342 - }
75.343 -
75.344 - // Creates an instance of a subclass 'R' of RoutingProxy<T>
75.345 - // RoutingServerProxy and RoutingConnectionProxy have their own factory
75.346 - // instance.
75.347 - static interface RoutingProxyFactory<T extends MBeanServerConnection,
75.348 - R extends RoutingProxy<T>> {
75.349 - public R newInstance(
75.350 - T source, String sourcePath, String targetPath, boolean probe);
75.351 - }
75.352 -
75.353 - // Performs a narrowDownToNamespace operation.
75.354 - // This method will attempt to merge two RoutingProxies in a single
75.355 - // one if they are of the same class.
75.356 - //
75.357 - // This method is never called directly - it should be called only by
75.358 - // subclasses of RoutingProxy.
75.359 - //
75.360 - // As for now it is called by:
75.361 - // RoutingServerProxy.cd and RoutingConnectionProxy.cd.
75.362 - //
75.363 - static <T extends MBeanServerConnection, R extends RoutingProxy<T>>
75.364 - R cd(Class<R> routingProxyClass,
75.365 - RoutingProxyFactory<T,R> factory,
75.366 - T source, String sourcePath, boolean probe) {
75.367 - if (source == null) throw new IllegalArgumentException("null");
75.368 - if (source.getClass().equals(routingProxyClass)) {
75.369 - // cast is OK here, but findbugs complains unless we use class.cast
75.370 - final R other = routingProxyClass.cast(source);
75.371 - final String target = other.getTargetNamespace();
75.372 -
75.373 - // Avoid multiple layers of serialization.
75.374 - //
75.375 - // We construct a new proxy from the original source instead of
75.376 - // stacking a new proxy on top of the old one.
75.377 - // - that is we replace
75.378 - // cd ( cd ( x, dir1), dir2);
75.379 - // by
75.380 - // cd (x, dir1//dir2);
75.381 - //
75.382 - // We can do this only when the source class is exactly
75.383 - // RoutingServerProxy.
75.384 - //
75.385 - if (target == null || target.equals("")) {
75.386 - final String path =
75.387 - JMXNamespaces.concat(other.getSourceNamespace(),
75.388 - sourcePath);
75.389 - return factory.newInstance(other.source(), path, "", probe);
75.390 - }
75.391 - // Note: we could do possibly something here - but it would involve
75.392 - // removing part of targetDir, and possibly adding
75.393 - // something to sourcePath.
75.394 - // Too complex to bother! => simply default to stacking...
75.395 - }
75.396 - return factory.newInstance(source, sourcePath, "", probe);
75.397 - }
75.398 -}
76.1 --- a/src/share/classes/com/sun/jmx/namespace/RoutingServerProxy.java Mon Nov 23 10:04:47 2009 +0000
76.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
76.3 @@ -1,576 +0,0 @@
76.4 -/*
76.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
76.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
76.7 - *
76.8 - * This code is free software; you can redistribute it and/or modify it
76.9 - * under the terms of the GNU General Public License version 2 only, as
76.10 - * published by the Free Software Foundation. Sun designates this
76.11 - * particular file as subject to the "Classpath" exception as provided
76.12 - * by Sun in the LICENSE file that accompanied this code.
76.13 - *
76.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
76.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
76.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
76.17 - * version 2 for more details (a copy is included in the LICENSE file that
76.18 - * accompanied this code).
76.19 - *
76.20 - * You should have received a copy of the GNU General Public License version
76.21 - * 2 along with this work; if not, write to the Free Software Foundation,
76.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
76.23 - *
76.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
76.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
76.26 - * have any questions.
76.27 - */
76.28 -
76.29 -package com.sun.jmx.namespace;
76.30 -
76.31 -
76.32 -import com.sun.jmx.mbeanserver.Util;
76.33 -import java.io.IOException;
76.34 -import java.io.ObjectInputStream;
76.35 -import java.lang.reflect.UndeclaredThrowableException;
76.36 -import java.util.Collections;
76.37 -import java.util.Set;
76.38 -
76.39 -import javax.management.Attribute;
76.40 -import javax.management.AttributeList;
76.41 -import javax.management.AttributeNotFoundException;
76.42 -import javax.management.InstanceAlreadyExistsException;
76.43 -import javax.management.InstanceNotFoundException;
76.44 -import javax.management.IntrospectionException;
76.45 -import javax.management.InvalidAttributeValueException;
76.46 -import javax.management.ListenerNotFoundException;
76.47 -import javax.management.MBeanException;
76.48 -import javax.management.MBeanInfo;
76.49 -import javax.management.MBeanRegistrationException;
76.50 -import javax.management.MBeanServer;
76.51 -import javax.management.NotCompliantMBeanException;
76.52 -import javax.management.NotificationFilter;
76.53 -import javax.management.NotificationListener;
76.54 -import javax.management.ObjectInstance;
76.55 -import javax.management.ObjectName;
76.56 -import javax.management.OperationsException;
76.57 -import javax.management.QueryExp;
76.58 -import javax.management.ReflectionException;
76.59 -import javax.management.loading.ClassLoaderRepository;
76.60 -
76.61 -/**
76.62 - * A RoutingServerProxy is an MBeanServer proxy that proxies a
76.63 - * source name space in a source MBeanServer.
76.64 - * It wraps a source MBeanServer, and rewrites routing ObjectNames.
76.65 - * It is typically use for implementing 'cd' operations, and
76.66 - * will add the source name space to routing ObjectNames at input,
76.67 - * and remove it at output.
76.68 - * <p><b>
76.69 - * This API is a Sun internal API and is subject to changes without notice.
76.70 - * </b></p>
76.71 - *
76.72 - * @since 1.7
76.73 - */
76.74 -// See class hierarchy and detailled explanations in RoutingProxy in this
76.75 -// package.
76.76 -//
76.77 -public class RoutingServerProxy
76.78 - extends RoutingProxy<MBeanServer>
76.79 - implements MBeanServer {
76.80 -
76.81 - public RoutingServerProxy(MBeanServer source,
76.82 - String sourceNs,
76.83 - String targetNs,
76.84 - boolean probe) {
76.85 - super(source, sourceNs, targetNs, probe);
76.86 - }
76.87 -
76.88 - /**
76.89 - * This method is called each time an IOException is raised when
76.90 - * trying to forward an operation to the underlying
76.91 - * MBeanServerConnection, as a result of calling
76.92 - * {@link #getMBeanServerConnection()} or as a result of invoking the
76.93 - * operation on the returned connection.
76.94 - * Subclasses may redefine this method if they need to perform any
76.95 - * specific handling of IOException (logging etc...).
76.96 - * @param x The raised IOException.
76.97 - * @param method The name of the method in which the exception was
76.98 - * raised. This is one of the methods of the MBeanServer
76.99 - * interface.
76.100 - * @return A RuntimeException that should be thrown by the caller.
76.101 - * In this default implementation, this is an
76.102 - * {@link UndeclaredThrowableException} wrapping <var>x</var>.
76.103 - **/
76.104 - protected RuntimeException handleIOException(IOException x,
76.105 - String method) {
76.106 - return Util.newRuntimeIOException(x);
76.107 - }
76.108 -
76.109 -
76.110 - //--------------------------------------------
76.111 - //--------------------------------------------
76.112 - //
76.113 - // Implementation of the MBeanServer interface
76.114 - //
76.115 - //--------------------------------------------
76.116 - //--------------------------------------------
76.117 - @Override
76.118 - public void addNotificationListener(ObjectName name,
76.119 - NotificationListener listener,
76.120 - NotificationFilter filter,
76.121 - Object handback)
76.122 - throws InstanceNotFoundException {
76.123 - try {
76.124 - super.addNotificationListener(name, listener,
76.125 - filter, handback);
76.126 - } catch (IOException x) {
76.127 - throw handleIOException(x,"addNotificationListener");
76.128 - }
76.129 - }
76.130 -
76.131 - @Override
76.132 - public void addNotificationListener(ObjectName name,
76.133 - ObjectName listener,
76.134 - NotificationFilter filter,
76.135 - Object handback)
76.136 - throws InstanceNotFoundException {
76.137 - try {
76.138 - super.addNotificationListener(name, listener,
76.139 - filter, handback);
76.140 - } catch (IOException x) {
76.141 - throw handleIOException(x,"addNotificationListener");
76.142 - }
76.143 - }
76.144 -
76.145 - @Override
76.146 - public ObjectInstance createMBean(String className, ObjectName name)
76.147 - throws
76.148 - ReflectionException,
76.149 - InstanceAlreadyExistsException,
76.150 - MBeanRegistrationException,
76.151 - MBeanException,
76.152 - NotCompliantMBeanException {
76.153 - try {
76.154 - return super.createMBean(className, name);
76.155 - } catch (IOException x) {
76.156 - throw handleIOException(x,"createMBean");
76.157 - }
76.158 - }
76.159 -
76.160 - @Override
76.161 - public ObjectInstance createMBean(String className, ObjectName name,
76.162 - Object params[], String signature[])
76.163 - throws
76.164 - ReflectionException,
76.165 - InstanceAlreadyExistsException,
76.166 - MBeanRegistrationException,
76.167 - MBeanException,
76.168 - NotCompliantMBeanException {
76.169 - try {
76.170 - return super.createMBean(className, name,
76.171 - params, signature);
76.172 - } catch (IOException x) {
76.173 - throw handleIOException(x,"createMBean");
76.174 - }
76.175 - }
76.176 -
76.177 - @Override
76.178 - public ObjectInstance createMBean(String className,
76.179 - ObjectName name,
76.180 - ObjectName loaderName)
76.181 - throws
76.182 - ReflectionException,
76.183 - InstanceAlreadyExistsException,
76.184 - MBeanRegistrationException,
76.185 - MBeanException,
76.186 - NotCompliantMBeanException,
76.187 - InstanceNotFoundException {
76.188 - try {
76.189 - return super.createMBean(className, name, loaderName);
76.190 - } catch (IOException x) {
76.191 - throw handleIOException(x,"createMBean");
76.192 - }
76.193 - }
76.194 -
76.195 - @Override
76.196 - public ObjectInstance createMBean(String className,
76.197 - ObjectName name,
76.198 - ObjectName loaderName,
76.199 - Object params[],
76.200 - String signature[])
76.201 - throws
76.202 - ReflectionException,
76.203 - InstanceAlreadyExistsException,
76.204 - MBeanRegistrationException,
76.205 - MBeanException,
76.206 - NotCompliantMBeanException,
76.207 - InstanceNotFoundException {
76.208 - try {
76.209 - return super.createMBean(className, name, loaderName,
76.210 - params, signature);
76.211 - } catch (IOException x) {
76.212 - throw handleIOException(x,"createMBean");
76.213 - }
76.214 - }
76.215 -
76.216 - /**
76.217 - * @deprecated see {@link MBeanServer#deserialize(ObjectName,byte[])
76.218 - * MBeanServer}
76.219 - **/
76.220 - @Deprecated
76.221 - public ObjectInputStream deserialize(ObjectName name, byte[] data)
76.222 - throws InstanceNotFoundException, OperationsException {
76.223 - final ObjectName sourceName = toSourceOrRuntime(name);
76.224 - try {
76.225 - return source().deserialize(sourceName,data);
76.226 - } catch (RuntimeException x) {
76.227 - throw makeCompliantRuntimeException(x);
76.228 - }
76.229 - }
76.230 -
76.231 - /**
76.232 - * @deprecated see {@link MBeanServer#deserialize(String,byte[])
76.233 - * MBeanServer}
76.234 - */
76.235 - @Deprecated
76.236 - public ObjectInputStream deserialize(String className, byte[] data)
76.237 - throws OperationsException, ReflectionException {
76.238 - try {
76.239 - return source().deserialize(className,data);
76.240 - } catch (RuntimeException x) {
76.241 - throw makeCompliantRuntimeException(x);
76.242 - }
76.243 - }
76.244 -
76.245 - /**
76.246 - * @deprecated see {@link MBeanServer#deserialize(String,ObjectName,byte[])
76.247 - * MBeanServer}
76.248 - */
76.249 - @Deprecated
76.250 - public ObjectInputStream deserialize(String className,
76.251 - ObjectName loaderName,
76.252 - byte[] data)
76.253 - throws
76.254 - InstanceNotFoundException,
76.255 - OperationsException,
76.256 - ReflectionException {
76.257 - try {
76.258 - return source().deserialize(className,loaderName,data);
76.259 - } catch (RuntimeException x) {
76.260 - throw makeCompliantRuntimeException(x);
76.261 - }
76.262 - }
76.263 -
76.264 - @Override
76.265 - public Object getAttribute(ObjectName name, String attribute)
76.266 - throws
76.267 - MBeanException,
76.268 - AttributeNotFoundException,
76.269 - InstanceNotFoundException,
76.270 - ReflectionException {
76.271 - try {
76.272 - return super.getAttribute(name, attribute);
76.273 - } catch (IOException x) {
76.274 - throw handleIOException(x,"getAttribute");
76.275 - }
76.276 - }
76.277 -
76.278 - @Override
76.279 - public AttributeList getAttributes(ObjectName name, String[] attributes)
76.280 - throws InstanceNotFoundException, ReflectionException {
76.281 - try {
76.282 - return super.getAttributes(name, attributes);
76.283 - } catch (IOException x) {
76.284 - throw handleIOException(x,"getAttributes");
76.285 - }
76.286 - }
76.287 -
76.288 - public ClassLoader getClassLoader(ObjectName loaderName)
76.289 - throws InstanceNotFoundException {
76.290 - final ObjectName sourceName = toSourceOrRuntime(loaderName);
76.291 - try {
76.292 - return source().getClassLoader(sourceName);
76.293 - } catch (RuntimeException x) {
76.294 - throw makeCompliantRuntimeException(x);
76.295 - }
76.296 - }
76.297 -
76.298 - public ClassLoader getClassLoaderFor(ObjectName mbeanName)
76.299 - throws InstanceNotFoundException {
76.300 - final ObjectName sourceName = toSourceOrRuntime(mbeanName);
76.301 - try {
76.302 - return source().getClassLoaderFor(sourceName);
76.303 - } catch (RuntimeException x) {
76.304 - throw makeCompliantRuntimeException(x);
76.305 - }
76.306 - }
76.307 -
76.308 - public ClassLoaderRepository getClassLoaderRepository() {
76.309 - try {
76.310 - return source().getClassLoaderRepository();
76.311 - } catch (RuntimeException x) {
76.312 - throw makeCompliantRuntimeException(x);
76.313 - }
76.314 - }
76.315 -
76.316 - @Override
76.317 - public String getDefaultDomain() {
76.318 - try {
76.319 - return super.getDefaultDomain();
76.320 - } catch (IOException x) {
76.321 - throw handleIOException(x,"getDefaultDomain");
76.322 - }
76.323 - }
76.324 -
76.325 - @Override
76.326 - public String[] getDomains() {
76.327 - try {
76.328 - return super.getDomains();
76.329 - } catch (IOException x) {
76.330 - throw handleIOException(x,"getDomains");
76.331 - }
76.332 - }
76.333 -
76.334 - @Override
76.335 - public Integer getMBeanCount() {
76.336 - try {
76.337 - return super.getMBeanCount();
76.338 - } catch (IOException x) {
76.339 - throw handleIOException(x,"getMBeanCount");
76.340 - }
76.341 - }
76.342 -
76.343 - @Override
76.344 - public MBeanInfo getMBeanInfo(ObjectName name)
76.345 - throws
76.346 - InstanceNotFoundException,
76.347 - IntrospectionException,
76.348 - ReflectionException {
76.349 - try {
76.350 - return super.getMBeanInfo(name);
76.351 - } catch (IOException x) {
76.352 - throw handleIOException(x,"getMBeanInfo");
76.353 - }
76.354 - }
76.355 -
76.356 - @Override
76.357 - public ObjectInstance getObjectInstance(ObjectName name)
76.358 - throws InstanceNotFoundException {
76.359 - try {
76.360 - return super.getObjectInstance(name);
76.361 - } catch (IOException x) {
76.362 - throw handleIOException(x,"getObjectInstance");
76.363 - }
76.364 - }
76.365 -
76.366 - public Object instantiate(String className)
76.367 - throws ReflectionException, MBeanException {
76.368 - try {
76.369 - return source().instantiate(className);
76.370 - } catch (RuntimeException x) {
76.371 - throw makeCompliantRuntimeException(x);
76.372 - }
76.373 - }
76.374 -
76.375 - public Object instantiate(String className,
76.376 - Object params[],
76.377 - String signature[])
76.378 - throws ReflectionException, MBeanException {
76.379 - try {
76.380 - return source().instantiate(className,
76.381 - params,signature);
76.382 - } catch (RuntimeException x) {
76.383 - throw makeCompliantRuntimeException(x);
76.384 - }
76.385 - }
76.386 -
76.387 - public Object instantiate(String className, ObjectName loaderName)
76.388 - throws ReflectionException, MBeanException,
76.389 - InstanceNotFoundException {
76.390 - final ObjectName srcLoaderName = toSourceOrRuntime(loaderName);
76.391 - try {
76.392 - return source().instantiate(className,srcLoaderName);
76.393 - } catch (RuntimeException x) {
76.394 - throw makeCompliantRuntimeException(x);
76.395 - }
76.396 - }
76.397 -
76.398 - public Object instantiate(String className, ObjectName loaderName,
76.399 - Object params[], String signature[])
76.400 - throws ReflectionException, MBeanException,
76.401 - InstanceNotFoundException {
76.402 - final ObjectName srcLoaderName = toSourceOrRuntime(loaderName);
76.403 - try {
76.404 - return source().instantiate(className,srcLoaderName,
76.405 - params,signature);
76.406 - } catch (RuntimeException x) {
76.407 - throw makeCompliantRuntimeException(x);
76.408 - }
76.409 - }
76.410 -
76.411 - @Override
76.412 - public Object invoke(ObjectName name, String operationName,
76.413 - Object params[], String signature[])
76.414 - throws
76.415 - InstanceNotFoundException,
76.416 - MBeanException,
76.417 - ReflectionException {
76.418 - try {
76.419 - return super.invoke(name,operationName,params,signature);
76.420 - } catch (IOException x) {
76.421 - throw handleIOException(x,"invoke");
76.422 - }
76.423 - }
76.424 -
76.425 - @Override
76.426 - public boolean isInstanceOf(ObjectName name, String className)
76.427 - throws InstanceNotFoundException {
76.428 - try {
76.429 - return super.isInstanceOf(name, className);
76.430 - } catch (IOException x) {
76.431 - throw handleIOException(x,"isInstanceOf");
76.432 - }
76.433 - }
76.434 -
76.435 - @Override
76.436 - public boolean isRegistered(ObjectName name) {
76.437 - try {
76.438 - return super.isRegistered(name);
76.439 - } catch (IOException x) {
76.440 - throw handleIOException(x,"isRegistered");
76.441 - }
76.442 - }
76.443 -
76.444 - @Override
76.445 - public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
76.446 - try {
76.447 - return super.queryMBeans(name, query);
76.448 - } catch (IOException x) {
76.449 - handleIOException(x,"queryMBeans");
76.450 - return Collections.emptySet();
76.451 - }
76.452 - }
76.453 -
76.454 - @Override
76.455 - public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
76.456 - try {
76.457 - return super.queryNames(name, query);
76.458 - } catch (IOException x) {
76.459 - handleIOException(x,"queryNames");
76.460 - return Collections.emptySet();
76.461 - }
76.462 - }
76.463 -
76.464 - public ObjectInstance registerMBean(Object object, ObjectName name)
76.465 - throws
76.466 - InstanceAlreadyExistsException,
76.467 - MBeanRegistrationException,
76.468 - NotCompliantMBeanException {
76.469 - final ObjectName sourceName = newSourceMBeanName(name);
76.470 - try {
76.471 - return processOutputInstance(
76.472 - source().registerMBean(object,sourceName));
76.473 - } catch (RuntimeException x) {
76.474 - throw makeCompliantRuntimeException(x);
76.475 - }
76.476 - }
76.477 -
76.478 - @Override
76.479 - public void removeNotificationListener(ObjectName name,
76.480 - NotificationListener listener)
76.481 - throws InstanceNotFoundException, ListenerNotFoundException {
76.482 - try {
76.483 - super.removeNotificationListener(name, listener);
76.484 - } catch (IOException x) {
76.485 - throw handleIOException(x,"removeNotificationListener");
76.486 - }
76.487 - }
76.488 -
76.489 - @Override
76.490 - public void removeNotificationListener(ObjectName name,
76.491 - NotificationListener listener,
76.492 - NotificationFilter filter,
76.493 - Object handback)
76.494 - throws InstanceNotFoundException, ListenerNotFoundException {
76.495 - try {
76.496 - super.removeNotificationListener(name, listener,
76.497 - filter, handback);
76.498 - } catch (IOException x) {
76.499 - throw handleIOException(x,"removeNotificationListener");
76.500 - }
76.501 - }
76.502 -
76.503 - @Override
76.504 - public void removeNotificationListener(ObjectName name,
76.505 - ObjectName listener)
76.506 - throws InstanceNotFoundException, ListenerNotFoundException {
76.507 - try {
76.508 - super.removeNotificationListener(name, listener);
76.509 - } catch (IOException x) {
76.510 - throw handleIOException(x,"removeNotificationListener");
76.511 - }
76.512 - }
76.513 -
76.514 - @Override
76.515 - public void removeNotificationListener(ObjectName name,
76.516 - ObjectName listener,
76.517 - NotificationFilter filter,
76.518 - Object handback)
76.519 - throws InstanceNotFoundException, ListenerNotFoundException {
76.520 - try {
76.521 - super.removeNotificationListener(name, listener,
76.522 - filter, handback);
76.523 - } catch (IOException x) {
76.524 - throw handleIOException(x,"removeNotificationListener");
76.525 - }
76.526 - }
76.527 -
76.528 - @Override
76.529 - public void setAttribute(ObjectName name, Attribute attribute)
76.530 - throws
76.531 - InstanceNotFoundException,
76.532 - AttributeNotFoundException,
76.533 - InvalidAttributeValueException,
76.534 - MBeanException,
76.535 - ReflectionException {
76.536 - try {
76.537 - super.setAttribute(name, attribute);
76.538 - } catch (IOException x) {
76.539 - throw handleIOException(x,"setAttribute");
76.540 - }
76.541 - }
76.542 -
76.543 - @Override
76.544 - public AttributeList setAttributes(ObjectName name,
76.545 - AttributeList attributes)
76.546 - throws InstanceNotFoundException, ReflectionException {
76.547 - try {
76.548 - return super.setAttributes(name, attributes);
76.549 - } catch (IOException x) {
76.550 - throw handleIOException(x,"setAttributes");
76.551 - }
76.552 - }
76.553 -
76.554 - @Override
76.555 - public void unregisterMBean(ObjectName name)
76.556 - throws InstanceNotFoundException, MBeanRegistrationException {
76.557 - try {
76.558 - super.unregisterMBean(name);
76.559 - } catch (IOException x) {
76.560 - throw handleIOException(x,"unregisterMBean");
76.561 - }
76.562 - }
76.563 -
76.564 - static final RoutingProxyFactory<MBeanServer,RoutingServerProxy>
76.565 - FACTORY = new RoutingProxyFactory<MBeanServer,RoutingServerProxy>() {
76.566 -
76.567 - public RoutingServerProxy newInstance(MBeanServer source,
76.568 - String sourcePath, String targetPath, boolean probe) {
76.569 - return new RoutingServerProxy(
76.570 - source, sourcePath, targetPath, probe);
76.571 - }
76.572 - };
76.573 -
76.574 - public static MBeanServer cd(
76.575 - MBeanServer source, String sourcePath, boolean probe) {
76.576 - return RoutingProxy.cd(RoutingServerProxy.class, FACTORY,
76.577 - source, sourcePath, probe);
76.578 - }
76.579 -}
77.1 --- a/src/share/classes/com/sun/jmx/namespace/package.html Mon Nov 23 10:04:47 2009 +0000
77.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
77.3 @@ -1,45 +0,0 @@
77.4 -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
77.5 -
77.6 -<html>
77.7 - <head>
77.8 - <title>The <code>com.sun.jmx.namespace</code> package</title>
77.9 -<!--
77.10 -Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
77.11 -DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
77.12 -
77.13 -This code is free software; you can redistribute it and/or modify it
77.14 -under the terms of the GNU General Public License version 2 only, as
77.15 -published by the Free Software Foundation. Sun designates this
77.16 -particular file as subject to the "Classpath" exception as provided
77.17 -by Sun in the LICENSE file that accompanied this code.
77.18 -
77.19 -This code is distributed in the hope that it will be useful, but WITHOUT
77.20 -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
77.21 -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
77.22 -version 2 for more details (a copy is included in the LICENSE file that
77.23 -accompanied this code).
77.24 -
77.25 -You should have received a copy of the GNU General Public License version
77.26 -2 along with this work; if not, write to the Free Software Foundation,
77.27 -Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
77.28 -
77.29 -Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
77.30 -CA 95054 USA or visit www.sun.com if you need additional information or
77.31 -have any questions.
77.32 --->
77.33 - </head>
77.34 - <body bgcolor="white">
77.35 - <p>The <code>com.sun.jmx.namespace</code> package contains
77.36 - sun specific implementation classes used to implement the
77.37 - JMX namespaces.
77.38 - </p>
77.39 - <p><b>DO NOT USE THESE CLASSES DIRECTLY</b></p>
77.40 - <p><b>
77.41 - This API is a Sun internal API and is subject to changes without notice.
77.42 - </b></p>
77.43 - <p>The public API through wich these proprietary classes can be
77.44 - invoked is located in <code>javax.management.namespace</code>
77.45 - package.
77.46 - </p>
77.47 - </body>
77.48 -</html>
78.1 --- a/src/share/classes/com/sun/jmx/namespace/serial/DefaultRewritingProcessor.java Mon Nov 23 10:04:47 2009 +0000
78.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
78.3 @@ -1,150 +0,0 @@
78.4 -/*
78.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
78.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
78.7 - *
78.8 - * This code is free software; you can redistribute it and/or modify it
78.9 - * under the terms of the GNU General Public License version 2 only, as
78.10 - * published by the Free Software Foundation. Sun designates this
78.11 - * particular file as subject to the "Classpath" exception as provided
78.12 - * by Sun in the LICENSE file that accompanied this code.
78.13 - *
78.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
78.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
78.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
78.17 - * version 2 for more details (a copy is included in the LICENSE file that
78.18 - * accompanied this code).
78.19 - *
78.20 - * You should have received a copy of the GNU General Public License version
78.21 - * 2 along with this work; if not, write to the Free Software Foundation,
78.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
78.23 - *
78.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
78.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
78.26 - * have any questions.
78.27 - */
78.28 -
78.29 -package com.sun.jmx.namespace.serial;
78.30 -
78.31 -
78.32 -import javax.management.ObjectInstance;
78.33 -import javax.management.ObjectName;
78.34 -
78.35 -/**
78.36 - * Class DefaultRewritingProcessor. Rewrite ObjectName in input & output
78.37 - * parameters.
78.38 - * <p><b>
78.39 - * This API is a Sun internal API and is subject to changes without notice.
78.40 - * </b></p>
78.41 - * @since 1.7
78.42 - */
78.43 -// We know that rewriting using serialization is costly.
78.44 -// This object tries to determine whether an object needs rewriting prior
78.45 -// to rewriting, and rewrites by creating a new object in those cases
78.46 -// where we know how to recreate a new object (e.g. a Notification).
78.47 -// Rewriting is however usually not used - so this object is just a
78.48 -// skeleton that eventually uses serialization...
78.49 -//
78.50 -class DefaultRewritingProcessor extends RewritingProcessor {
78.51 -
78.52 -
78.53 - private static enum RewriteMode {
78.54 - INPUT, // Input from target to source (parameters)
78.55 - OUTPUT // Output from source to target (results)
78.56 - };
78.57 -
78.58 - private final boolean identity;
78.59 -
78.60 - public DefaultRewritingProcessor(String targetDirName) {
78.61 - this(targetDirName,null);
78.62 - }
78.63 -
78.64 - /** Creates a new instance of SerialParamProcessor */
78.65 - public DefaultRewritingProcessor(final String remove, final String add) {
78.66 - super(new SerialRewritingProcessor(remove, add));
78.67 - identity = remove.equals(add);
78.68 - }
78.69 -
78.70 - private ObjectName rewriteObjectName(RewriteMode mode,
78.71 - ObjectName name) {
78.72 - return changeContext(mode, name);
78.73 - }
78.74 -
78.75 - private ObjectInstance rewriteObjectInstance(RewriteMode mode,
78.76 - ObjectInstance moi) {
78.77 - final ObjectName srcName = moi.getObjectName();
78.78 - final ObjectName targetName = changeContext(mode,srcName);
78.79 - if (targetName == srcName) return moi;
78.80 - return new ObjectInstance(targetName,moi.getClassName());
78.81 - }
78.82 -
78.83 -
78.84 - private Object processObject(RewriteMode mode, Object obj) {
78.85 - if (obj == null) return null;
78.86 -
78.87 - // Some things which will always needs rewriting:
78.88 - // ObjectName, ObjectInstance, and Notifications.
78.89 - // Take care of those we can handle here...
78.90 - //
78.91 - if (obj instanceof ObjectName)
78.92 - return rewriteObjectName(mode,(ObjectName) obj);
78.93 - else if (obj instanceof ObjectInstance)
78.94 - return rewriteObjectInstance(mode,(ObjectInstance) obj);
78.95 -
78.96 - // TODO: add other standard JMX classes - like e.g. MBeanInfo...
78.97 - //
78.98 -
78.99 - // Well, the object may contain an ObjectName => pass it to
78.100 - // our serial rewriting delegate...
78.101 - //
78.102 - return processAnyObject(mode,obj);
78.103 - }
78.104 -
78.105 -
78.106 - private Object processAnyObject(RewriteMode mode, Object obj) {
78.107 - switch (mode) {
78.108 - case INPUT:
78.109 - return super.rewriteInput(obj);
78.110 - case OUTPUT:
78.111 - return super.rewriteOutput(obj);
78.112 - default: // can't happen.
78.113 - throw new AssertionError();
78.114 - }
78.115 - }
78.116 -
78.117 - private ObjectName changeContext(RewriteMode mode, ObjectName name) {
78.118 - switch (mode) {
78.119 - case INPUT:
78.120 - return toSourceContext(name);
78.121 - case OUTPUT:
78.122 - return toTargetContext(name);
78.123 - default: // can't happen.
78.124 - throw new AssertionError();
78.125 - }
78.126 - }
78.127 -
78.128 - @Override
78.129 - public ObjectName toTargetContext(ObjectName srcName) {
78.130 - if (identity) return srcName;
78.131 - return super.toTargetContext(srcName);
78.132 - }
78.133 -
78.134 - @Override
78.135 - public ObjectName toSourceContext(ObjectName targetName) {
78.136 - if (identity) return targetName;
78.137 - return super.toSourceContext(targetName);
78.138 - }
78.139 -
78.140 - @SuppressWarnings("unchecked")
78.141 - @Override
78.142 - public <T> T rewriteInput(T input) {
78.143 - if (identity) return input;
78.144 - return (T) processObject(RewriteMode.INPUT,input);
78.145 - }
78.146 -
78.147 - @SuppressWarnings("unchecked")
78.148 - @Override
78.149 - public <T> T rewriteOutput(T result) {
78.150 - if (identity) return result;
78.151 - return (T) processObject(RewriteMode.OUTPUT,result);
78.152 - }
78.153 -}
79.1 --- a/src/share/classes/com/sun/jmx/namespace/serial/IdentityProcessor.java Mon Nov 23 10:04:47 2009 +0000
79.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
79.3 @@ -1,74 +0,0 @@
79.4 -/*
79.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
79.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
79.7 - *
79.8 - * This code is free software; you can redistribute it and/or modify it
79.9 - * under the terms of the GNU General Public License version 2 only, as
79.10 - * published by the Free Software Foundation. Sun designates this
79.11 - * particular file as subject to the "Classpath" exception as provided
79.12 - * by Sun in the LICENSE file that accompanied this code.
79.13 - *
79.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
79.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
79.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
79.17 - * version 2 for more details (a copy is included in the LICENSE file that
79.18 - * accompanied this code).
79.19 - *
79.20 - * You should have received a copy of the GNU General Public License version
79.21 - * 2 along with this work; if not, write to the Free Software Foundation,
79.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
79.23 - *
79.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
79.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
79.26 - * have any questions.
79.27 - */
79.28 -
79.29 -package com.sun.jmx.namespace.serial;
79.30 -
79.31 -
79.32 -import javax.management.ObjectInstance;
79.33 -import javax.management.ObjectName;
79.34 -
79.35 -/**
79.36 - * Class RoutingOnlyProcessor. A RewritingProcessor that uses
79.37 - * Java Serialization to rewrite ObjectNames contained in
79.38 - * input & results...
79.39 - * <p><b>
79.40 - * This API is a Sun internal API and is subject to changes without notice.
79.41 - * </b></p>
79.42 - *
79.43 - * @since 1.7
79.44 - */
79.45 -class IdentityProcessor extends RewritingProcessor {
79.46 -
79.47 -
79.48 - /** Creates a new instance of SerialRewritingProcessor */
79.49 - public IdentityProcessor() {
79.50 - }
79.51 -
79.52 - @Override
79.53 - public <T> T rewriteOutput(T result) {
79.54 - return result;
79.55 - }
79.56 -
79.57 - @Override
79.58 - public <T> T rewriteInput(T input) {
79.59 - return input;
79.60 - }
79.61 -
79.62 - @Override
79.63 - public final ObjectName toTargetContext(ObjectName sourceName) {
79.64 - return sourceName;
79.65 - }
79.66 -
79.67 - @Override
79.68 - public final ObjectInstance toTargetContext(ObjectInstance sourceMoi) {
79.69 - return sourceMoi;
79.70 - }
79.71 -
79.72 - @Override
79.73 - public final ObjectName toSourceContext(ObjectName targetName) {
79.74 - return targetName;
79.75 - }
79.76 -
79.77 -}
80.1 --- a/src/share/classes/com/sun/jmx/namespace/serial/JMXNamespaceContext.java Mon Nov 23 10:04:47 2009 +0000
80.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
80.3 @@ -1,145 +0,0 @@
80.4 -/*
80.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
80.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
80.7 - *
80.8 - * This code is free software; you can redistribute it and/or modify it
80.9 - * under the terms of the GNU General Public License version 2 only, as
80.10 - * published by the Free Software Foundation. Sun designates this
80.11 - * particular file as subject to the "Classpath" exception as provided
80.12 - * by Sun in the LICENSE file that accompanied this code.
80.13 - *
80.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
80.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
80.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
80.17 - * version 2 for more details (a copy is included in the LICENSE file that
80.18 - * accompanied this code).
80.19 - *
80.20 - * You should have received a copy of the GNU General Public License version
80.21 - * 2 along with this work; if not, write to the Free Software Foundation,
80.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
80.23 - *
80.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
80.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
80.26 - * have any questions.
80.27 - */
80.28 -
80.29 -package com.sun.jmx.namespace.serial;
80.30 -
80.31 -import com.sun.jmx.defaults.JmxProperties;
80.32 -import java.io.IOException;
80.33 -import java.io.ObjectInputStream;
80.34 -import java.io.ObjectOutputStream;
80.35 -import java.util.logging.Level;
80.36 -import java.util.logging.Logger;
80.37 -
80.38 -
80.39 -/**
80.40 - * The JMXNamespaceContext class is used to implement a thread local
80.41 - * serialization / deserialization context for namespaces.
80.42 - * <p>
80.43 - * This class is consulted by {@link javax.management.ObjectName} at
80.44 - * serialization / deserialization time.
80.45 - * The serialization or deserialization context is established by
80.46 - * by the {@link SerialRewritingProcessor} defined in this package.
80.47 - * <p>
80.48 - * These classes are Sun proprietary APIs, subject to change without
80.49 - * notice. Do not use these classes directly.
80.50 - * The public API to rewrite ObjectNames embedded in parameters is
80.51 - * defined in {@link javax.management.namespace.JMXNamespaces}.
80.52 - *
80.53 - * <p><b>
80.54 - * This API is a Sun internal API and is subject to changes without notice.
80.55 - * </b></p>
80.56 - * @since 1.7
80.57 - */
80.58 -public class JMXNamespaceContext {
80.59 -
80.60 - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
80.61 -
80.62 - public final String prefixToRemove;
80.63 - public final String prefixToAdd;
80.64 -
80.65 - private JMXNamespaceContext(String add, String remove) {
80.66 - prefixToRemove = (remove==null?"":remove);
80.67 - prefixToAdd = (add==null?"":add);
80.68 - }
80.69 -
80.70 - private final static class SerialContext {
80.71 - private JMXNamespaceContext serializationContext;
80.72 - private JMXNamespaceContext deserializationContext;
80.73 - public SerialContext(){
80.74 - serializationContext = new JMXNamespaceContext("","");
80.75 - deserializationContext = new JMXNamespaceContext("","");
80.76 - }
80.77 - }
80.78 -
80.79 - private final static ThreadLocal<SerialContext> prefix =
80.80 - new ThreadLocal<SerialContext>() {
80.81 - @Override
80.82 - protected SerialContext initialValue() {
80.83 - return new SerialContext();
80.84 - }
80.85 - };
80.86 -
80.87 - public static JMXNamespaceContext getSerializationContext() {
80.88 - return prefix.get().serializationContext;
80.89 - }
80.90 -
80.91 - public static JMXNamespaceContext getDeserializationContext() {
80.92 - return prefix.get().deserializationContext;
80.93 - }
80.94 -
80.95 - private static String[] setSerializationContext(String oldPrefix,
80.96 - String newPrefix) {
80.97 - final SerialContext c = prefix.get();
80.98 - JMXNamespaceContext dc = c.serializationContext;
80.99 - String[] old = {dc.prefixToRemove, dc.prefixToAdd};
80.100 - c.serializationContext = new JMXNamespaceContext(newPrefix,oldPrefix);
80.101 - return old;
80.102 - }
80.103 -
80.104 - private static String[] setDeserializationContext(String oldPrefix,
80.105 - String newPrefix) {
80.106 - final SerialContext c = prefix.get();
80.107 - JMXNamespaceContext dc = c.deserializationContext;
80.108 - String[] old = {dc.prefixToRemove, dc.prefixToAdd};
80.109 - c.deserializationContext = new JMXNamespaceContext(newPrefix,oldPrefix);
80.110 - return old;
80.111 - }
80.112 -
80.113 - static void serialize(ObjectOutputStream stream, Object obj,
80.114 - String prefixToRemove, String prefixToAdd)
80.115 - throws IOException {
80.116 - final String[] old =
80.117 - setSerializationContext(prefixToRemove,prefixToAdd);
80.118 - try {
80.119 - stream.writeObject(obj);
80.120 - } finally {
80.121 - try {
80.122 - setSerializationContext(old[0],old[1]);
80.123 - } catch (Exception x) {
80.124 - LOG.log(Level.FINEST,
80.125 - "failed to restore serialization context",x);
80.126 - }
80.127 - }
80.128 - }
80.129 -
80.130 - static Object deserialize(ObjectInputStream stream,
80.131 - String prefixToRemove,
80.132 - String prefixToAdd)
80.133 - throws IOException, ClassNotFoundException {
80.134 - final String[] old =
80.135 - setDeserializationContext(prefixToRemove,prefixToAdd);
80.136 - try {
80.137 - return stream.readObject();
80.138 - } finally {
80.139 - try {
80.140 - setDeserializationContext(old[0],old[1]);
80.141 - } catch (Exception x) {
80.142 - LOG.log(Level.FINEST,
80.143 - "failed to restore serialization context",x);
80.144 - }
80.145 - }
80.146 - }
80.147 -
80.148 -}
81.1 --- a/src/share/classes/com/sun/jmx/namespace/serial/RewritingProcessor.java Mon Nov 23 10:04:47 2009 +0000
81.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
81.3 @@ -1,362 +0,0 @@
81.4 -/*
81.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
81.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
81.7 - *
81.8 - * This code is free software; you can redistribute it and/or modify it
81.9 - * under the terms of the GNU General Public License version 2 only, as
81.10 - * published by the Free Software Foundation. Sun designates this
81.11 - * particular file as subject to the "Classpath" exception as provided
81.12 - * by Sun in the LICENSE file that accompanied this code.
81.13 - *
81.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
81.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
81.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
81.17 - * version 2 for more details (a copy is included in the LICENSE file that
81.18 - * accompanied this code).
81.19 - *
81.20 - * You should have received a copy of the GNU General Public License version
81.21 - * 2 along with this work; if not, write to the Free Software Foundation,
81.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
81.23 - *
81.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
81.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
81.26 - * have any questions.
81.27 - */
81.28 -
81.29 -package com.sun.jmx.namespace.serial;
81.30 -
81.31 -
81.32 -import javax.management.ObjectInstance;
81.33 -import javax.management.ObjectName;
81.34 -
81.35 -/**
81.36 - * An object that can rewrite ObjectNames contained in input/output
81.37 - * parameters when entering/leaving a {@link javax.management.namespace
81.38 - * namespace}.
81.39 - * <p>When entering a {@link javax.management.namespace
81.40 - * namespace}, the {@code namespace} prefix is stripped from
81.41 - * ObjectNames contained in input parameters. When leaving a
81.42 - * {@code namespace},
81.43 - * the {@code namespace} prefix is prepended to the ObjectNames contained in
81.44 - * the result parameters returned from that {@code namespace}.
81.45 - * </p>
81.46 - * <p>Objects that need to perform these operations usually use a
81.47 - * {@code RewritingProcessor} for that purpose.<br>
81.48 - * The {@code RewritingProcessor} allows a somewhat larger
81.49 - * transformation in which part of a prefix {@link #newRewritingProcessor
81.50 - * remove} can be replaced by another prefix {@link #newRewritingProcessor
81.51 - * add}. The transformation described above correspond to the case where
81.52 - * {@code remove} is the stripped {@link javax.management.namespace
81.53 - * namespace} prefix (removed when entering the {@code namespace}) and
81.54 - * {@code add} is the empty String {@code ""}.
81.55 - * <br>
81.56 - * It is interesting to note that {@link
81.57 - * javax.management.JMXNamespaces#narrowToNamespace narrowToNamespace}
81.58 - * operations use the inverse transformation (that is, {@code remove} is
81.59 - * the empty String {@code ""} and {@code add} is the {@link
81.60 - * javax.management.namespace namespace} prefix).
81.61 - * <br>
81.62 - * On a more general scale, {@link #rewriteInput rewriteInput} removes
81.63 - * {@link #newRewritingProcessor remove} and the prepend {@link
81.64 - * #newRewritingProcessor add}, and {@link #rewriteOutput rewriteOutput}
81.65 - * does the opposite, removing {@link #newRewritingProcessor add}, and
81.66 - * then adding {@link #newRewritingProcessor remove}.
81.67 - * <br>
81.68 - * An implementation of {@code RewritingProcessor} should make sure that
81.69 - * <code>rewriteInput(rewriteOutput(x,clp),clp)</code> and
81.70 - * <code>rewriteOutput(rewriteInput(x,clp),clp)</code> always return
81.71 - * {@code x} or an exact clone of {@code x}.
81.72 - * </p>
81.73 - * <p>A default implementation of {@code RewritingProcessor} based on
81.74 - * Java Object Serialization can be
81.75 - * obtained from {@link #newRewritingProcessor newRewritingProcessor}.
81.76 - * </p>
81.77 - * <p>
81.78 - * By default, the instances of {@code RewritingProcessor} returned by
81.79 - * {@link #newRewritingProcessor newRewritingProcessor} will rewrite
81.80 - * ObjectNames contained in instances of classes they don't know about by
81.81 - * serializing and then deserializing such object instances. This will
81.82 - * happen even if such instances don't - or can't contain ObjectNames,
81.83 - * because the default implementation of {@code RewritingProcessor} will
81.84 - * not be able to determine whether instances of such classes can/do contain
81.85 - * instance of ObjectNames before serializing/deserializing them.
81.86 - * </p>
81.87 - * <p>If you are using custom classes that the default implementation of
81.88 - * {@code RewritingProcessor} don't know about, it can be interesting to
81.89 - * prevent an instance of {@code RewritingProcessor} to serialize/deserialize
81.90 - * instances of such classes for nothing. In that case, you could customize
81.91 - * the behavior of such a {@code RewritingProcessor} by wrapping it in a
81.92 - * custom subclass of {@code RewritingProcessor} as shown below:
81.93 - * <pre>
81.94 - * public class MyRewritingProcessor extends RewritingProcessor {
81.95 - * MyRewritingProcessor(String remove, String add) {
81.96 - * this(RewritingProcessor.newRewritingProcessor(remove,add));
81.97 - * }
81.98 - * MyRewritingProcessor(RewritingProcessor delegate) {
81.99 - * super(delegate);
81.100 - * }
81.101 - *
81.102 - * <T> T rewriteInput(T input) {
81.103 - * if (input == null) return null;
81.104 - * if (MyClass.equals(input.getClass())) {
81.105 - * // I know that MyClass doesn't contain any ObjectName
81.106 - * return (T) input;
81.107 - * }
81.108 - * return super.rewriteInput(input);
81.109 - * }
81.110 - * <T> T rewriteOutput(T result) {
81.111 - * if (result == null) return null;
81.112 - * if (MyClass.equals(result.getClass())) {
81.113 - * // I know that MyClass doesn't contain any ObjectName
81.114 - * return (T) result;
81.115 - * }
81.116 - * return super.rewriteOutput(result);
81.117 - * }
81.118 - * }
81.119 - * </pre>
81.120 - * </p>
81.121 - * <p>Such a subclass may also provide an alternate way of rewriting
81.122 - * custom subclasses for which rewriting is needed - for instance:
81.123 - * <pre>
81.124 - * public class MyRewritingProcessor extends RewritingProcessor {
81.125 - * MyRewritingProcessor(String remove, String add) {
81.126 - * this(RewritingProcessor.newRewritingProcessor(remove,add));
81.127 - * }
81.128 - * MyRewritingProcessor(RewritingProcessor delegate) {
81.129 - * super(delegate);
81.130 - * }
81.131 - *
81.132 - * <T> T rewriteInput(T input) {
81.133 - * if (input == null) return null;
81.134 - * if (MyClass.equals(input.getClass())) {
81.135 - * // I know that MyClass doesn't contain any ObjectName
81.136 - * return (T) input;
81.137 - * } else if (MyOtherClass.equals(input.getClass())) {
81.138 - * // Returns a new instance in which ObjectNames have been
81.139 - * // replaced.
81.140 - * final ObjectName aname = ((MyOtherClass)input).getName();
81.141 - * return (T) (new MyOtherClass(super.rewriteInput(aname)));
81.142 - * }
81.143 - * return super.rewriteInput(input,clp);
81.144 - * }
81.145 - * <T> T rewriteOutput(T result) {
81.146 - * if (result == null) return null;
81.147 - * if (MyClass.equals(result.getClass())) {
81.148 - * // I know that MyClass doesn't contain any ObjectName
81.149 - * return (T) result;
81.150 - * } else if (MyOtherClass.equals(result.getClass())) {
81.151 - * // Returns a new instance in which ObjectNames have been
81.152 - * // replaced.
81.153 - * final ObjectName aname = ((MyOtherClass)result).getName();
81.154 - * return (T) (new MyOtherClass(super.rewriteOutput(aname)));
81.155 - * }
81.156 - * return super.rewriteOutput(result,clp);
81.157 - * }
81.158 - * }
81.159 - * </pre>
81.160 - * </p>
81.161 - * <p>If your application only uses {@link javax.management.MXBean MXBeans},
81.162 - * or MBeans using simple types, and doesn't define any custom subclass of
81.163 - * {@link javax.management.Notification}, you should never write such
81.164 - * such {@code RewitingProcessor} implementations.
81.165 - * </p>
81.166 - * <p><b>
81.167 - * This API is a Sun internal API and is subject to changes without notice.
81.168 - * </b></p>
81.169 - * @since 1.7
81.170 - */
81.171 -public abstract class RewritingProcessor {
81.172 - /**
81.173 - * A logger for this class.
81.174 - **/
81.175 - private final RewritingProcessor delegate;
81.176 -
81.177 - /**
81.178 - * Creates a new instance of RewritingProcessor.
81.179 - * <p>This is equivalent to calling {@link
81.180 - * #RewritingProcessor(RewritingProcessor) RewritingProcessor(null)}.
81.181 - * </p>
81.182 - **/
81.183 - protected RewritingProcessor() {
81.184 - this(null);
81.185 - }
81.186 -
81.187 - /**
81.188 - * Creates a new instance of RewritingProcessor, with a delegate.
81.189 - * @param delegate a {@code RewritingProcessor} to which all the
81.190 - * calls will be delegated. When implementing a subclass
81.191 - * of {@code RewritingProcessor}, calling {@link
81.192 - * #rewriteInput super.rewriteInput} will invoke
81.193 - * {@code delegate.rewriteInput} and calling {@link
81.194 - * #rewriteOutput super.rewriteOutput} will invoke
81.195 - * {@code delegate.rewriteOutput}.
81.196 - *
81.197 - **/
81.198 - protected RewritingProcessor(RewritingProcessor delegate) {
81.199 - this.delegate = delegate;
81.200 - }
81.201 -
81.202 - /**
81.203 - * Rewrites ObjectNames when {@link RewritingProcessor leaving} a {@link
81.204 - * javax.management.namespace namespace}.
81.205 - * <p>
81.206 - * Returns {@code obj}, if it is known that {@code obj} doesn't contain
81.207 - * any ObjectName, or a new copied instance of {@code obj} in which
81.208 - * ObjectNames (if any) will have been rewritten, if {@code obj} contains
81.209 - * ObjectNames, or if it is not known whether {@code obj} contains
81.210 - * ObjectNames or not.
81.211 - * </p>
81.212 - * <p>
81.213 - * The default implementation of this method is as follows: if the
81.214 - * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code
81.215 - * null}, throws an {@link IllegalArgumentException}. Otherwise,
81.216 - * returns {@code delegate.rewriteOutput(obj)}.
81.217 - * </p>
81.218 - * <p>This behavior can be overridden by subclasses as shown in this
81.219 - * class {@link RewritingProcessor description}.
81.220 - * </p>
81.221 - * @param obj The result to be rewritten if needed.
81.222 - *
81.223 - * @return {@code obj}, or a clone of {@code obj} in which ObjectNames
81.224 - * have been rewritten. See this class {@link RewritingProcessor
81.225 - * description} for more details.
81.226 - * @throws IllegalArgumentException if this implementation does not know
81.227 - * how to rewrite the object.
81.228 - **/
81.229 - public <T> T rewriteOutput(T obj) {
81.230 - if (obj == null) return null;
81.231 - if (delegate != null)
81.232 - return delegate.rewriteOutput(obj);
81.233 - throw new IllegalArgumentException("can't rewrite "+
81.234 - obj.getClass().getName());
81.235 - }
81.236 -
81.237 - /**
81.238 - * Rewrites ObjectNames when {@link RewritingProcessor entering} a {@link
81.239 - * javax.management.namespace namespace}.
81.240 - * <p>
81.241 - * Returns {@code obj}, if it is known that {@code obj} doesn't contain
81.242 - * any ObjectName, or a new copied instance of {@code obj} in which
81.243 - * ObjectNames (if any) will have been rewritten, if {@code obj} contains
81.244 - * ObjectNames, or if it is not known whether {@code obj} contains
81.245 - * ObjectNames or not.
81.246 - * </p>
81.247 - * <p>
81.248 - * The default implementation of this method is as follows: if the
81.249 - * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code
81.250 - * null}, throws an {@link IllegalArgumentException}. Otherwise,
81.251 - * returns {@code delegate.rewriteInput(obj)}.
81.252 - * </p>
81.253 - * <p>This behavior can be overridden by subclasses as shown in this
81.254 - * class {@link RewritingProcessor description}.
81.255 - * </p>
81.256 - * @param obj The result to be rewritten if needed.
81.257 - * @return {@code obj}, or a clone of {@code obj} in which ObjectNames
81.258 - * have been rewritten. See this class {@link RewritingProcessor
81.259 - * description} for more details.
81.260 - * @throws IllegalArgumentException if this implementation does not know
81.261 - * how to rewrite the object.
81.262 - **/
81.263 - public <T> T rewriteInput(T obj) {
81.264 - if (obj == null) return null;
81.265 - if (delegate != null)
81.266 - return delegate.rewriteInput(obj);
81.267 - throw new IllegalArgumentException("can't rewrite "+
81.268 - obj.getClass().getName());
81.269 - }
81.270 -
81.271 - /**
81.272 - * Translate a routing ObjectName from the target (calling) context to
81.273 - * the source (called) context when {@link RewritingProcessor entering} a
81.274 - * {@link javax.management.namespace namespace}.
81.275 - * <p>
81.276 - * The default implementation of this method is as follows: if the
81.277 - * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code
81.278 - * null}, throws an {@link IllegalArgumentException}. Otherwise,
81.279 - * returns {@code delegate.toSourceContext(targetName)}.
81.280 - * </p>
81.281 - * <p>This behavior can be overridden by subclasses as shown in this
81.282 - * class {@link RewritingProcessor description}.
81.283 - * </p>
81.284 - * @param targetName The routing target ObjectName to translate.
81.285 - * @return The ObjectName translated to the source context.
81.286 - * @throws IllegalArgumentException if this implementation does not know
81.287 - * how to rewrite the object.
81.288 - **/
81.289 - public ObjectName toSourceContext(ObjectName targetName) {
81.290 - if (delegate != null)
81.291 - return delegate.toSourceContext(targetName);
81.292 - throw new IllegalArgumentException("can't rewrite targetName: "+
81.293 - " no delegate.");
81.294 - }
81.295 -
81.296 - /**
81.297 - * Translate an ObjectName returned from the source context into
81.298 - * the target (calling) context when {@link RewritingProcessor leaving} a
81.299 - * {@link javax.management.namespace namespace}.
81.300 - * <p>
81.301 - * The default implementation of this method is as follows: if the
81.302 - * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code
81.303 - * null}, throws an {@link IllegalArgumentException}. Otherwise,
81.304 - * returns {@code delegate.toTargetContext(sourceName)}.
81.305 - * </p>
81.306 - * <p>This behavior can be overridden by subclasses as shown in this
81.307 - * class {@link RewritingProcessor description}.
81.308 - * </p>
81.309 - * @param sourceName The routing source ObjectName to translate to the
81.310 - * target context.
81.311 - * @return The ObjectName translated to the target context.
81.312 - * @throws IllegalArgumentException if this implementation does not know
81.313 - * how to rewrite the object.
81.314 - **/
81.315 - public ObjectName toTargetContext(ObjectName sourceName) {
81.316 - if (delegate != null)
81.317 - return delegate.toTargetContext(sourceName);
81.318 - throw new IllegalArgumentException("can't rewrite sourceName: "+
81.319 - " no delegate.");
81.320 - }
81.321 -
81.322 - /**
81.323 - * Translate an ObjectInstance returned from the source context into
81.324 - * the target (calling) context when {@link RewritingProcessor leaving} a
81.325 - * {@link javax.management.namespace namespace}.
81.326 - * <p>
81.327 - * The default implementation of this method is as follows: if the
81.328 - * {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code
81.329 - * null}, throws an {@link IllegalArgumentException}. Otherwise,
81.330 - * returns {@code delegate.toTargetContext(sourceMoi)}.
81.331 - * </p>
81.332 - * <p>This behavior can be overridden by subclasses as shown in this
81.333 - * class {@link RewritingProcessor description}.
81.334 - * </p>
81.335 - * @param sourceMoi The routing source ObjectInstance to translate.
81.336 - * @return The ObjectInstance translated to the target context.
81.337 - * @throws IllegalArgumentException if this implementation does not know
81.338 - * how to rewrite the object.
81.339 - **/
81.340 - public ObjectInstance toTargetContext(ObjectInstance sourceMoi) {
81.341 - if (delegate != null)
81.342 - return delegate.toTargetContext(sourceMoi);
81.343 - throw new IllegalArgumentException("can't rewrite sourceName: "+
81.344 - " no delegate.");
81.345 - }
81.346 -
81.347 - /**
81.348 - * Creates a new default instance of {@link RewritingProcessor}.
81.349 - * @param remove The prefix to remove from {@link ObjectName ObjectNames}
81.350 - * when {@link RewritingProcessor entering} the {@link
81.351 - * javax.management.namespace namespace}.
81.352 - * @param add The prefix to add to {@link ObjectName ObjectNames}
81.353 - * when {@link RewritingProcessor entering} the {@link
81.354 - * javax.management.namespace namespace} (this is performed
81.355 - * after having removed the {@code remove} prefix.
81.356 - * @return A new {@link RewritingProcessor} processor object that will
81.357 - * perform the requested operation, using Java serialization if
81.358 - * necessary.
81.359 - **/
81.360 - public static RewritingProcessor newRewritingProcessor(String remove,
81.361 - String add) {
81.362 - return new DefaultRewritingProcessor(remove,add);
81.363 - }
81.364 -
81.365 -}
82.1 --- a/src/share/classes/com/sun/jmx/namespace/serial/RoutingOnlyProcessor.java Mon Nov 23 10:04:47 2009 +0000
82.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
82.3 @@ -1,74 +0,0 @@
82.4 -/*
82.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
82.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
82.7 - *
82.8 - * This code is free software; you can redistribute it and/or modify it
82.9 - * under the terms of the GNU General Public License version 2 only, as
82.10 - * published by the Free Software Foundation. Sun designates this
82.11 - * particular file as subject to the "Classpath" exception as provided
82.12 - * by Sun in the LICENSE file that accompanied this code.
82.13 - *
82.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
82.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
82.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
82.17 - * version 2 for more details (a copy is included in the LICENSE file that
82.18 - * accompanied this code).
82.19 - *
82.20 - * You should have received a copy of the GNU General Public License version
82.21 - * 2 along with this work; if not, write to the Free Software Foundation,
82.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
82.23 - *
82.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
82.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
82.26 - * have any questions.
82.27 - */
82.28 -
82.29 -package com.sun.jmx.namespace.serial;
82.30 -
82.31 -import com.sun.jmx.namespace.ObjectNameRouter;
82.32 -
82.33 -
82.34 -import javax.management.ObjectInstance;
82.35 -import javax.management.ObjectName;
82.36 -
82.37 -/**
82.38 - * Class RoutingOnlyProcessor. A RewritingProcessor that uses
82.39 - * Java Serialization to rewrite ObjectNames contained in
82.40 - * input and results...
82.41 - *
82.42 - * <p><b>
82.43 - * This API is a Sun internal API and is subject to changes without notice.
82.44 - * </b></p>
82.45 - * @since 1.7
82.46 - */
82.47 -class RoutingOnlyProcessor extends RewritingProcessor {
82.48 -
82.49 - final ObjectNameRouter router;
82.50 -
82.51 - public RoutingOnlyProcessor(String targetDirName) {
82.52 - this(targetDirName,null);
82.53 - }
82.54 -
82.55 - /** Creates a new instance of RoutingOnlyProcessor */
82.56 - public RoutingOnlyProcessor(final String remove, final String add) {
82.57 - super(new IdentityProcessor());
82.58 - if (remove == null || add == null)
82.59 - throw new IllegalArgumentException("Null argument");
82.60 - router = new ObjectNameRouter(remove,add);
82.61 - }
82.62 -
82.63 - @Override
82.64 - public final ObjectName toTargetContext(ObjectName sourceName) {
82.65 - return router.toTargetContext(sourceName,false);
82.66 - }
82.67 -
82.68 - @Override
82.69 - public final ObjectName toSourceContext(ObjectName targetName) {
82.70 - return router.toSourceContext(targetName,false);
82.71 - }
82.72 -
82.73 - @Override
82.74 - public final ObjectInstance toTargetContext(ObjectInstance sourceMoi) {
82.75 - return router.toTargetContext(sourceMoi,false);
82.76 - }
82.77 -}
83.1 --- a/src/share/classes/com/sun/jmx/namespace/serial/SerialRewritingProcessor.java Mon Nov 23 10:04:47 2009 +0000
83.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
83.3 @@ -1,172 +0,0 @@
83.4 -/*
83.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
83.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
83.7 - *
83.8 - * This code is free software; you can redistribute it and/or modify it
83.9 - * under the terms of the GNU General Public License version 2 only, as
83.10 - * published by the Free Software Foundation. Sun designates this
83.11 - * particular file as subject to the "Classpath" exception as provided
83.12 - * by Sun in the LICENSE file that accompanied this code.
83.13 - *
83.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
83.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
83.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
83.17 - * version 2 for more details (a copy is included in the LICENSE file that
83.18 - * accompanied this code).
83.19 - *
83.20 - * You should have received a copy of the GNU General Public License version
83.21 - * 2 along with this work; if not, write to the Free Software Foundation,
83.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
83.23 - *
83.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
83.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
83.26 - * have any questions.
83.27 - */
83.28 -
83.29 -package com.sun.jmx.namespace.serial;
83.30 -
83.31 -import java.io.ByteArrayInputStream;
83.32 -import java.io.ByteArrayOutputStream;
83.33 -import java.io.IOException;
83.34 -import java.io.InputStream;
83.35 -import java.io.InvalidClassException;
83.36 -import java.io.ObjectInputStream;
83.37 -import java.io.ObjectOutputStream;
83.38 -import java.io.ObjectStreamClass;
83.39 -import java.io.OutputStream;
83.40 -import java.util.LinkedList;
83.41 -import java.util.Queue;
83.42 -
83.43 -import javax.management.ObjectName;
83.44 -
83.45 -/**
83.46 - * Class SerialRewritingProcessor. A RewritingProcessor that uses
83.47 - * Java Serialization to rewrite ObjectNames contained in
83.48 - * input & results...
83.49 - * <p><b>
83.50 - * This API is a Sun internal API and is subject to changes without notice.
83.51 - * </b></p>
83.52 - * @since 1.7
83.53 - */
83.54 -class SerialRewritingProcessor extends RewritingProcessor {
83.55 -
83.56 -
83.57 - private static class CloneOutput extends ObjectOutputStream {
83.58 - Queue<Class<?>> classQueue = new LinkedList<Class<?>>();
83.59 -
83.60 - CloneOutput(OutputStream out) throws IOException {
83.61 - super(out);
83.62 - }
83.63 -
83.64 - @Override
83.65 - protected void annotateClass(Class<?> c) {
83.66 - classQueue.add(c);
83.67 - }
83.68 -
83.69 - @Override
83.70 - protected void annotateProxyClass(Class<?> c) {
83.71 - classQueue.add(c);
83.72 - }
83.73 - }
83.74 -
83.75 - private static class CloneInput extends ObjectInputStream {
83.76 - private final CloneOutput output;
83.77 -
83.78 - CloneInput(InputStream in, CloneOutput output) throws IOException {
83.79 - super(in);
83.80 - this.output = output;
83.81 - }
83.82 -
83.83 - @Override
83.84 - protected Class<?> resolveClass(ObjectStreamClass osc)
83.85 - throws IOException, ClassNotFoundException {
83.86 - Class<?> c = output.classQueue.poll();
83.87 - String expected = osc.getName();
83.88 - String found = (c == null) ? null : c.getName();
83.89 - if (!expected.equals(found)) {
83.90 - throw new InvalidClassException("Classes desynchronized: " +
83.91 - "found " + found + " when expecting " + expected);
83.92 - }
83.93 - return c;
83.94 - }
83.95 -
83.96 - @Override
83.97 - protected Class<?> resolveProxyClass(String[] interfaceNames)
83.98 - throws IOException, ClassNotFoundException {
83.99 - return output.classQueue.poll();
83.100 - }
83.101 - }
83.102 -
83.103 -
83.104 - final String targetPrefix;
83.105 - final String sourcePrefix;
83.106 - final boolean identity;
83.107 -
83.108 -
83.109 - public SerialRewritingProcessor(String targetDirName) {
83.110 - this(targetDirName,null);
83.111 - }
83.112 -
83.113 - /** Creates a new instance of SerialRewritingProcessor */
83.114 - public SerialRewritingProcessor(final String remove, final String add) {
83.115 - super(new RoutingOnlyProcessor(remove,add));
83.116 - this.targetPrefix = remove;
83.117 - this.sourcePrefix = add;
83.118 - identity = targetPrefix.equals(sourcePrefix);
83.119 - }
83.120 -
83.121 - private <T> T switchContext(T result, String from,String to)
83.122 - throws IOException, ClassNotFoundException {
83.123 - final ByteArrayOutputStream baos = new ByteArrayOutputStream();
83.124 - final CloneOutput ostream = new CloneOutput(baos);
83.125 -
83.126 - JMXNamespaceContext.serialize(ostream,result,from,null);
83.127 - ostream.flush();
83.128 -
83.129 - final byte[] bytes = baos.toByteArray();
83.130 - final ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
83.131 - final CloneInput istream = new CloneInput(bais, ostream);
83.132 - @SuppressWarnings("unchecked")
83.133 - final T clone = (T) JMXNamespaceContext.deserialize(istream,null,to);
83.134 - return clone;
83.135 - }
83.136 -
83.137 - @Override
83.138 - @SuppressWarnings("unchecked")
83.139 - public <T> T rewriteOutput(T result) {
83.140 - if (identity) return result;
83.141 - return (T) processOutput(result);
83.142 - }
83.143 -
83.144 - private Object processOutput(Object result) {
83.145 - try {
83.146 - if (result instanceof ObjectName)
83.147 - return toTargetContext((ObjectName) result);
83.148 - return switchContext(result,sourcePrefix,targetPrefix);
83.149 - } catch (ClassNotFoundException x) {
83.150 - throw new IllegalArgumentException("Can't process result: "+x,x);
83.151 - } catch (IOException x) {
83.152 - throw new IllegalArgumentException("Can't process result: "+x,x);
83.153 - }
83.154 - }
83.155 -
83.156 - @Override
83.157 - @SuppressWarnings("unchecked")
83.158 - public <T> T rewriteInput(T input) {
83.159 - if (identity) return input;
83.160 - return (T) processInput(input);
83.161 - }
83.162 -
83.163 - private Object processInput(Object input) {
83.164 - try {
83.165 - if (input instanceof ObjectName)
83.166 - return toSourceContext((ObjectName) input);
83.167 - return switchContext(input,targetPrefix,sourcePrefix);
83.168 - } catch (ClassNotFoundException x) {
83.169 - throw new IllegalArgumentException("Can't process input: "+x,x);
83.170 - } catch (IOException x) {
83.171 - throw new IllegalArgumentException("Can't process input: "+x,x);
83.172 - }
83.173 - }
83.174 -
83.175 -}
84.1 --- a/src/share/classes/com/sun/jmx/namespace/serial/package.html Mon Nov 23 10:04:47 2009 +0000
84.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
84.3 @@ -1,44 +0,0 @@
84.4 -<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
84.5 -
84.6 -<html>
84.7 - <head>
84.8 - <title>The <code>com.sun.jmx.namespace.serial</code> package</title>
84.9 -<!--
84.10 -Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
84.11 -DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
84.12 -
84.13 -This code is free software; you can redistribute it and/or modify it
84.14 -under the terms of the GNU General Public License version 2 only, as
84.15 -published by the Free Software Foundation. Sun designates this
84.16 -particular file as subject to the "Classpath" exception as provided
84.17 -by Sun in the LICENSE file that accompanied this code.
84.18 -
84.19 -This code is distributed in the hope that it will be useful, but WITHOUT
84.20 -ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
84.21 -FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
84.22 -version 2 for more details (a copy is included in the LICENSE file that
84.23 -accompanied this code).
84.24 -
84.25 -You should have received a copy of the GNU General Public License version
84.26 -2 along with this work; if not, write to the Free Software Foundation,
84.27 -Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
84.28 -
84.29 -Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
84.30 -CA 95054 USA or visit www.sun.com if you need additional information or
84.31 -have any questions.
84.32 --->
84.33 - </head>
84.34 - <body bgcolor="white">
84.35 - <p>The <code>com.sun.jmx.namespace.serial</code> package contains
84.36 - sun specific implementation classes used to switch namespace
84.37 - prefixes in ObjectName during serialization.
84.38 - </p>
84.39 - <p><b>NEVER USE THESE CLASSES DIRECTLY</b></p>
84.40 - <p><b>
84.41 - This API is a Sun internal API and is subject to changes without notice.
84.42 - </b></p>
84.43 - <p>The public API through which these proprietary classes can be invoked is
84.44 - located in <code>javax.management.namespace.JMXNamespaces</code>
84.45 - </p>
84.46 - </body>
84.47 -</html>
85.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
85.2 +++ b/src/share/classes/com/sun/jmx/remote/internal/IIOPHelper.java Wed Nov 25 11:08:25 2009 -0800
85.3 @@ -0,0 +1,188 @@
85.4 +/*
85.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
85.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
85.7 + *
85.8 + * This code is free software; you can redistribute it and/or modify it
85.9 + * under the terms of the GNU General Public License version 2 only, as
85.10 + * published by the Free Software Foundation. Sun designates this
85.11 + * particular file as subject to the "Classpath" exception as provided
85.12 + * by Sun in the LICENSE file that accompanied this code.
85.13 + *
85.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
85.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
85.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
85.17 + * version 2 for more details (a copy is included in the LICENSE file that
85.18 + * accompanied this code).
85.19 + *
85.20 + * You should have received a copy of the GNU General Public License version
85.21 + * 2 along with this work; if not, write to the Free Software Foundation,
85.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
85.23 + *
85.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
85.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
85.26 + * have any questions.
85.27 + */
85.28 +
85.29 +package com.sun.jmx.remote.internal;
85.30 +
85.31 +import java.util.Properties;
85.32 +import java.rmi.Remote;
85.33 +import java.rmi.RemoteException;
85.34 +import java.rmi.NoSuchObjectException;
85.35 +
85.36 +import java.util.Properties;
85.37 +import java.rmi.Remote;
85.38 +import java.rmi.RemoteException;
85.39 +import java.rmi.NoSuchObjectException;
85.40 +
85.41 +import java.security.AccessController;
85.42 +import java.security.PrivilegedAction;
85.43 +
85.44 +/**
85.45 + * A helper class for RMI-IIOP and CORBA APIs.
85.46 + */
85.47 +
85.48 +public final class IIOPHelper {
85.49 + private IIOPHelper() { }
85.50 +
85.51 + // loads IIOPProxy implementation class if available
85.52 + private static final String IMPL_CLASS =
85.53 + "com.sun.jmx.remote.protocol.iiop.IIOPProxyImpl";
85.54 + private static final IIOPProxy proxy =
85.55 + AccessController.doPrivileged(new PrivilegedAction<IIOPProxy>() {
85.56 + public IIOPProxy run() {
85.57 + try {
85.58 + Class<?> c = Class.forName(IMPL_CLASS, true, null);
85.59 + return (IIOPProxy)c.newInstance();
85.60 + } catch (ClassNotFoundException cnf) {
85.61 + return null;
85.62 + } catch (InstantiationException e) {
85.63 + throw new AssertionError(e);
85.64 + } catch (IllegalAccessException e) {
85.65 + throw new AssertionError(e);
85.66 + }
85.67 + }});
85.68 +
85.69 + /**
85.70 + * Returns true if RMI-IIOP and CORBA is available.
85.71 + */
85.72 + public static boolean isAvailable() {
85.73 + return proxy != null;
85.74 + }
85.75 +
85.76 + private static void ensureAvailable() {
85.77 + if (proxy == null)
85.78 + throw new AssertionError("Should not here");
85.79 + }
85.80 +
85.81 + /**
85.82 + * Returns true if the given object is a Stub.
85.83 + */
85.84 + public static boolean isStub(Object obj) {
85.85 + return (proxy == null) ? false : proxy.isStub(obj);
85.86 + }
85.87 +
85.88 + /**
85.89 + * Returns the Delegate to which the given Stub delegates.
85.90 + */
85.91 + public static Object getDelegate(Object stub) {
85.92 + ensureAvailable();
85.93 + return proxy.getDelegate(stub);
85.94 + }
85.95 +
85.96 + /**
85.97 + * Sets the Delegate for a given Stub.
85.98 + */
85.99 + public static void setDelegate(Object stub, Object delegate) {
85.100 + ensureAvailable();
85.101 + proxy.setDelegate(stub, delegate);
85.102 + }
85.103 +
85.104 + /**
85.105 + * Returns the ORB associated with the given stub
85.106 + *
85.107 + * @throws UnsupportedOperationException
85.108 + * if the object does not support the operation that
85.109 + * was invoked
85.110 + */
85.111 + public static Object getOrb(Object stub) {
85.112 + ensureAvailable();
85.113 + return proxy.getOrb(stub);
85.114 + }
85.115 +
85.116 + /**
85.117 + * Connects the Stub to the given ORB.
85.118 + */
85.119 + public static void connect(Object stub, Object orb)
85.120 + throws RemoteException
85.121 + {
85.122 + ensureAvailable();
85.123 + proxy.connect(stub, orb);
85.124 + }
85.125 +
85.126 + /**
85.127 + * Returns true if the given object is an ORB.
85.128 + */
85.129 + public static boolean isOrb(Object obj) {
85.130 + ensureAvailable();
85.131 + return proxy.isOrb(obj);
85.132 + }
85.133 +
85.134 + /**
85.135 + * Creates, and returns, a new ORB instance.
85.136 + */
85.137 + public static Object createOrb(String[] args, Properties props) {
85.138 + ensureAvailable();
85.139 + return proxy.createOrb(args, props);
85.140 + }
85.141 +
85.142 + /**
85.143 + * Converts a string, produced by the object_to_string method, back
85.144 + * to a CORBA object reference.
85.145 + */
85.146 + public static Object stringToObject(Object orb, String str) {
85.147 + ensureAvailable();
85.148 + return proxy.stringToObject(orb, str);
85.149 + }
85.150 +
85.151 + /**
85.152 + * Converts the given CORBA object reference to a string.
85.153 + */
85.154 + public static String objectToString(Object orb, Object obj) {
85.155 + ensureAvailable();
85.156 + return proxy.objectToString(orb, obj);
85.157 + }
85.158 +
85.159 + /**
85.160 + * Checks to ensure that an object of a remote or abstract interface
85.161 + * type can be cast to a desired type.
85.162 + */
85.163 + public static <T> T narrow(Object narrowFrom, Class<T> narrowTo) {
85.164 + ensureAvailable();
85.165 + return proxy.narrow(narrowFrom, narrowTo);
85.166 + }
85.167 +
85.168 + /**
85.169 + * Makes a server object ready to receive remote calls
85.170 + */
85.171 + public static void exportObject(Remote obj) throws RemoteException {
85.172 + ensureAvailable();
85.173 + proxy.exportObject(obj);
85.174 + }
85.175 +
85.176 + /**
85.177 + * Deregisters a server object from the runtime.
85.178 + */
85.179 + public static void unexportObject(Remote obj) throws NoSuchObjectException {
85.180 + ensureAvailable();
85.181 + proxy.unexportObject(obj);
85.182 + }
85.183 +
85.184 + /**
85.185 + * Returns a stub for the given server object.
85.186 + */
85.187 + public static Remote toStub(Remote obj) throws NoSuchObjectException {
85.188 + ensureAvailable();
85.189 + return proxy.toStub(obj);
85.190 + }
85.191 +}
86.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
86.2 +++ b/src/share/classes/com/sun/jmx/remote/internal/IIOPProxy.java Wed Nov 25 11:08:25 2009 -0800
86.3 @@ -0,0 +1,110 @@
86.4 +/*
86.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
86.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
86.7 + *
86.8 + * This code is free software; you can redistribute it and/or modify it
86.9 + * under the terms of the GNU General Public License version 2 only, as
86.10 + * published by the Free Software Foundation. Sun designates this
86.11 + * particular file as subject to the "Classpath" exception as provided
86.12 + * by Sun in the LICENSE file that accompanied this code.
86.13 + *
86.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
86.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
86.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
86.17 + * version 2 for more details (a copy is included in the LICENSE file that
86.18 + * accompanied this code).
86.19 + *
86.20 + * You should have received a copy of the GNU General Public License version
86.21 + * 2 along with this work; if not, write to the Free Software Foundation,
86.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
86.23 + *
86.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
86.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
86.26 + * have any questions.
86.27 + */
86.28 +
86.29 +package com.sun.jmx.remote.internal;
86.30 +
86.31 +import java.util.Properties;
86.32 +import java.rmi.Remote;
86.33 +import java.rmi.RemoteException;
86.34 +import java.rmi.NoSuchObjectException;
86.35 +
86.36 +/**
86.37 + * An interface to a subset of the RMI-IIOP and CORBA APIs to avoid a
86.38 + * static dependencies on the types defined by these APIs.
86.39 + */
86.40 +
86.41 +public interface IIOPProxy {
86.42 +
86.43 + /**
86.44 + * Returns true if the given object is a Stub.
86.45 + */
86.46 + boolean isStub(Object obj);
86.47 +
86.48 + /**
86.49 + * Returns the Delegate to which the given Stub delegates.
86.50 + */
86.51 + Object getDelegate(Object stub);
86.52 +
86.53 + /**
86.54 + * Sets the Delegate for a given Stub.
86.55 + */
86.56 + void setDelegate(Object stub, Object delegate);
86.57 +
86.58 + /**
86.59 + * Returns the ORB associated with the given stub
86.60 + *
86.61 + * @throws UnsupportedOperationException
86.62 + * if the object does not support the operation that
86.63 + * was invoked
86.64 + */
86.65 + Object getOrb(Object stub);
86.66 +
86.67 + /**
86.68 + * Connects the Stub to the given ORB.
86.69 + */
86.70 + void connect(Object stub, Object orb) throws RemoteException;
86.71 +
86.72 + /**
86.73 + * Returns true if the given object is an ORB.
86.74 + */
86.75 + boolean isOrb(Object obj);
86.76 +
86.77 + /**
86.78 + * Creates, and returns, a new ORB instance.
86.79 + */
86.80 + Object createOrb(String[] args, Properties props);
86.81 +
86.82 + /**
86.83 + * Converts a string, produced by the object_to_string method, back
86.84 + * to a CORBA object reference.
86.85 + */
86.86 + Object stringToObject(Object orb, String str);
86.87 +
86.88 + /**
86.89 + * Converts the given CORBA object reference to a string.
86.90 + */
86.91 + String objectToString(Object orb, Object obj);
86.92 +
86.93 + /**
86.94 + * Checks to ensure that an object of a remote or abstract interface
86.95 + * type can be cast to a desired type.
86.96 + */
86.97 + <T> T narrow(Object narrowFrom, Class<T> narrowTo);
86.98 +
86.99 + /**
86.100 + * Makes a server object ready to receive remote calls
86.101 + */
86.102 + void exportObject(Remote obj) throws RemoteException;
86.103 +
86.104 + /**
86.105 + * Deregisters a server object from the runtime.
86.106 + */
86.107 + void unexportObject(Remote obj) throws NoSuchObjectException;
86.108 +
86.109 + /**
86.110 + * Returns a stub for the given server object.
86.111 + */
86.112 + Remote toStub(Remote obj) throws NoSuchObjectException;
86.113 +}
87.1 --- a/src/share/classes/com/sun/jmx/remote/internal/ProxyInputStream.java Mon Nov 23 10:04:47 2009 +0000
87.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
87.3 @@ -1,241 +0,0 @@
87.4 -/*
87.5 - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
87.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
87.7 - *
87.8 - * This code is free software; you can redistribute it and/or modify it
87.9 - * under the terms of the GNU General Public License version 2 only, as
87.10 - * published by the Free Software Foundation. Sun designates this
87.11 - * particular file as subject to the "Classpath" exception as provided
87.12 - * by Sun in the LICENSE file that accompanied this code.
87.13 - *
87.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
87.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
87.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
87.17 - * version 2 for more details (a copy is included in the LICENSE file that
87.18 - * accompanied this code).
87.19 - *
87.20 - * You should have received a copy of the GNU General Public License version
87.21 - * 2 along with this work; if not, write to the Free Software Foundation,
87.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
87.23 - *
87.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
87.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
87.26 - * have any questions.
87.27 - */
87.28 -
87.29 -package com.sun.jmx.remote.internal;
87.30 -
87.31 -import java.io.IOException;
87.32 -import java.io.Serializable;
87.33 -import java.math.BigDecimal;
87.34 -
87.35 -import org.omg.CORBA.Any;
87.36 -import org.omg.CORBA.Context;
87.37 -import org.omg.CORBA.NO_IMPLEMENT;
87.38 -import org.omg.CORBA.ORB;
87.39 -import org.omg.CORBA.TypeCode;
87.40 -import org.omg.CORBA.portable.BoxedValueHelper;
87.41 -
87.42 -@SuppressWarnings({"deprecation", "rawtypes"})
87.43 -public class ProxyInputStream extends org.omg.CORBA_2_3.portable.InputStream {
87.44 - public ProxyInputStream(org.omg.CORBA.portable.InputStream in) {
87.45 - this.in = in;
87.46 - }
87.47 -
87.48 - public boolean read_boolean() {
87.49 - return in.read_boolean();
87.50 - }
87.51 -
87.52 - public char read_char() {
87.53 - return in.read_char();
87.54 - }
87.55 -
87.56 - public char read_wchar() {
87.57 - return in.read_wchar();
87.58 - }
87.59 -
87.60 - public byte read_octet() {
87.61 - return in.read_octet();
87.62 - }
87.63 -
87.64 - public short read_short() {
87.65 - return in.read_short();
87.66 - }
87.67 -
87.68 - public short read_ushort() {
87.69 - return in.read_ushort();
87.70 - }
87.71 -
87.72 - public int read_long() {
87.73 - return in.read_long();
87.74 - }
87.75 -
87.76 - public int read_ulong() {
87.77 - return in.read_ulong();
87.78 - }
87.79 -
87.80 - public long read_longlong() {
87.81 - return in.read_longlong();
87.82 - }
87.83 -
87.84 - public long read_ulonglong() {
87.85 - return in.read_ulonglong();
87.86 - }
87.87 -
87.88 - public float read_float() {
87.89 - return in.read_float();
87.90 - }
87.91 -
87.92 - public double read_double() {
87.93 - return in.read_double();
87.94 - }
87.95 -
87.96 - public String read_string() {
87.97 - return in.read_string();
87.98 - }
87.99 -
87.100 - public String read_wstring() {
87.101 - return in.read_wstring();
87.102 - }
87.103 -
87.104 - public void read_boolean_array(boolean[] value, int offset, int length) {
87.105 - in.read_boolean_array(value, offset, length);
87.106 - }
87.107 -
87.108 - public void read_char_array(char[] value, int offset, int length) {
87.109 - in.read_char_array(value, offset, length);
87.110 - }
87.111 -
87.112 - public void read_wchar_array(char[] value, int offset, int length) {
87.113 - in.read_wchar_array(value, offset, length);
87.114 - }
87.115 -
87.116 - public void read_octet_array(byte[] value, int offset, int length) {
87.117 - in.read_octet_array(value, offset, length);
87.118 - }
87.119 -
87.120 - public void read_short_array(short[] value, int offset, int length) {
87.121 - in.read_short_array(value, offset, length);
87.122 - }
87.123 -
87.124 - public void read_ushort_array(short[] value, int offset, int length) {
87.125 - in.read_ushort_array(value, offset, length);
87.126 - }
87.127 -
87.128 - public void read_long_array(int[] value, int offset, int length) {
87.129 - in.read_long_array(value, offset, length);
87.130 - }
87.131 -
87.132 - public void read_ulong_array(int[] value, int offset, int length) {
87.133 - in.read_ulong_array(value, offset, length);
87.134 - }
87.135 -
87.136 - public void read_longlong_array(long[] value, int offset, int length) {
87.137 - in.read_longlong_array(value, offset, length);
87.138 - }
87.139 -
87.140 - public void read_ulonglong_array(long[] value, int offset, int length) {
87.141 - in.read_ulonglong_array(value, offset, length);
87.142 - }
87.143 -
87.144 - public void read_float_array(float[] value, int offset, int length) {
87.145 - in.read_float_array(value, offset, length);
87.146 - }
87.147 -
87.148 - public void read_double_array(double[] value, int offset, int length) {
87.149 - in.read_double_array(value, offset, length);
87.150 - }
87.151 -
87.152 - public org.omg.CORBA.Object read_Object() {
87.153 - return in.read_Object();
87.154 - }
87.155 -
87.156 - public TypeCode read_TypeCode() {
87.157 - return in.read_TypeCode();
87.158 - }
87.159 -
87.160 - public Any read_any() {
87.161 - return in.read_any();
87.162 - }
87.163 -
87.164 - /**
87.165 - * @deprecated
87.166 - */
87.167 - @Override
87.168 - @Deprecated
87.169 - public org.omg.CORBA.Principal read_Principal() {
87.170 - return in.read_Principal();
87.171 - }
87.172 -
87.173 - @Override
87.174 - public int read() throws IOException {
87.175 - return in.read();
87.176 - }
87.177 -
87.178 - @Override
87.179 - public BigDecimal read_fixed() {
87.180 - return in.read_fixed();
87.181 - }
87.182 -
87.183 - @Override
87.184 - public Context read_Context() {
87.185 - return in.read_Context();
87.186 - }
87.187 -
87.188 - @Override
87.189 - public org.omg.CORBA.Object read_Object(java.lang.Class clz) {
87.190 - return in.read_Object(clz);
87.191 - }
87.192 -
87.193 - @Override
87.194 - public ORB orb() {
87.195 - return in.orb();
87.196 - }
87.197 -
87.198 - @Override
87.199 - public Serializable read_value() {
87.200 - return narrow().read_value();
87.201 - }
87.202 -
87.203 - @Override
87.204 - public Serializable read_value(Class clz) {
87.205 - return narrow().read_value(clz);
87.206 - }
87.207 -
87.208 - @Override
87.209 - public Serializable read_value(BoxedValueHelper factory) {
87.210 - return narrow().read_value(factory);
87.211 - }
87.212 -
87.213 - @Override
87.214 - public Serializable read_value(String rep_id) {
87.215 - return narrow().read_value(rep_id);
87.216 - }
87.217 -
87.218 - @Override
87.219 - public Serializable read_value(Serializable value) {
87.220 - return narrow().read_value(value);
87.221 - }
87.222 -
87.223 - @Override
87.224 - public Object read_abstract_interface() {
87.225 - return narrow().read_abstract_interface();
87.226 - }
87.227 -
87.228 - @Override
87.229 - public Object read_abstract_interface(Class clz) {
87.230 - return narrow().read_abstract_interface(clz);
87.231 - }
87.232 -
87.233 - protected org.omg.CORBA_2_3.portable.InputStream narrow() {
87.234 - if (in instanceof org.omg.CORBA_2_3.portable.InputStream)
87.235 - return (org.omg.CORBA_2_3.portable.InputStream) in;
87.236 - throw new NO_IMPLEMENT();
87.237 - }
87.238 -
87.239 - public org.omg.CORBA.portable.InputStream getProxiedInputStream() {
87.240 - return in;
87.241 - }
87.242 -
87.243 - protected final org.omg.CORBA.portable.InputStream in;
87.244 -}
88.1 --- a/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java Mon Nov 23 10:04:47 2009 +0000
88.2 +++ b/src/share/classes/com/sun/jmx/remote/internal/ServerNotifForwarder.java Wed Nov 25 11:08:25 2009 -0800
88.3 @@ -86,8 +86,7 @@
88.4
88.5 // Explicitly check MBeanPermission for addNotificationListener
88.6 //
88.7 - checkMBeanPermission(getMBeanServerName(),
88.8 - mbeanServer, name, "addNotificationListener");
88.9 + checkMBeanPermission(name, "addNotificationListener");
88.10 if (notificationAccessController != null) {
88.11 notificationAccessController.addNotificationListener(
88.12 connectionId, name, getSubject());
88.13 @@ -157,8 +156,7 @@
88.14
88.15 // Explicitly check MBeanPermission for removeNotificationListener
88.16 //
88.17 - checkMBeanPermission(getMBeanServerName(),
88.18 - mbeanServer, name, "removeNotificationListener");
88.19 + checkMBeanPermission(name, "removeNotificationListener");
88.20 if (notificationAccessController != null) {
88.21 notificationAccessController.removeNotificationListener(
88.22 connectionId, name, getSubject());
88.23 @@ -333,8 +331,8 @@
88.24 * Explicitly check the MBeanPermission for
88.25 * the current access control context.
88.26 */
88.27 - public static void checkMBeanPermission(String serverName,
88.28 - final MBeanServer mbs, final ObjectName name, final String actions)
88.29 + public void checkMBeanPermission(
88.30 + final ObjectName name, final String actions)
88.31 throws InstanceNotFoundException, SecurityException {
88.32 SecurityManager sm = System.getSecurityManager();
88.33 if (sm != null) {
88.34 @@ -345,7 +343,7 @@
88.35 new PrivilegedExceptionAction<ObjectInstance>() {
88.36 public ObjectInstance run()
88.37 throws InstanceNotFoundException {
88.38 - return mbs.getObjectInstance(name);
88.39 + return mbeanServer.getObjectInstance(name);
88.40 }
88.41 });
88.42 } catch (PrivilegedActionException e) {
88.43 @@ -353,7 +351,6 @@
88.44 }
88.45 String classname = oi.getClassName();
88.46 MBeanPermission perm = new MBeanPermission(
88.47 - serverName,
88.48 classname,
88.49 null,
88.50 name,
88.51 @@ -369,8 +366,7 @@
88.52 TargetedNotification tn) {
88.53 try {
88.54 if (checkNotificationEmission) {
88.55 - checkMBeanPermission(getMBeanServerName(),
88.56 - mbeanServer, name, "addNotificationListener");
88.57 + checkMBeanPermission(name, "addNotificationListener");
88.58 }
88.59 if (notificationAccessController != null) {
88.60 notificationAccessController.fetchNotification(
88.61 @@ -432,27 +428,12 @@
88.62 }
88.63 }
88.64
88.65 - private String getMBeanServerName() {
88.66 - if (mbeanServerName != null) return mbeanServerName;
88.67 - else return (mbeanServerName = getMBeanServerName(mbeanServer));
88.68 - }
88.69 -
88.70 - private static String getMBeanServerName(final MBeanServer server) {
88.71 - final PrivilegedAction<String> action = new PrivilegedAction<String>() {
88.72 - public String run() {
88.73 - return Util.getMBeanServerSecurityName(server);
88.74 - }
88.75 - };
88.76 - return AccessController.doPrivileged(action);
88.77 - }
88.78 -
88.79
88.80 //------------------
88.81 // PRIVATE VARIABLES
88.82 //------------------
88.83
88.84 private MBeanServer mbeanServer;
88.85 - private volatile String mbeanServerName;
88.86
88.87 private final String connectionId;
88.88
88.89 @@ -462,7 +443,7 @@
88.90 private final static int[] listenerCounterLock = new int[0];
88.91
88.92 private NotificationBuffer notifBuffer;
88.93 - private Map<ObjectName, Set<IdAndFilter>> listenerMap =
88.94 + private final Map<ObjectName, Set<IdAndFilter>> listenerMap =
88.95 new HashMap<ObjectName, Set<IdAndFilter>>();
88.96
88.97 private boolean terminated = false;
89.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
89.2 +++ b/src/share/classes/com/sun/jmx/remote/protocol/iiop/IIOPProxyImpl.java Wed Nov 25 11:08:25 2009 -0800
89.3 @@ -0,0 +1,119 @@
89.4 +/*
89.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
89.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
89.7 + *
89.8 + * This code is free software; you can redistribute it and/or modify it
89.9 + * under the terms of the GNU General Public License version 2 only, as
89.10 + * published by the Free Software Foundation. Sun designates this
89.11 + * particular file as subject to the "Classpath" exception as provided
89.12 + * by Sun in the LICENSE file that accompanied this code.
89.13 + *
89.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
89.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
89.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
89.17 + * version 2 for more details (a copy is included in the LICENSE file that
89.18 + * accompanied this code).
89.19 + *
89.20 + * You should have received a copy of the GNU General Public License version
89.21 + * 2 along with this work; if not, write to the Free Software Foundation,
89.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
89.23 + *
89.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
89.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
89.26 + * have any questions.
89.27 + */
89.28 +
89.29 +package com.sun.jmx.remote.protocol.iiop;
89.30 +
89.31 +import org.omg.CORBA.ORB;
89.32 +import org.omg.CORBA.portable.Delegate;
89.33 +import javax.rmi.PortableRemoteObject;
89.34 +import javax.rmi.CORBA.Stub;
89.35 +
89.36 +import java.util.Properties;
89.37 +import java.rmi.Remote;
89.38 +import java.rmi.RemoteException;
89.39 +import java.rmi.NoSuchObjectException;
89.40 +
89.41 +import com.sun.jmx.remote.internal.IIOPProxy;
89.42 +
89.43 +/**
89.44 + * An implementatin of IIOPProxy that simply delegates to the appropriate
89.45 + * RMI-IIOP and CORBA APIs.
89.46 + */
89.47 +
89.48 +public class IIOPProxyImpl implements IIOPProxy {
89.49 + public IIOPProxyImpl() { }
89.50 +
89.51 + @Override
89.52 + public boolean isStub(Object obj) {
89.53 + return (obj instanceof Stub);
89.54 + }
89.55 +
89.56 + @Override
89.57 + public Object getDelegate(Object stub) {
89.58 + return ((Stub)stub)._get_delegate();
89.59 + }
89.60 +
89.61 + @Override
89.62 + public void setDelegate(Object stub, Object delegate) {
89.63 + ((Stub)stub)._set_delegate((Delegate)delegate);
89.64 + }
89.65 +
89.66 + @Override
89.67 + public Object getOrb(Object stub) {
89.68 + try {
89.69 + return ((Stub)stub)._orb();
89.70 + } catch (org.omg.CORBA.BAD_OPERATION x) {
89.71 + throw new UnsupportedOperationException(x);
89.72 + }
89.73 + }
89.74 +
89.75 + @Override
89.76 + public void connect(Object stub, Object orb)
89.77 + throws RemoteException
89.78 + {
89.79 + ((Stub)stub).connect((ORB)orb);
89.80 + }
89.81 +
89.82 + @Override
89.83 + public boolean isOrb(Object obj) {
89.84 + return (obj instanceof ORB);
89.85 + }
89.86 +
89.87 + @Override
89.88 + public Object createOrb(String[] args, Properties props) {
89.89 + return ORB.init(args, props);
89.90 + }
89.91 +
89.92 + @Override
89.93 + public Object stringToObject(Object orb, String str) {
89.94 + return ((ORB)orb).string_to_object(str);
89.95 + }
89.96 +
89.97 + @Override
89.98 + public String objectToString(Object orb, Object obj) {
89.99 + return ((ORB)orb).object_to_string((org.omg.CORBA.Object)obj);
89.100 + }
89.101 +
89.102 + @Override
89.103 + @SuppressWarnings("unchecked")
89.104 + public <T> T narrow(Object narrowFrom, Class<T> narrowTo) {
89.105 + return (T)PortableRemoteObject.narrow(narrowFrom, narrowTo);
89.106 + }
89.107 +
89.108 + @Override
89.109 + public void exportObject(Remote obj) throws RemoteException {
89.110 + PortableRemoteObject.exportObject(obj);
89.111 + }
89.112 +
89.113 + @Override
89.114 + public void unexportObject(Remote obj) throws NoSuchObjectException {
89.115 + PortableRemoteObject.unexportObject(obj);
89.116 + }
89.117 +
89.118 + @Override
89.119 + public Remote toStub(Remote obj) throws NoSuchObjectException {
89.120 + return PortableRemoteObject.toStub(obj);
89.121 + }
89.122 +}
90.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
90.2 +++ b/src/share/classes/com/sun/jmx/remote/protocol/iiop/ProxyInputStream.java Wed Nov 25 11:08:25 2009 -0800
90.3 @@ -0,0 +1,241 @@
90.4 +/*
90.5 + * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
90.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
90.7 + *
90.8 + * This code is free software; you can redistribute it and/or modify it
90.9 + * under the terms of the GNU General Public License version 2 only, as
90.10 + * published by the Free Software Foundation. Sun designates this
90.11 + * particular file as subject to the "Classpath" exception as provided
90.12 + * by Sun in the LICENSE file that accompanied this code.
90.13 + *
90.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
90.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
90.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
90.17 + * version 2 for more details (a copy is included in the LICENSE file that
90.18 + * accompanied this code).
90.19 + *
90.20 + * You should have received a copy of the GNU General Public License version
90.21 + * 2 along with this work; if not, write to the Free Software Foundation,
90.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
90.23 + *
90.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
90.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
90.26 + * have any questions.
90.27 + */
90.28 +
90.29 +package com.sun.jmx.remote.protocol.iiop;
90.30 +
90.31 +import java.io.IOException;
90.32 +import java.io.Serializable;
90.33 +import java.math.BigDecimal;
90.34 +
90.35 +import org.omg.CORBA.Any;
90.36 +import org.omg.CORBA.Context;
90.37 +import org.omg.CORBA.NO_IMPLEMENT;
90.38 +import org.omg.CORBA.ORB;
90.39 +import org.omg.CORBA.TypeCode;
90.40 +import org.omg.CORBA.portable.BoxedValueHelper;
90.41 +
90.42 +@SuppressWarnings({"deprecation", "rawtypes"})
90.43 +public class ProxyInputStream extends org.omg.CORBA_2_3.portable.InputStream {
90.44 + public ProxyInputStream(org.omg.CORBA.portable.InputStream in) {
90.45 + this.in = in;
90.46 + }
90.47 +
90.48 + public boolean read_boolean() {
90.49 + return in.read_boolean();
90.50 + }
90.51 +
90.52 + public char read_char() {
90.53 + return in.read_char();
90.54 + }
90.55 +
90.56 + public char read_wchar() {
90.57 + return in.read_wchar();
90.58 + }
90.59 +
90.60 + public byte read_octet() {
90.61 + return in.read_octet();
90.62 + }
90.63 +
90.64 + public short read_short() {
90.65 + return in.read_short();
90.66 + }
90.67 +
90.68 + public short read_ushort() {
90.69 + return in.read_ushort();
90.70 + }
90.71 +
90.72 + public int read_long() {
90.73 + return in.read_long();
90.74 + }
90.75 +
90.76 + public int read_ulong() {
90.77 + return in.read_ulong();
90.78 + }
90.79 +
90.80 + public long read_longlong() {
90.81 + return in.read_longlong();
90.82 + }
90.83 +
90.84 + public long read_ulonglong() {
90.85 + return in.read_ulonglong();
90.86 + }
90.87 +
90.88 + public float read_float() {
90.89 + return in.read_float();
90.90 + }
90.91 +
90.92 + public double read_double() {
90.93 + return in.read_double();
90.94 + }
90.95 +
90.96 + public String read_string() {
90.97 + return in.read_string();
90.98 + }
90.99 +
90.100 + public String read_wstring() {
90.101 + return in.read_wstring();
90.102 + }
90.103 +
90.104 + public void read_boolean_array(boolean[] value, int offset, int length) {
90.105 + in.read_boolean_array(value, offset, length);
90.106 + }
90.107 +
90.108 + public void read_char_array(char[] value, int offset, int length) {
90.109 + in.read_char_array(value, offset, length);
90.110 + }
90.111 +
90.112 + public void read_wchar_array(char[] value, int offset, int length) {
90.113 + in.read_wchar_array(value, offset, length);
90.114 + }
90.115 +
90.116 + public void read_octet_array(byte[] value, int offset, int length) {
90.117 + in.read_octet_array(value, offset, length);
90.118 + }
90.119 +
90.120 + public void read_short_array(short[] value, int offset, int length) {
90.121 + in.read_short_array(value, offset, length);
90.122 + }
90.123 +
90.124 + public void read_ushort_array(short[] value, int offset, int length) {
90.125 + in.read_ushort_array(value, offset, length);
90.126 + }
90.127 +
90.128 + public void read_long_array(int[] value, int offset, int length) {
90.129 + in.read_long_array(value, offset, length);
90.130 + }
90.131 +
90.132 + public void read_ulong_array(int[] value, int offset, int length) {
90.133 + in.read_ulong_array(value, offset, length);
90.134 + }
90.135 +
90.136 + public void read_longlong_array(long[] value, int offset, int length) {
90.137 + in.read_longlong_array(value, offset, length);
90.138 + }
90.139 +
90.140 + public void read_ulonglong_array(long[] value, int offset, int length) {
90.141 + in.read_ulonglong_array(value, offset, length);
90.142 + }
90.143 +
90.144 + public void read_float_array(float[] value, int offset, int length) {
90.145 + in.read_float_array(value, offset, length);
90.146 + }
90.147 +
90.148 + public void read_double_array(double[] value, int offset, int length) {
90.149 + in.read_double_array(value, offset, length);
90.150 + }
90.151 +
90.152 + public org.omg.CORBA.Object read_Object() {
90.153 + return in.read_Object();
90.154 + }
90.155 +
90.156 + public TypeCode read_TypeCode() {
90.157 + return in.read_TypeCode();
90.158 + }
90.159 +
90.160 + public Any read_any() {
90.161 + return in.read_any();
90.162 + }
90.163 +
90.164 + /**
90.165 + * @deprecated
90.166 + */
90.167 + @Override
90.168 + @Deprecated
90.169 + public org.omg.CORBA.Principal read_Principal() {
90.170 + return in.read_Principal();
90.171 + }
90.172 +
90.173 + @Override
90.174 + public int read() throws IOException {
90.175 + return in.read();
90.176 + }
90.177 +
90.178 + @Override
90.179 + public BigDecimal read_fixed() {
90.180 + return in.read_fixed();
90.181 + }
90.182 +
90.183 + @Override
90.184 + public Context read_Context() {
90.185 + return in.read_Context();
90.186 + }
90.187 +
90.188 + @Override
90.189 + public org.omg.CORBA.Object read_Object(java.lang.Class clz) {
90.190 + return in.read_Object(clz);
90.191 + }
90.192 +
90.193 + @Override
90.194 + public ORB orb() {
90.195 + return in.orb();
90.196 + }
90.197 +
90.198 + @Override
90.199 + public Serializable read_value() {
90.200 + return narrow().read_value();
90.201 + }
90.202 +
90.203 + @Override
90.204 + public Serializable read_value(Class clz) {
90.205 + return narrow().read_value(clz);
90.206 + }
90.207 +
90.208 + @Override
90.209 + public Serializable read_value(BoxedValueHelper factory) {
90.210 + return narrow().read_value(factory);
90.211 + }
90.212 +
90.213 + @Override
90.214 + public Serializable read_value(String rep_id) {
90.215 + return narrow().read_value(rep_id);
90.216 + }
90.217 +
90.218 + @Override
90.219 + public Serializable read_value(Serializable value) {
90.220 + return narrow().read_value(value);
90.221 + }
90.222 +
90.223 + @Override
90.224 + public Object read_abstract_interface() {
90.225 + return narrow().read_abstract_interface();
90.226 + }
90.227 +
90.228 + @Override
90.229 + public Object read_abstract_interface(Class clz) {
90.230 + return narrow().read_abstract_interface(clz);
90.231 + }
90.232 +
90.233 + protected org.omg.CORBA_2_3.portable.InputStream narrow() {
90.234 + if (in instanceof org.omg.CORBA_2_3.portable.InputStream)
90.235 + return (org.omg.CORBA_2_3.portable.InputStream) in;
90.236 + throw new NO_IMPLEMENT();
90.237 + }
90.238 +
90.239 + public org.omg.CORBA.portable.InputStream getProxiedInputStream() {
90.240 + return in;
90.241 + }
90.242 +
90.243 + protected final org.omg.CORBA.portable.InputStream in;
90.244 +}
91.1 --- a/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java Mon Nov 23 10:04:47 2009 +0000
91.2 +++ b/src/share/classes/com/sun/jmx/remote/util/EnvHelp.java Wed Nov 25 11:08:25 2009 -0800
91.3 @@ -781,25 +781,6 @@
91.4 }
91.5
91.6 /**
91.7 - * Returns true if the parameter JMXConnector.USE_EVENT_SERVICE is set to a
91.8 - * String equals "true" by ignoring case in the map or in the System.
91.9 - */
91.10 - public static boolean eventServiceEnabled(Map<String, ?> env) {
91.11 - return computeBooleanFromString(env, JMXConnector.USE_EVENT_SERVICE, true);
91.12 - }
91.13 -
91.14 - /**
91.15 - * Returns true if the parameter JMXConnectorServer.DELEGATE_TO_EVENT_SERVICE
91.16 - * is set to a String equals "true" (ignores case).
91.17 - * If the property DELEGATE_TO_EVENT_SERVICE is not set, returns
91.18 - * a default value of "true".
91.19 - */
91.20 - public static boolean delegateToEventService(Map<String, ?> env) {
91.21 - return computeBooleanFromString(env,
91.22 - JMXConnectorServer.DELEGATE_TO_EVENT_SERVICE, true, true);
91.23 - }
91.24 -
91.25 - /**
91.26 * <p>Name of the attribute that specifies whether a connector server
91.27 * should not prevent the VM from exiting
91.28 */
91.29 @@ -817,46 +798,6 @@
91.30 ("true".equalsIgnoreCase((String)env.get(JMX_SERVER_DAEMON)));
91.31 }
91.32
91.33 -// /**
91.34 -// * <p>Name of the attribute that specifies an EventRelay object to use.
91.35 -// */
91.36 -// public static final String EVENT_RELAY =
91.37 -// "jmx.remote.x.event.relay";
91.38 -//
91.39 -//
91.40 -// /**
91.41 -// * Returns an EventRelay object. The default one is FetchingEventRelay.
91.42 -// * If {@code EVENT_RELAY} is specified in {@code env} as a key,
91.43 -// * its value will be returned as an EventRelay object, if the value is
91.44 -// * not of type {@code EventRelay}, the default {@code FetchingEventRelay}
91.45 -// * will be returned.
91.46 -// * If {@code EVENT_RELAY} is not specified but {@code ENABLE_EVENT_RELAY}
91.47 -// * is specified as a key and its value is <code true>, the default {@code FetchingEventRelay}
91.48 -// * will be returned.
91.49 -// */
91.50 -// public static EventRelay getEventRelay(Map env) {
91.51 -// Map info = env == null ?
91.52 -// Collections.EMPTY_MAP : env;
91.53 -//
91.54 -// Object o = env.get(EVENT_RELAY);
91.55 -// if (o instanceof EventRelay) {
91.56 -// return (EventRelay)o;
91.57 -// } else if (o != null) {
91.58 -// logger.warning("getEventRelay",
91.59 -// "The user specified object is not an EventRelay object, " +
91.60 -// "using the default class FetchingEventRelay.");
91.61 -//
91.62 -// return new FetchingEventRelay();
91.63 -// }
91.64 -//
91.65 -// if (enableEventRelay(env)) {
91.66 -// return new FetchingEventRelay();
91.67 -// }
91.68 -//
91.69 -// return null;
91.70 -// }
91.71 -
91.72 -
91.73 private static final class SinkOutputStream extends OutputStream {
91.74 public void write(byte[] b, int off, int len) {}
91.75 public void write(int b) {}
92.1 --- a/src/share/classes/com/sun/jmx/remote/util/EventClientConnection.java Mon Nov 23 10:04:47 2009 +0000
92.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
92.3 @@ -1,469 +0,0 @@
92.4 -/*
92.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
92.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
92.7 - *
92.8 - * This code is free software; you can redistribute it and/or modify it
92.9 - * under the terms of the GNU General Public License version 2 only, as
92.10 - * published by the Free Software Foundation. Sun designates this
92.11 - * particular file as subject to the "Classpath" exception as provided
92.12 - * by Sun in the LICENSE file that accompanied this code.
92.13 - *
92.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
92.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
92.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
92.17 - * version 2 for more details (a copy is included in the LICENSE file that
92.18 - * accompanied this code).
92.19 - *
92.20 - * You should have received a copy of the GNU General Public License version
92.21 - * 2 along with this work; if not, write to the Free Software Foundation,
92.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
92.23 - *
92.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
92.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
92.26 - * have any questions.
92.27 - */
92.28 -
92.29 -package com.sun.jmx.remote.util;
92.30 -
92.31 -import com.sun.jmx.defaults.JmxProperties;
92.32 -import com.sun.jmx.event.EventClientFactory;
92.33 -
92.34 -import java.lang.reflect.InvocationHandler;
92.35 -import java.lang.reflect.InvocationTargetException;
92.36 -import java.lang.reflect.Method;
92.37 -import java.lang.reflect.Proxy;
92.38 -import java.util.Arrays;
92.39 -import java.util.concurrent.Callable;
92.40 -import java.util.concurrent.TimeUnit;
92.41 -import java.util.concurrent.locks.Lock;
92.42 -import java.util.concurrent.locks.ReentrantLock;
92.43 -import java.util.logging.Level;
92.44 -import java.util.logging.Logger;
92.45 -
92.46 -import javax.management.MBeanServerConnection;
92.47 -import javax.management.NotificationFilter;
92.48 -import javax.management.NotificationListener;
92.49 -import javax.management.ObjectName;
92.50 -import javax.management.event.EventClient;
92.51 -import javax.management.event.EventClientDelegate;
92.52 -import javax.management.namespace.JMXNamespaces;
92.53 -
92.54 -/**
92.55 - * Class EventClientConnection - a {@link Proxy} that wraps an
92.56 - * {@link MBeanServerConnection} and an {@link EventClient}.
92.57 - * All methods are routed to the underlying {@code MBeanServerConnection},
92.58 - * except add/remove notification listeners which are routed to the
92.59 - * {@code EventClient}.
92.60 - * The caller only sees an {@code MBeanServerConnection} which uses an
92.61 - * {@code EventClient} behind the scenes.
92.62 - *
92.63 - * @author Sun Microsystems, Inc.
92.64 - */
92.65 -public class EventClientConnection implements InvocationHandler,
92.66 - EventClientFactory {
92.67 -
92.68 - /**
92.69 - * A logger for this class.
92.70 - **/
92.71 - private static final Logger LOG = JmxProperties.NOTIFICATION_LOGGER;
92.72 -
92.73 - private static final int NAMESPACE_SEPARATOR_LENGTH =
92.74 - JMXNamespaces.NAMESPACE_SEPARATOR.length();
92.75 -
92.76 - /**
92.77 - * Creates a new {@code EventClientConnection}.
92.78 - * @param connection The underlying MBeanServerConnection.
92.79 - */
92.80 - public EventClientConnection(MBeanServerConnection connection) {
92.81 - this(connection,null);
92.82 - }
92.83 -
92.84 - /**
92.85 - * Creates a new {@code EventClientConnection}.
92.86 - * @param connection The underlying MBeanServerConnection.
92.87 - * @param eventClientFactory a factory object that will be invoked
92.88 - * to create an {@link EventClient} when needed.
92.89 - * The {@code EventClient} is created lazily, when it is needed
92.90 - * for the first time. If null, a default factory will be used
92.91 - * (see {@link #createEventClient}).
92.92 - */
92.93 - public EventClientConnection(MBeanServerConnection connection,
92.94 - Callable<EventClient> eventClientFactory) {
92.95 -
92.96 - if (connection == null) {
92.97 - throw new IllegalArgumentException("Null connection");
92.98 - }
92.99 - this.connection = connection;
92.100 - if (eventClientFactory == null) {
92.101 - eventClientFactory = new Callable<EventClient>() {
92.102 - public final EventClient call() throws Exception {
92.103 - return createEventClient(EventClientConnection.this.connection);
92.104 - }
92.105 - };
92.106 - }
92.107 - this.eventClientFactory = eventClientFactory;
92.108 - this.lock = new ReentrantLock();
92.109 - }
92.110 -
92.111 - /**
92.112 - * <p>The MBean server connection through which the methods of
92.113 - * a proxy using this handler are forwarded.</p>
92.114 - *
92.115 - * @return the MBean server connection.
92.116 - *
92.117 - * @since 1.6
92.118 - */
92.119 - public MBeanServerConnection getMBeanServerConnection() {
92.120 - return connection;
92.121 - }
92.122 -
92.123 -
92.124 -
92.125 -
92.126 - /**
92.127 - * Creates a new EventClientConnection proxy instance.
92.128 - *
92.129 - * @param <T> The underlying {@code MBeanServerConnection} - which should
92.130 - * not be using the Event Service itself.
92.131 - * @param interfaceClass {@code MBeanServerConnection.class}, or a subclass.
92.132 - * @param eventClientFactory a factory used to create the EventClient.
92.133 - * If null, a default factory is used (see {@link
92.134 - * #createEventClient}).
92.135 - * @return the new proxy instance, which will route add/remove notification
92.136 - * listener calls through an {@code EventClient}.
92.137 - *
92.138 - */
92.139 - private static <T extends MBeanServerConnection> T
92.140 - newProxyInstance(T connection,
92.141 - Class<T> interfaceClass, Callable<EventClient> eventClientFactory) {
92.142 - final InvocationHandler handler =
92.143 - new EventClientConnection(connection,eventClientFactory);
92.144 - final Class<?>[] interfaces =
92.145 - new Class<?>[] {interfaceClass, EventClientFactory.class};
92.146 -
92.147 - Object proxy =
92.148 - Proxy.newProxyInstance(interfaceClass.getClassLoader(),
92.149 - interfaces,
92.150 - handler);
92.151 - return interfaceClass.cast(proxy);
92.152 - }
92.153 -
92.154 -
92.155 - public Object invoke(Object proxy, Method method, Object[] args)
92.156 - throws Throwable {
92.157 - final String methodName = method.getName();
92.158 -
92.159 - // add/remove notification listener are routed to the EventClient
92.160 - if (methodName.equals("addNotificationListener")
92.161 - || methodName.equals("removeNotificationListener")) {
92.162 - final Class<?>[] sig = method.getParameterTypes();
92.163 - if (sig.length>1 &&
92.164 - NotificationListener.class.isAssignableFrom(sig[1])) {
92.165 - return invokeBroadcasterMethod(proxy,method,args);
92.166 - }
92.167 - }
92.168 -
92.169 - // subscribe/unsubscribe are also routed to the EventClient.
92.170 - final Class<?> clazz = method.getDeclaringClass();
92.171 - if (clazz.equals(EventClientFactory.class)) {
92.172 - return invokeEventClientSubscriberMethod(proxy,method,args);
92.173 - }
92.174 -
92.175 - // local or not: equals, toString, hashCode
92.176 - if (shouldDoLocally(proxy, method))
92.177 - return doLocally(proxy, method, args);
92.178 -
92.179 - return call(connection,method,args);
92.180 - }
92.181 -
92.182 - // The purpose of this method is to unwrap InvocationTargetException,
92.183 - // in order to avoid throwing UndeclaredThrowableException for
92.184 - // declared exceptions.
92.185 - //
92.186 - // When calling method.invoke(), any exception thrown by the invoked
92.187 - // method will be wrapped in InvocationTargetException. If we don't
92.188 - // unwrap this exception, the proxy will always throw
92.189 - // UndeclaredThrowableException, even for runtime exceptions.
92.190 - //
92.191 - private Object call(final Object obj, final Method m,
92.192 - final Object[] args)
92.193 - throws Throwable {
92.194 - try {
92.195 - return m.invoke(obj,args);
92.196 - } catch (InvocationTargetException x) {
92.197 - final Throwable xx = x.getTargetException();
92.198 - if (xx == null) throw x;
92.199 - else throw xx;
92.200 - }
92.201 - }
92.202 -
92.203 - /**
92.204 - * Route add/remove notification listener to the event client.
92.205 - **/
92.206 - private Object invokeBroadcasterMethod(Object proxy, Method method,
92.207 - Object[] args) throws Exception {
92.208 - final String methodName = method.getName();
92.209 - final int nargs = (args == null) ? 0 : args.length;
92.210 -
92.211 - if (nargs < 1) {
92.212 - final String msg =
92.213 - "Bad arg count: " + nargs;
92.214 - throw new IllegalArgumentException(msg);
92.215 - }
92.216 -
92.217 - final ObjectName mbean = (ObjectName) args[0];
92.218 - final EventClient evtClient = getEventClient();
92.219 -
92.220 - // Fails if evtClient is null AND the MBean we try to listen to is
92.221 - // in a subnamespace. We fail here because we know this will not
92.222 - // work.
92.223 - //
92.224 - // Note that if the wrapped MBeanServerConnection points to a an
92.225 - // earlier agent (JDK 1.6 or earlier), then the EventClient will
92.226 - // be null (we can't use the event service with earlier JDKs).
92.227 - //
92.228 - // In principle a null evtClient indicates that the remote VM is of
92.229 - // an earlier version, in which case it shouldn't contain any namespace.
92.230 - //
92.231 - // So having a null evtClient AND an MBean contained in a namespace is
92.232 - // clearly an error case.
92.233 - //
92.234 - if (evtClient == null) {
92.235 - final String domain = mbean.getDomain();
92.236 - final int index = domain.indexOf(JMXNamespaces.NAMESPACE_SEPARATOR);
92.237 - if (index > -1 && index <
92.238 - (domain.length()-NAMESPACE_SEPARATOR_LENGTH)) {
92.239 - throw new UnsupportedOperationException(method.getName()+
92.240 - " on namespace "+domain.substring(0,index+
92.241 - NAMESPACE_SEPARATOR_LENGTH));
92.242 - }
92.243 - }
92.244 -
92.245 - if (methodName.equals("addNotificationListener")) {
92.246 - /* The various throws of IllegalArgumentException here
92.247 - should not happen, since we know what the methods in
92.248 - NotificationBroadcaster and NotificationEmitter
92.249 - are. */
92.250 - if (nargs != 4) {
92.251 - final String msg =
92.252 - "Bad arg count to addNotificationListener: " + nargs;
92.253 - throw new IllegalArgumentException(msg);
92.254 - }
92.255 - /* Other inconsistencies will produce ClassCastException
92.256 - below. */
92.257 -
92.258 - final NotificationListener listener = (NotificationListener) args[1];
92.259 - final NotificationFilter filter = (NotificationFilter) args[2];
92.260 - final Object handback = args[3];
92.261 -
92.262 - if (evtClient != null) {
92.263 - // general case
92.264 - evtClient.addNotificationListener(mbean,listener,filter,handback);
92.265 - } else {
92.266 - // deprecated case. Only works for mbean in local namespace.
92.267 - connection.addNotificationListener(mbean,listener,filter,
92.268 - handback);
92.269 - }
92.270 - return null;
92.271 -
92.272 - } else if (methodName.equals("removeNotificationListener")) {
92.273 -
92.274 - /* NullPointerException if method with no args, but that
92.275 - shouldn't happen because removeNL does have args. */
92.276 - NotificationListener listener = (NotificationListener) args[1];
92.277 -
92.278 - switch (nargs) {
92.279 - case 2:
92.280 - if (evtClient != null) {
92.281 - // general case
92.282 - evtClient.removeNotificationListener(mbean,listener);
92.283 - } else {
92.284 - // deprecated case. Only works for mbean in local namespace.
92.285 - connection.removeNotificationListener(mbean, listener);
92.286 - }
92.287 - return null;
92.288 -
92.289 - case 4:
92.290 - NotificationFilter filter = (NotificationFilter) args[2];
92.291 - Object handback = args[3];
92.292 - if (evtClient != null) {
92.293 - evtClient.removeNotificationListener(mbean,
92.294 - listener,
92.295 - filter,
92.296 - handback);
92.297 - } else {
92.298 - connection.removeNotificationListener(mbean,
92.299 - listener,
92.300 - filter,
92.301 - handback);
92.302 - }
92.303 - return null;
92.304 -
92.305 - default:
92.306 - final String msg =
92.307 - "Bad arg count to removeNotificationListener: " + nargs;
92.308 - throw new IllegalArgumentException(msg);
92.309 - }
92.310 -
92.311 - } else {
92.312 - throw new IllegalArgumentException("Bad method name: " +
92.313 - methodName);
92.314 - }
92.315 - }
92.316 -
92.317 - private boolean shouldDoLocally(Object proxy, Method method) {
92.318 - final String methodName = method.getName();
92.319 - if ((methodName.equals("hashCode") || methodName.equals("toString"))
92.320 - && method.getParameterTypes().length == 0
92.321 - && isLocal(proxy, method))
92.322 - return true;
92.323 - if (methodName.equals("equals")
92.324 - && Arrays.equals(method.getParameterTypes(),
92.325 - new Class<?>[] {Object.class})
92.326 - && isLocal(proxy, method))
92.327 - return true;
92.328 - return false;
92.329 - }
92.330 -
92.331 - private Object doLocally(Object proxy, Method method, Object[] args) {
92.332 - final String methodName = method.getName();
92.333 -
92.334 - if (methodName.equals("equals")) {
92.335 -
92.336 - if (this == args[0]) {
92.337 - return true;
92.338 - }
92.339 -
92.340 - if (!(args[0] instanceof Proxy)) {
92.341 - return false;
92.342 - }
92.343 -
92.344 - final InvocationHandler ihandler =
92.345 - Proxy.getInvocationHandler(args[0]);
92.346 -
92.347 - if (ihandler == null ||
92.348 - !(ihandler instanceof EventClientConnection)) {
92.349 - return false;
92.350 - }
92.351 -
92.352 - final EventClientConnection handler =
92.353 - (EventClientConnection)ihandler;
92.354 -
92.355 - return connection.equals(handler.connection) &&
92.356 - proxy.getClass().equals(args[0].getClass());
92.357 - } else if (methodName.equals("hashCode")) {
92.358 - return connection.hashCode();
92.359 - }
92.360 -
92.361 - throw new RuntimeException("Unexpected method name: " + methodName);
92.362 - }
92.363 -
92.364 - private static boolean isLocal(Object proxy, Method method) {
92.365 - final Class<?>[] interfaces = proxy.getClass().getInterfaces();
92.366 - if(interfaces == null) {
92.367 - return true;
92.368 - }
92.369 -
92.370 - final String methodName = method.getName();
92.371 - final Class<?>[] params = method.getParameterTypes();
92.372 - for (Class<?> intf : interfaces) {
92.373 - try {
92.374 - intf.getMethod(methodName, params);
92.375 - return false; // found method in one of our interfaces
92.376 - } catch (NoSuchMethodException nsme) {
92.377 - // OK.
92.378 - }
92.379 - }
92.380 -
92.381 - return true; // did not find in any interface
92.382 - }
92.383 -
92.384 - /**
92.385 - * Return the EventClient used by this object. Can be null if the
92.386 - * remote VM is of an earlier JDK version which doesn't have the
92.387 - * event service.<br>
92.388 - * This method will invoke the event client factory the first time
92.389 - * it is called.
92.390 - **/
92.391 - public final EventClient getEventClient() {
92.392 - if (initialized) return client;
92.393 - try {
92.394 - if (!lock.tryLock(TRYLOCK_TIMEOUT,TimeUnit.SECONDS))
92.395 - throw new IllegalStateException("can't acquire lock");
92.396 - try {
92.397 - client = eventClientFactory.call();
92.398 - initialized = true;
92.399 - } finally {
92.400 - lock.unlock();
92.401 - }
92.402 - } catch (RuntimeException x) {
92.403 - throw x;
92.404 - } catch (Exception x) {
92.405 - throw new IllegalStateException("Can't create EventClient: "+x,x);
92.406 - }
92.407 - return client;
92.408 - }
92.409 -
92.410 - /**
92.411 - * Returns an event client for the wrapped {@code MBeanServerConnection}.
92.412 - * This is the method invoked by the default event client factory.
92.413 - * @param connection the wrapped {@code MBeanServerConnection}.
92.414 - **/
92.415 - protected EventClient createEventClient(MBeanServerConnection connection)
92.416 - throws Exception {
92.417 - final ObjectName name =
92.418 - EventClientDelegate.OBJECT_NAME;
92.419 - if (connection.isRegistered(name)) {
92.420 - return new EventClient(connection);
92.421 - }
92.422 - return null;
92.423 - }
92.424 -
92.425 - /**
92.426 - * Creates a new {@link MBeanServerConnection} that goes through an
92.427 - * {@link EventClient} to receive/subscribe to notifications.
92.428 - * @param connection the underlying {@link MBeanServerConnection}.
92.429 - * The given <code>connection</code> shouldn't be already
92.430 - * using an {@code EventClient}.
92.431 - * @param eventClientFactory a factory object that will be invoked
92.432 - * to create an {@link EventClient} when needed.
92.433 - * The {@code EventClient} is created lazily, when it is needed
92.434 - * for the first time. If null, a default factory will be used
92.435 - * (see {@link #createEventClient}).
92.436 - * @return the MBeanServerConnection.
92.437 - **/
92.438 - public static MBeanServerConnection getEventConnectionFor(
92.439 - MBeanServerConnection connection,
92.440 - Callable<EventClient> eventClientFactory) {
92.441 - if (connection instanceof EventClientFactory
92.442 - && eventClientFactory != null)
92.443 - throw new IllegalArgumentException("connection already uses EventClient");
92.444 -
92.445 - if (connection instanceof EventClientFactory)
92.446 - return connection;
92.447 -
92.448 - // create a new proxy using an event client.
92.449 - //
92.450 - if (LOG.isLoggable(Level.FINE))
92.451 - LOG.fine("Creating EventClient for: "+connection);
92.452 - return newProxyInstance(connection,
92.453 - MBeanServerConnection.class,
92.454 - eventClientFactory);
92.455 - }
92.456 -
92.457 - private Object invokeEventClientSubscriberMethod(Object proxy,
92.458 - Method method, Object[] args) throws Throwable {
92.459 - return call(this,method,args);
92.460 - }
92.461 -
92.462 - // Maximum lock timeout in seconds. Obviously arbitrary.
92.463 - //
92.464 - private final static short TRYLOCK_TIMEOUT = 3;
92.465 -
92.466 - private final MBeanServerConnection connection;
92.467 - private final Callable<EventClient> eventClientFactory;
92.468 - private final Lock lock;
92.469 - private volatile EventClient client = null;
92.470 - private volatile boolean initialized = false;
92.471 -
92.472 -}
93.1 --- a/src/share/classes/com/sun/jndi/ldap/Connection.java Mon Nov 23 10:04:47 2009 +0000
93.2 +++ b/src/share/classes/com/sun/jndi/ldap/Connection.java Wed Nov 25 11:08:25 2009 -0800
93.3 @@ -1,5 +1,5 @@
93.4 /*
93.5 - * Copyright 1999-2005 Sun Microsystems, Inc. All Rights Reserved.
93.6 + * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
93.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
93.8 *
93.9 * This code is free software; you can redistribute it and/or modify it
93.10 @@ -32,12 +32,8 @@
93.11 import java.io.OutputStream;
93.12 import java.io.InputStream;
93.13 import java.net.Socket;
93.14 -import java.util.Vector;
93.15 -import java.util.Hashtable;
93.16
93.17 import javax.naming.CommunicationException;
93.18 -import javax.naming.AuthenticationException;
93.19 -import javax.naming.AuthenticationNotSupportedException;
93.20 import javax.naming.ServiceUnavailableException;
93.21 import javax.naming.NamingException;
93.22 import javax.naming.InterruptedNamingException;
93.23 @@ -47,6 +43,8 @@
93.24 import java.lang.reflect.Method;
93.25 import java.lang.reflect.Constructor;
93.26 import java.lang.reflect.InvocationTargetException;
93.27 +import java.util.Arrays;
93.28 +import sun.misc.IOUtils;
93.29 //import javax.net.SocketFactory;
93.30
93.31 /**
93.32 @@ -799,7 +797,6 @@
93.33 byte inbuf[]; // Buffer for reading incoming bytes
93.34 int inMsgId; // Message id of incoming response
93.35 int bytesread; // Number of bytes in inbuf
93.36 - int bytesleft; // Number of bytes that need to read for completing resp
93.37 int br; // Temp; number of bytes read from stream
93.38 int offset; // Offset of where to store bytes in inbuf
93.39 int seqlen; // Length of ASN sequence
93.40 @@ -811,7 +808,7 @@
93.41 try {
93.42 while (true) {
93.43 try {
93.44 - inbuf = new byte[2048];
93.45 + inbuf = new byte[10];
93.46
93.47 offset = 0;
93.48 seqlen = 0;
93.49 @@ -871,19 +868,10 @@
93.50 }
93.51
93.52 // read in seqlen bytes
93.53 - bytesleft = seqlen;
93.54 - if ((offset + bytesleft) > inbuf.length) {
93.55 - byte nbuf[] = new byte[offset + bytesleft];
93.56 - System.arraycopy(inbuf, 0, nbuf, 0, offset);
93.57 - inbuf = nbuf;
93.58 - }
93.59 - while (bytesleft > 0) {
93.60 - bytesread = in.read(inbuf, offset, bytesleft);
93.61 - if (bytesread < 0)
93.62 - break; // EOF
93.63 - offset += bytesread;
93.64 - bytesleft -= bytesread;
93.65 - }
93.66 + byte[] left = IOUtils.readFully(in, seqlen, false);
93.67 + inbuf = Arrays.copyOf(inbuf, offset + left.length);
93.68 + System.arraycopy(left, 0, inbuf, offset, left.length);
93.69 + offset += left.length;
93.70 /*
93.71 if (dump > 0) {
93.72 System.err.println("seqlen: " + seqlen);
94.1 --- a/src/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java Mon Nov 23 10:04:47 2009 +0000
94.2 +++ b/src/share/classes/com/sun/jndi/ldap/ext/StartTlsResponseImpl.java Wed Nov 25 11:08:25 2009 -0800
94.3 @@ -40,7 +40,6 @@
94.4 import java.security.Principal;
94.5 import java.security.cert.X509Certificate;
94.6 import java.security.cert.CertificateException;
94.7 -import javax.security.auth.kerberos.KerberosPrincipal;
94.8
94.9 import javax.net.ssl.SSLSession;
94.10 import javax.net.ssl.SSLSocket;
94.11 @@ -413,14 +412,15 @@
94.12 try {
94.13 HostnameChecker checker = HostnameChecker.getInstance(
94.14 HostnameChecker.TYPE_LDAP);
94.15 - Principal principal = getPeerPrincipal(session);
94.16 - if (principal instanceof KerberosPrincipal) {
94.17 - if (!checker.match(hostname, (KerberosPrincipal) principal)) {
94.18 + // Use ciphersuite to determine whether Kerberos is active.
94.19 + if (session.getCipherSuite().startsWith("TLS_KRB5")) {
94.20 + Principal principal = getPeerPrincipal(session);
94.21 + if (!checker.match(hostname, principal)) {
94.22 throw new SSLPeerUnverifiedException(
94.23 "hostname of the kerberos principal:" + principal +
94.24 " does not match the hostname:" + hostname);
94.25 }
94.26 - } else {
94.27 + } else { // X.509
94.28
94.29 // get the subject's certificate
94.30 certs = session.getPeerCertificates();
95.1 --- a/src/share/classes/com/sun/net/ssl/internal/www/protocol/https/DelegateHttpsURLConnection.java Mon Nov 23 10:04:47 2009 +0000
95.2 +++ b/src/share/classes/com/sun/net/ssl/internal/www/protocol/https/DelegateHttpsURLConnection.java Wed Nov 25 11:08:25 2009 -0800
95.3 @@ -36,7 +36,6 @@
95.4 import java.security.cert.*;
95.5
95.6 import javax.security.auth.x500.X500Principal;
95.7 -import javax.security.auth.kerberos.KerberosPrincipal;
95.8
95.9 import sun.security.util.HostnameChecker;
95.10 import sun.security.util.DerValue;
95.11 @@ -109,20 +108,18 @@
95.12 /*
95.13 * In com.sun.net.ssl.HostnameVerifier the method is defined
95.14 * as verify(String urlHostname, String certHostname).
95.15 - * This means we need to extract the hostname from the certificate
95.16 - * in this wrapper
95.17 + * This means we need to extract the hostname from the X.509 certificate
95.18 + * or from the Kerberos principal name, in this wrapper.
95.19 */
95.20 public boolean verify(String hostname, javax.net.ssl.SSLSession session) {
95.21 try {
95.22 String serverName;
95.23 - Principal principal = getPeerPrincipal(session);
95.24 - // X.500 principal or Kerberos principal.
95.25 - // (Use ciphersuite check to determine whether Kerberos is present.)
95.26 - if (session.getCipherSuite().startsWith("TLS_KRB5") &&
95.27 - principal instanceof KerberosPrincipal) {
95.28 + // Use ciphersuite to determine whether Kerberos is active.
95.29 + if (session.getCipherSuite().startsWith("TLS_KRB5")) {
95.30 serverName =
95.31 - HostnameChecker.getServerName((KerberosPrincipal)principal);
95.32 - } else {
95.33 + HostnameChecker.getServerName(getPeerPrincipal(session));
95.34 +
95.35 + } else { // X.509
95.36 Certificate[] serverChain = session.getPeerCertificates();
95.37 if ((serverChain == null) || (serverChain.length == 0)) {
95.38 return false;
96.1 --- a/src/share/classes/java/applet/Applet.java Mon Nov 23 10:04:47 2009 +0000
96.2 +++ b/src/share/classes/java/applet/Applet.java Wed Nov 25 11:08:25 2009 -0800
96.3 @@ -230,6 +230,21 @@
96.4 }
96.5
96.6 /**
96.7 + * Indicates if this container is a validate root.
96.8 + * <p>
96.9 + * {@code Applet} objects are the validate roots, and, therefore, they
96.10 + * override this method to return {@code true}.
96.11 + *
96.12 + * @return {@code true}
96.13 + * @since 1.7
96.14 + * @see java.awt.Container#isValidateRoot
96.15 + */
96.16 + @Override
96.17 + public boolean isValidateRoot() {
96.18 + return true;
96.19 + }
96.20 +
96.21 + /**
96.22 * Requests that the argument string be displayed in the
96.23 * "status window". Many browsers and applet viewers
96.24 * provide such a window, where the application can inform users of
97.1 --- a/src/share/classes/java/awt/AWTPermission.java Mon Nov 23 10:04:47 2009 +0000
97.2 +++ b/src/share/classes/java/awt/AWTPermission.java Wed Nov 25 11:08:25 2009 -0800
97.3 @@ -1,5 +1,5 @@
97.4 /*
97.5 - * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
97.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
97.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
97.8 *
97.9 * This code is free software; you can redistribute it and/or modify it
97.10 @@ -92,7 +92,15 @@
97.11 * <td>Enter full-screen exclusive mode</td>
97.12 * <td>Entering full-screen exclusive mode allows direct access to
97.13 * low-level graphics card memory. This could be used to spoof the
97.14 - * system, since the program is in direct control of rendering.</td>
97.15 + * system, since the program is in direct control of rendering. Depending on
97.16 + * the implementation, the security warning may not be shown for the windows
97.17 + * used to enter the full-screen exclusive mode (assuming that the {@code
97.18 + * fullScreenExclusive} permission has been granted to this application). Note
97.19 + * that this behavior does not mean that the {@code
97.20 + * showWindowWithoutWarningBanner} permission will be automatically granted to
97.21 + * the application which has the {@code fullScreenExclusive} permission:
97.22 + * non-full-screen windows will continue to be shown with the security
97.23 + * warning.</td>
97.24 * </tr>
97.25 *
97.26 * <tr>
98.1 --- a/src/share/classes/java/awt/Component.java Mon Nov 23 10:04:47 2009 +0000
98.2 +++ b/src/share/classes/java/awt/Component.java Wed Nov 25 11:08:25 2009 -0800
98.3 @@ -2764,8 +2764,11 @@
98.4 }
98.5
98.6 /**
98.7 - * Ensures that this component has a valid layout. This method is
98.8 - * primarily intended to operate on instances of <code>Container</code>.
98.9 + * Validates this component.
98.10 + * <p>
98.11 + * The meaning of the term <i>validating</i> is defined by the ancestors of
98.12 + * this class. See {@link Container#validate} for more details.
98.13 + *
98.14 * @see #invalidate
98.15 * @see #doLayout()
98.16 * @see LayoutManager
98.17 @@ -2794,12 +2797,24 @@
98.18 }
98.19
98.20 /**
98.21 - * Invalidates this component. This component and all parents
98.22 - * above it are marked as needing to be laid out. This method can
98.23 - * be called often, so it needs to execute quickly.
98.24 + * Invalidates this component and its ancestors.
98.25 + * <p>
98.26 + * All the ancestors of this component up to the nearest validate root are
98.27 + * marked invalid also. If there is no a validate root container for this
98.28 + * component, all of its ancestors up to the root of the hierarchy are
98.29 + * marked invalid as well. Marking a container <i>invalid</i> indicates
98.30 + * that the container needs to be laid out.
98.31 + * <p>
98.32 + * This method is called automatically when any layout-related information
98.33 + * changes (e.g. setting the bounds of the component, or adding the
98.34 + * component to a container).
98.35 + * <p>
98.36 + * This method might be called often, so it should work fast.
98.37 + *
98.38 * @see #validate
98.39 * @see #doLayout
98.40 * @see LayoutManager
98.41 + * @see java.awt.Container#isValidateRoot
98.42 * @since JDK1.0
98.43 */
98.44 public void invalidate() {
98.45 @@ -2818,9 +2833,18 @@
98.46 if (!isMaximumSizeSet()) {
98.47 maxSize = null;
98.48 }
98.49 - if (parent != null) {
98.50 - parent.invalidateIfValid();
98.51 - }
98.52 + invalidateParent();
98.53 + }
98.54 + }
98.55 +
98.56 + /**
98.57 + * Invalidates the parent of this component if any.
98.58 + *
98.59 + * This method MUST BE invoked under the TreeLock.
98.60 + */
98.61 + void invalidateParent() {
98.62 + if (parent != null) {
98.63 + parent.invalidateIfValid();
98.64 }
98.65 }
98.66
98.67 @@ -6727,12 +6751,13 @@
98.68 }
98.69 }
98.70 } else {
98.71 - // It's native. If the parent is lightweight it
98.72 - // will need some help.
98.73 - Container parent = this.parent;
98.74 - if (parent != null && parent.peer instanceof LightweightPeer) {
98.75 + // It's native. If the parent is lightweight it will need some
98.76 + // help.
98.77 + Container parent = getContainer();
98.78 + if (parent != null && parent.isLightweight()) {
98.79 relocateComponent();
98.80 - if (!isRecursivelyVisible()) {
98.81 + if (!parent.isRecursivelyVisibleUpToHeavyweightContainer())
98.82 + {
98.83 peer.setVisible(false);
98.84 }
98.85 }
99.1 --- a/src/share/classes/java/awt/Container.java Mon Nov 23 10:04:47 2009 +0000
99.2 +++ b/src/share/classes/java/awt/Container.java Wed Nov 25 11:08:25 2009 -0800
99.3 @@ -1492,20 +1492,59 @@
99.4 }
99.5
99.6 /**
99.7 - * Invalidates the container. The container and all parents
99.8 - * above it are marked as needing to be laid out. This method can
99.9 - * be called often, so it needs to execute quickly.
99.10 + * Indicates if this container is a <i>validate root</i>.
99.11 + * <p>
99.12 + * Layout-related changes, such as bounds of the validate root descendants,
99.13 + * do not affect the layout of the validate root parent. This peculiarity
99.14 + * enables the {@code invalidate()} method to stop invalidating the
99.15 + * component hierarchy when the method encounters a validate root.
99.16 + * <p>
99.17 + * If a component hierarchy contains validate roots, the {@code validate()}
99.18 + * method must be invoked on the validate root of a previously invalidated
99.19 + * component, rather than on the top-level container (such as a {@code
99.20 + * Frame} object) to restore the validity of the hierarchy later.
99.21 + * <p>
99.22 + * The {@code Window} class and the {@code Applet} class are the validate
99.23 + * roots in AWT. Swing introduces more validate roots.
99.24 *
99.25 - * <p> If the {@code LayoutManager} installed on this container is
99.26 - * an instance of {@code LayoutManager2}, then
99.27 - * {@link LayoutManager2#invalidateLayout(Container)} is invoked on
99.28 - * it supplying this {@code Container} as the argument.
99.29 + * @return whether this container is a validate root
99.30 + * @see #invalidate
99.31 + * @see java.awt.Component#invalidate
99.32 + * @see javax.swing.JComponent#isValidateRoot
99.33 + * @see javax.swing.JComponent#revalidate
99.34 + * @since 1.7
99.35 + */
99.36 + public boolean isValidateRoot() {
99.37 + return false;
99.38 + }
99.39 +
99.40 + /**
99.41 + * Invalidates the parent of the container unless the container
99.42 + * is a validate root.
99.43 + */
99.44 + @Override
99.45 + void invalidateParent() {
99.46 + if (!isValidateRoot()) {
99.47 + super.invalidateParent();
99.48 + }
99.49 + }
99.50 +
99.51 + /**
99.52 + * Invalidates the container.
99.53 + * <p>
99.54 + * If the {@code LayoutManager} installed on this container is an instance
99.55 + * of the {@code LayoutManager2} interface, then
99.56 + * the {@link LayoutManager2#invalidateLayout(Container)} method is invoked
99.57 + * on it supplying this {@code Container} as the argument.
99.58 + * <p>
99.59 + * Afterwards this method marks this container invalid, and invalidates its
99.60 + * ancestors. See the {@link Component#invalidate} method for more details.
99.61 *
99.62 * @see #validate
99.63 * @see #layout
99.64 - * @see LayoutManager
99.65 - * @see LayoutManager2#invalidateLayout(Container)
99.66 + * @see LayoutManager2
99.67 */
99.68 + @Override
99.69 public void invalidate() {
99.70 LayoutManager layoutMgr = this.layoutMgr;
99.71 if (layoutMgr instanceof LayoutManager2) {
99.72 @@ -1518,52 +1557,90 @@
99.73 /**
99.74 * Validates this container and all of its subcomponents.
99.75 * <p>
99.76 - * The <code>validate</code> method is used to cause a container
99.77 - * to lay out its subcomponents again. It should be invoked when
99.78 - * this container's subcomponents are modified (added to or
99.79 - * removed from the container, or layout-related information
99.80 - * changed) after the container has been displayed.
99.81 - *
99.82 - * <p>If this {@code Container} is not valid, this method invokes
99.83 + * Validating a container means laying out its subcomponents.
99.84 + * Layout-related changes, such as setting the bounds of a component, or
99.85 + * adding a component to the container, invalidate the container
99.86 + * automatically. Note that the ancestors of the container may be
99.87 + * invalidated also (see {@link Component#invalidate} for details.)
99.88 + * Therefore, to restore the validity of the hierarchy, the {@code
99.89 + * validate()} method should be invoked on a validate root of an
99.90 + * invalidated component, or on the top-most container if the hierarchy
99.91 + * does not contain validate roots.
99.92 + * <p>
99.93 + * Validating the container may be a quite time-consuming operation. For
99.94 + * performance reasons a developer may postpone the validation of the
99.95 + * hierarchy till a set of layout-related operations completes, e.g. after
99.96 + * adding all the children to the container.
99.97 + * <p>
99.98 + * If this {@code Container} is not valid, this method invokes
99.99 * the {@code validateTree} method and marks this {@code Container}
99.100 * as valid. Otherwise, no action is performed.
99.101 - * <p>
99.102 - * Note that the {@code invalidate()} method may invalidate not only the
99.103 - * component it is called upon, but also the parents of the component.
99.104 - * Therefore, to restore the validity of the hierarchy, the {@code
99.105 - * validate()} method must be invoked on the top-most invalid container of
99.106 - * the hierarchy. For performance reasons a developer may postpone the
99.107 - * validation of the hierarchy till a bunch of layout-related operations
99.108 - * completes, e.g. after adding all the children to the container.
99.109 *
99.110 * @see #add(java.awt.Component)
99.111 * @see #invalidate
99.112 + * @see Container#isValidateRoot
99.113 * @see javax.swing.JComponent#revalidate()
99.114 * @see #validateTree
99.115 */
99.116 public void validate() {
99.117 - /* Avoid grabbing lock unless really necessary. */
99.118 - if (!isValid()) {
99.119 - boolean updateCur = false;
99.120 - synchronized (getTreeLock()) {
99.121 - if (!isValid() && peer != null) {
99.122 - ContainerPeer p = null;
99.123 - if (peer instanceof ContainerPeer) {
99.124 - p = (ContainerPeer) peer;
99.125 - }
99.126 - if (p != null) {
99.127 - p.beginValidate();
99.128 - }
99.129 - validateTree();
99.130 - if (p != null) {
99.131 - p.endValidate();
99.132 + boolean updateCur = false;
99.133 + synchronized (getTreeLock()) {
99.134 + if ((!isValid() || descendUnconditionallyWhenValidating)
99.135 + && peer != null)
99.136 + {
99.137 + ContainerPeer p = null;
99.138 + if (peer instanceof ContainerPeer) {
99.139 + p = (ContainerPeer) peer;
99.140 + }
99.141 + if (p != null) {
99.142 + p.beginValidate();
99.143 + }
99.144 + validateTree();
99.145 + if (p != null) {
99.146 + p.endValidate();
99.147 + // Avoid updating cursor if this is an internal call.
99.148 + // See validateUnconditionally() for details.
99.149 + if (!descendUnconditionallyWhenValidating) {
99.150 updateCur = isVisible();
99.151 }
99.152 }
99.153 }
99.154 - if (updateCur) {
99.155 - updateCursorImmediately();
99.156 + }
99.157 + if (updateCur) {
99.158 + updateCursorImmediately();
99.159 + }
99.160 + }
99.161 +
99.162 + /**
99.163 + * Indicates whether valid containers should also traverse their
99.164 + * children and call the validateTree() method on them.
99.165 + *
99.166 + * Synchronization: TreeLock.
99.167 + *
99.168 + * The field is allowed to be static as long as the TreeLock itself is
99.169 + * static.
99.170 + *
99.171 + * @see #validateUnconditionally()
99.172 + */
99.173 + private static boolean descendUnconditionallyWhenValidating = false;
99.174 +
99.175 + /**
99.176 + * Unconditionally validate the component hierarchy.
99.177 + */
99.178 + final void validateUnconditionally() {
99.179 + boolean updateCur = false;
99.180 + synchronized (getTreeLock()) {
99.181 + descendUnconditionallyWhenValidating = true;
99.182 +
99.183 + validate();
99.184 + if (peer instanceof ContainerPeer) {
99.185 + updateCur = isVisible();
99.186 }
99.187 +
99.188 + descendUnconditionallyWhenValidating = false;
99.189 + }
99.190 + if (updateCur) {
99.191 + updateCursorImmediately();
99.192 }
99.193 }
99.194
99.195 @@ -1578,16 +1655,20 @@
99.196 */
99.197 protected void validateTree() {
99.198 checkTreeLock();
99.199 - if (!isValid()) {
99.200 + if (!isValid() || descendUnconditionallyWhenValidating) {
99.201 if (peer instanceof ContainerPeer) {
99.202 ((ContainerPeer)peer).beginLayout();
99.203 }
99.204 - doLayout();
99.205 + if (!isValid()) {
99.206 + doLayout();
99.207 + }
99.208 for (int i = 0; i < component.size(); i++) {
99.209 Component comp = component.get(i);
99.210 if ( (comp instanceof Container)
99.211 && !(comp instanceof Window)
99.212 - && !comp.isValid()) {
99.213 + && (!comp.isValid() ||
99.214 + descendUnconditionallyWhenValidating))
99.215 + {
99.216 ((Container)comp).validateTree();
99.217 } else {
99.218 comp.validate();
99.219 @@ -4092,16 +4173,29 @@
99.220 }
99.221 }
99.222
99.223 - /*
99.224 + /**
99.225 + * Checks if the container and its direct lightweight containers are
99.226 + * visible.
99.227 + *
99.228 * Consider the heavyweight container hides or shows the HW descendants
99.229 * automatically. Therefore we care of LW containers' visibility only.
99.230 + *
99.231 + * This method MUST be invoked under the TreeLock.
99.232 */
99.233 - private boolean isRecursivelyVisibleUpToHeavyweightContainer() {
99.234 + final boolean isRecursivelyVisibleUpToHeavyweightContainer() {
99.235 if (!isLightweight()) {
99.236 return true;
99.237 }
99.238 - return isVisible() && (getContainer() == null ||
99.239 - getContainer().isRecursivelyVisibleUpToHeavyweightContainer());
99.240 +
99.241 + for (Container cont = getContainer();
99.242 + cont != null && cont.isLightweight();
99.243 + cont = cont.getContainer())
99.244 + {
99.245 + if (!cont.isVisible()) {
99.246 + return false;
99.247 + }
99.248 + }
99.249 + return true;
99.250 }
99.251
99.252 @Override
100.1 --- a/src/share/classes/java/awt/EventQueue.java Mon Nov 23 10:04:47 2009 +0000
100.2 +++ b/src/share/classes/java/awt/EventQueue.java Wed Nov 25 11:08:25 2009 -0800
100.3 @@ -1027,7 +1027,9 @@
100.4
100.5 synchronized (lock) {
100.6 Toolkit.getEventQueue().postEvent(event);
100.7 - lock.wait();
100.8 + while (!event.isDispatched()) {
100.9 + lock.wait();
100.10 + }
100.11 }
100.12
100.13 Throwable eventThrowable = event.getThrowable();
101.1 --- a/src/share/classes/java/awt/Frame.java Mon Nov 23 10:04:47 2009 +0000
101.2 +++ b/src/share/classes/java/awt/Frame.java Wed Nov 25 11:08:25 2009 -0800
101.3 @@ -845,8 +845,11 @@
101.4 * others by setting those fields you want to accept from system
101.5 * to <code>Integer.MAX_VALUE</code>.
101.6 * <p>
101.7 - * On some systems only the size portion of the bounds is taken
101.8 - * into account.
101.9 + * Note, the given maximized bounds are used as a hint for the native
101.10 + * system, because the underlying platform may not support setting the
101.11 + * location and/or size of the maximized windows. If that is the case, the
101.12 + * provided values do not affect the appearance of the frame in the
101.13 + * maximized state.
101.14 *
101.15 * @param bounds bounds for the maximized state
101.16 * @see #getMaximizedBounds()
102.1 --- a/src/share/classes/java/awt/KeyboardFocusManager.java Mon Nov 23 10:04:47 2009 +0000
102.2 +++ b/src/share/classes/java/awt/KeyboardFocusManager.java Wed Nov 25 11:08:25 2009 -0800
102.3 @@ -53,7 +53,8 @@
102.4 import java.util.StringTokenizer;
102.5 import java.util.WeakHashMap;
102.6
102.7 -import sun.util.logging.PlatformLogger;
102.8 +import java.util.logging.Level;
102.9 +import java.util.logging.Logger;
102.10
102.11 import sun.awt.AppContext;
102.12 import sun.awt.HeadlessToolkit;
102.13 @@ -110,7 +111,7 @@
102.14 {
102.15
102.16 // Shared focus engine logger
102.17 - private static final PlatformLogger focusLog = PlatformLogger.getLogger("java.awt.focus.KeyboardFocusManager");
102.18 + private static final Logger focusLog = Logger.getLogger("java.awt.focus.KeyboardFocusManager");
102.19
102.20 static {
102.21 /* ensure that the necessary native libraries are loaded */
102.22 @@ -153,7 +154,7 @@
102.23 */
102.24 private static native void initIDs();
102.25
102.26 - private static final PlatformLogger log = PlatformLogger.getLogger("java.awt.KeyboardFocusManager");
102.27 + private static final Logger log = Logger.getLogger("java.awt.KeyboardFocusManager");
102.28
102.29 /**
102.30 * The identifier for the Forward focus traversal keys.
102.31 @@ -503,8 +504,8 @@
102.32 if (this == getCurrentKeyboardFocusManager()) {
102.33 return focusOwner;
102.34 } else {
102.35 - if (focusLog.isLoggable(PlatformLogger.FINER)) {
102.36 - focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
102.37 + if (focusLog.isLoggable(Level.FINER)) {
102.38 + focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
102.39 }
102.40 throw new SecurityException(notPrivileged);
102.41 }
102.42 @@ -608,9 +609,9 @@
102.43 }
102.44
102.45 void setNativeFocusOwner(Component comp) {
102.46 - if (focusLog.isLoggable(PlatformLogger.FINEST)) {
102.47 - focusLog.finest("Calling peer {0} setCurrentFocusOwner for {1}",
102.48 - peer, comp);
102.49 + if (focusLog.isLoggable(Level.FINEST)) {
102.50 + focusLog.log(Level.FINEST, "Calling peer {0} setCurrentFocusOwner for {1}",
102.51 + new Object[] {String.valueOf(peer), String.valueOf(comp)});
102.52 }
102.53 peer.setCurrentFocusOwner(comp);
102.54 }
102.55 @@ -672,8 +673,8 @@
102.56 if (this == getCurrentKeyboardFocusManager()) {
102.57 return permanentFocusOwner;
102.58 } else {
102.59 - if (focusLog.isLoggable(PlatformLogger.FINER)) {
102.60 - focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
102.61 + if (focusLog.isLoggable(Level.FINER)) {
102.62 + focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
102.63 }
102.64 throw new SecurityException(notPrivileged);
102.65 }
102.66 @@ -780,8 +781,8 @@
102.67 if (this == getCurrentKeyboardFocusManager()) {
102.68 return focusedWindow;
102.69 } else {
102.70 - if (focusLog.isLoggable(PlatformLogger.FINER)) {
102.71 - focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
102.72 + if (focusLog.isLoggable(Level.FINER)) {
102.73 + focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
102.74 }
102.75 throw new SecurityException(notPrivileged);
102.76 }
102.77 @@ -884,8 +885,8 @@
102.78 if (this == getCurrentKeyboardFocusManager()) {
102.79 return activeWindow;
102.80 } else {
102.81 - if (focusLog.isLoggable(PlatformLogger.FINER)) {
102.82 - focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
102.83 + if (focusLog.isLoggable(Level.FINER)) {
102.84 + focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
102.85 }
102.86 throw new SecurityException(notPrivileged);
102.87 }
102.88 @@ -918,8 +919,8 @@
102.89 Window oldActiveWindow;
102.90 synchronized (KeyboardFocusManager.class) {
102.91 oldActiveWindow = getActiveWindow();
102.92 - if (focusLog.isLoggable(PlatformLogger.FINER)) {
102.93 - focusLog.finer("Setting global active window to " + activeWindow + ", old active " + oldActiveWindow);
102.94 + if (focusLog.isLoggable(Level.FINER)) {
102.95 + focusLog.log(Level.FINER, "Setting global active window to " + activeWindow + ", old active " + oldActiveWindow);
102.96 }
102.97
102.98 try {
102.99 @@ -1214,8 +1215,8 @@
102.100 if (this == getCurrentKeyboardFocusManager()) {
102.101 return currentFocusCycleRoot;
102.102 } else {
102.103 - if (focusLog.isLoggable(PlatformLogger.FINER)) {
102.104 - focusLog.finer("This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
102.105 + if (focusLog.isLoggable(Level.FINER)) {
102.106 + focusLog.log(Level.FINER, "This manager is " + this + ", current is " + getCurrentKeyboardFocusManager());
102.107 }
102.108 throw new SecurityException(notPrivileged);
102.109 }
102.110 @@ -2148,9 +2149,9 @@
102.111
102.112 HeavyweightFocusRequest(Component heavyweight, Component descendant,
102.113 boolean temporary, CausedFocusEvent.Cause cause) {
102.114 - if (log.isLoggable(PlatformLogger.FINE)) {
102.115 + if (log.isLoggable(Level.FINE)) {
102.116 if (heavyweight == null) {
102.117 - log.fine("Assertion (heavyweight != null) failed");
102.118 + log.log(Level.FINE, "Assertion (heavyweight != null) failed");
102.119 }
102.120 }
102.121
102.122 @@ -2160,12 +2161,12 @@
102.123 }
102.124 boolean addLightweightRequest(Component descendant,
102.125 boolean temporary, CausedFocusEvent.Cause cause) {
102.126 - if (log.isLoggable(PlatformLogger.FINE)) {
102.127 + if (log.isLoggable(Level.FINE)) {
102.128 if (this == HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) {
102.129 - log.fine("Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed");
102.130 + log.log(Level.FINE, "Assertion (this != HeavyweightFocusRequest.CLEAR_GLOBAL_FOCUS_OWNER) failed");
102.131 }
102.132 if (descendant == null) {
102.133 - log.fine("Assertion (descendant != null) failed");
102.134 + log.log(Level.FINE, "Assertion (descendant != null) failed");
102.135 }
102.136 }
102.137
102.138 @@ -2338,12 +2339,12 @@
102.139 (Component heavyweight, Component descendant, boolean temporary,
102.140 boolean focusedWindowChangeAllowed, long time, CausedFocusEvent.Cause cause)
102.141 {
102.142 - if (log.isLoggable(PlatformLogger.FINE)) {
102.143 + if (log.isLoggable(Level.FINE)) {
102.144 if (heavyweight == null) {
102.145 - log.fine("Assertion (heavyweight != null) failed");
102.146 + log.log(Level.FINE, "Assertion (heavyweight != null) failed");
102.147 }
102.148 if (time == 0) {
102.149 - log.fine("Assertion (time != 0) failed");
102.150 + log.log(Level.FINE, "Assertion (time != 0) failed");
102.151 }
102.152 }
102.153
102.154 @@ -2360,31 +2361,31 @@
102.155 Component currentFocusOwner = thisManager.getGlobalFocusOwner();
102.156 Component nativeFocusOwner = thisManager.getNativeFocusOwner();
102.157 Window nativeFocusedWindow = thisManager.getNativeFocusedWindow();
102.158 - if (focusLog.isLoggable(PlatformLogger.FINER)) {
102.159 - focusLog.finer("SNFH for {0} in {1}",
102.160 - descendant, heavyweight);
102.161 + if (focusLog.isLoggable(Level.FINER)) {
102.162 + focusLog.log(Level.FINER, "SNFH for {0} in {1}",
102.163 + new Object[] {String.valueOf(descendant), String.valueOf(heavyweight)});
102.164 }
102.165 - if (focusLog.isLoggable(PlatformLogger.FINEST)) {
102.166 - focusLog.finest("0. Current focus owner {0}",
102.167 - currentFocusOwner);
102.168 - focusLog.finest("0. Native focus owner {0}",
102.169 - nativeFocusOwner);
102.170 - focusLog.finest("0. Native focused window {0}",
102.171 - nativeFocusedWindow);
102.172 + if (focusLog.isLoggable(Level.FINEST)) {
102.173 + focusLog.log(Level.FINEST, "0. Current focus owner {0}",
102.174 + String.valueOf(currentFocusOwner));
102.175 + focusLog.log(Level.FINEST, "0. Native focus owner {0}",
102.176 + String.valueOf(nativeFocusOwner));
102.177 + focusLog.log(Level.FINEST, "0. Native focused window {0}",
102.178 + String.valueOf(nativeFocusedWindow));
102.179 }
102.180 synchronized (heavyweightRequests) {
102.181 HeavyweightFocusRequest hwFocusRequest = getLastHWRequest();
102.182 - if (focusLog.isLoggable(PlatformLogger.FINEST)) {
102.183 - focusLog.finest("Request {0}", hwFocusRequest);
102.184 + if (focusLog.isLoggable(Level.FINEST)) {
102.185 + focusLog.log(Level.FINEST, "Request {0}", String.valueOf(hwFocusRequest));
102.186 }
102.187 if (hwFocusRequest == null &&
102.188 heavyweight == nativeFocusOwner)
102.189 {
102.190 if (descendant == currentFocusOwner) {
102.191 // Redundant request.
102.192 - if (focusLog.isLoggable(PlatformLogger.FINEST))
102.193 - focusLog.finest("1. SNFH_FAILURE for {0}",
102.194 - descendant);
102.195 + if (focusLog.isLoggable(Level.FINEST))
102.196 + focusLog.log(Level.FINEST, "1. SNFH_FAILURE for {0}",
102.197 + String.valueOf(descendant));
102.198 return SNFH_FAILURE;
102.199 }
102.200
102.201 @@ -2416,8 +2417,8 @@
102.202 // SunToolkit.postPriorityEvent(newFocusOwnerEvent);
102.203 SunToolkit.postEvent(descendant.appContext, newFocusOwnerEvent);
102.204
102.205 - if (focusLog.isLoggable(PlatformLogger.FINEST))
102.206 - focusLog.finest("2. SNFH_HANDLED for {0}", descendant);
102.207 + if (focusLog.isLoggable(Level.FINEST))
102.208 + focusLog.log(Level.FINEST, "2. SNFH_HANDLED for {0}", String.valueOf(descendant));
102.209 return SNFH_SUCCESS_HANDLED;
102.210 } else if (hwFocusRequest != null &&
102.211 hwFocusRequest.heavyweight == heavyweight) {
102.212 @@ -2430,7 +2431,7 @@
102.213 manager.enqueueKeyEvents(time, descendant);
102.214 }
102.215
102.216 - if (focusLog.isLoggable(PlatformLogger.FINEST))
102.217 + if (focusLog.isLoggable(Level.FINEST))
102.218 focusLog.finest("3. SNFH_HANDLED for lightweight" +
102.219 descendant + " in " + heavyweight);
102.220 return SNFH_SUCCESS_HANDLED;
102.221 @@ -2453,7 +2454,7 @@
102.222 (hwFocusRequest != null)
102.223 ? hwFocusRequest.heavyweight
102.224 : nativeFocusedWindow)) {
102.225 - if (focusLog.isLoggable(PlatformLogger.FINEST))
102.226 + if (focusLog.isLoggable(Level.FINEST))
102.227 focusLog.finest("4. SNFH_FAILURE for " + descendant);
102.228 return SNFH_FAILURE;
102.229 }
102.230 @@ -2463,7 +2464,7 @@
102.231 heavyweightRequests.add
102.232 (new HeavyweightFocusRequest(heavyweight, descendant,
102.233 temporary, cause));
102.234 - if (focusLog.isLoggable(PlatformLogger.FINEST))
102.235 + if (focusLog.isLoggable(Level.FINEST))
102.236 focusLog.finest("5. SNFH_PROCEED for " + descendant);
102.237 return SNFH_SUCCESS_PROCEED;
102.238 }
102.239 @@ -2854,13 +2855,14 @@
102.240 }
102.241
102.242 KeyboardFocusManager manager = getCurrentKeyboardFocusManager();
102.243 - if (focusLog.isLoggable(PlatformLogger.FINER)) {
102.244 + if (focusLog.isLoggable(Level.FINER)) {
102.245 if (event instanceof FocusEvent || event instanceof WindowEvent) {
102.246 - focusLog.finer(">>> {0}", event);
102.247 + focusLog.log(Level.FINER, ">>> {0}", new Object[] {String.valueOf(event)});
102.248 }
102.249 - if (focusLog.isLoggable(PlatformLogger.FINER) && event instanceof KeyEvent) {
102.250 - focusLog.finer(" focus owner is {0}", manager.getGlobalFocusOwner());
102.251 - focusLog.finer(">>> {0}", event);
102.252 + if (focusLog.isLoggable(Level.FINER) && event instanceof KeyEvent) {
102.253 + focusLog.log(Level.FINER, " focus owner is {0}",
102.254 + new Object[] {String.valueOf(manager.getGlobalFocusOwner())});
102.255 + focusLog.log(Level.FINER, ">>> {0}", new Object[] {String.valueOf(event)});
102.256 }
102.257 }
102.258
102.259 @@ -2944,9 +2946,9 @@
102.260 }
102.261 }
102.262 static void removeLastFocusRequest(Component heavyweight) {
102.263 - if (log.isLoggable(PlatformLogger.FINE)) {
102.264 + if (log.isLoggable(Level.FINE)) {
102.265 if (heavyweight == null) {
102.266 - log.fine("Assertion (heavyweight != null) failed");
102.267 + log.log(Level.FINE, "Assertion (heavyweight != null) failed");
102.268 }
102.269 }
102.270
103.1 --- a/src/share/classes/java/awt/Window.java Mon Nov 23 10:04:47 2009 +0000
103.2 +++ b/src/share/classes/java/awt/Window.java Wed Nov 25 11:08:25 2009 -0800
103.3 @@ -767,7 +767,7 @@
103.4 isPacked = true;
103.5 }
103.6
103.7 - validate();
103.8 + validateUnconditionally();
103.9 }
103.10
103.11 /**
103.12 @@ -943,7 +943,7 @@
103.13 if (peer == null) {
103.14 addNotify();
103.15 }
103.16 - validate();
103.17 + validateUnconditionally();
103.18
103.19 isInShow = true;
103.20 if (visible) {
103.21 @@ -2600,6 +2600,21 @@
103.22 }
103.23
103.24 /**
103.25 + * Indicates if this container is a validate root.
103.26 + * <p>
103.27 + * {@code Window} objects are the validate roots, and, therefore, they
103.28 + * override this method to return {@code true}.
103.29 + *
103.30 + * @return {@code true}
103.31 + * @since 1.7
103.32 + * @see java.awt.Container#isValidateRoot
103.33 + */
103.34 + @Override
103.35 + public boolean isValidateRoot() {
103.36 + return true;
103.37 + }
103.38 +
103.39 + /**
103.40 * Dispatches an event to this window or one of its sub components.
103.41 * @param e the event
103.42 */
104.1 --- a/src/share/classes/java/awt/color/ICC_Profile.java Mon Nov 23 10:04:47 2009 +0000
104.2 +++ b/src/share/classes/java/awt/color/ICC_Profile.java Wed Nov 25 11:08:25 2009 -0800
104.3 @@ -865,7 +865,9 @@
104.4 case ColorSpace.CS_PYCC:
104.5 synchronized(ICC_Profile.class) {
104.6 if (PYCCprofile == null) {
104.7 - if (getProfileFile("PYCC.pf") != null) {
104.8 + if (BootClassLoaderHook.getHook() != null ||
104.9 + standardProfileExists("PYCC.pf"))
104.10 + {
104.11 ProfileDeferralInfo pInfo =
104.12 new ProfileDeferralInfo("PYCC.pf",
104.13 ColorSpace.TYPE_3CLR, 3,
104.14 @@ -963,15 +965,15 @@
104.15 * and it does not permit read access to the given file.
104.16 */
104.17 public static ICC_Profile getInstance(String fileName) throws IOException {
104.18 - ICC_Profile thisProfile;
104.19 - FileInputStream fis;
104.20 + ICC_Profile thisProfile;
104.21 + FileInputStream fis = null;
104.22
104.23 - SecurityManager security = System.getSecurityManager();
104.24 - if (security != null) {
104.25 - security.checkRead(fileName);
104.26 +
104.27 + File f = getProfileFile(fileName);
104.28 + if (f != null) {
104.29 + fis = new FileInputStream(f);
104.30 }
104.31 -
104.32 - if ((fis = openProfile(fileName)) == null) {
104.33 + if (fis == null) {
104.34 throw new IOException("Cannot open file " + fileName);
104.35 }
104.36
104.37 @@ -1083,11 +1085,22 @@
104.38 void activateDeferredProfile() throws ProfileDataException {
104.39 byte profileData[];
104.40 FileInputStream fis;
104.41 - String fileName = deferralInfo.filename;
104.42 + final String fileName = deferralInfo.filename;
104.43
104.44 profileActivator = null;
104.45 deferralInfo = null;
104.46 - if ((fis = openProfile(fileName)) == null) {
104.47 + PrivilegedAction<FileInputStream> pa = new PrivilegedAction<FileInputStream>() {
104.48 + public FileInputStream run() {
104.49 + File f = getStandardProfileFile(fileName);
104.50 + if (f != null) {
104.51 + try {
104.52 + return new FileInputStream(f);
104.53 + } catch (FileNotFoundException e) {}
104.54 + }
104.55 + return null;
104.56 + }
104.57 + };
104.58 + if ((fis = AccessController.doPrivileged(pa)) == null) {
104.59 throw new ProfileDataException("Cannot open file " + fileName);
104.60 }
104.61 try {
104.62 @@ -1786,85 +1799,104 @@
104.63 * available, such as a profile for sRGB. Built-in profiles use .pf as
104.64 * the file name extension for profiles, e.g. sRGB.pf.
104.65 */
104.66 - private static FileInputStream openProfile(final String fileName) {
104.67 - return (FileInputStream)java.security.AccessController.doPrivileged(
104.68 - new java.security.PrivilegedAction() {
104.69 - public Object run() {
104.70 - File f = privilegedGetProfileFile(fileName);
104.71 - if (f != null) {
104.72 - try {
104.73 - return new FileInputStream(f);
104.74 - } catch (FileNotFoundException e) {
104.75 - }
104.76 - }
104.77 - return null;
104.78 - }
104.79 - });
104.80 - }
104.81 -
104.82 - private static File getProfileFile(final String fileName) {
104.83 - return (File)java.security.AccessController.doPrivileged(
104.84 - new java.security.PrivilegedAction() {
104.85 - public Object run() {
104.86 - return privilegedGetProfileFile(fileName);
104.87 - }
104.88 - });
104.89 - }
104.90 -
104.91 - /*
104.92 - * this version is called from doPrivileged in openProfile
104.93 - * or getProfileFile, so the whole method is privileged!
104.94 - */
104.95 -
104.96 - private static File privilegedGetProfileFile(String fileName) {
104.97 + private static File getProfileFile(String fileName) {
104.98 String path, dir, fullPath;
104.99
104.100 File f = new File(fileName); /* try absolute file name */
104.101 -
104.102 + if (f.isAbsolute()) {
104.103 + /* Rest of code has little sense for an absolute pathname,
104.104 + so return here. */
104.105 + return f.isFile() ? f : null;
104.106 + }
104.107 if ((!f.isFile()) &&
104.108 ((path = System.getProperty("java.iccprofile.path")) != null)){
104.109 /* try relative to java.iccprofile.path */
104.110 StringTokenizer st =
104.111 new StringTokenizer(path, File.pathSeparator);
104.112 - while (st.hasMoreTokens() && (!f.isFile())) {
104.113 + while (st.hasMoreTokens() && ((f == null) || (!f.isFile()))) {
104.114 + dir = st.nextToken();
104.115 + fullPath = dir + File.separatorChar + fileName;
104.116 + f = new File(fullPath);
104.117 + if (!isChildOf(f, dir)) {
104.118 + f = null;
104.119 + }
104.120 + }
104.121 + }
104.122 +
104.123 + if (((f == null) || (!f.isFile())) &&
104.124 + ((path = System.getProperty("java.class.path")) != null)) {
104.125 + /* try relative to java.class.path */
104.126 + StringTokenizer st =
104.127 + new StringTokenizer(path, File.pathSeparator);
104.128 + while (st.hasMoreTokens() && ((f == null) || (!f.isFile()))) {
104.129 dir = st.nextToken();
104.130 fullPath = dir + File.separatorChar + fileName;
104.131 f = new File(fullPath);
104.132 }
104.133 }
104.134
104.135 - if ((!f.isFile()) &&
104.136 - ((path = System.getProperty("java.class.path")) != null)) {
104.137 - /* try relative to java.class.path */
104.138 - StringTokenizer st =
104.139 - new StringTokenizer(path, File.pathSeparator);
104.140 - while (st.hasMoreTokens() && (!f.isFile())) {
104.141 - dir = st.nextToken();
104.142 - fullPath = dir + File.separatorChar + fileName;
104.143 - f = new File(fullPath);
104.144 - }
104.145 - }
104.146 -
104.147 - if (!f.isFile()) { /* try the directory of built-in profiles */
104.148 - dir = System.getProperty("java.home") +
104.149 - File.separatorChar + "lib" + File.separatorChar + "cmm";
104.150 - fullPath = dir + File.separatorChar + fileName;
104.151 - f = new File(fullPath);
104.152 - if (!f.isFile()) {
104.153 - //make sure file was installed in the kernel mode
104.154 - BootClassLoaderHook hook = BootClassLoaderHook.getHook();
104.155 - if (hook.getHook() != null) {
104.156 - hook.prefetchFile("lib/cmm/"+fileName);
104.157 - }
104.158 - }
104.159 - }
104.160 -
104.161 - if (f.isFile()) {
104.162 + if ((f == null) || (!f.isFile())) {
104.163 + /* try the directory of built-in profiles */
104.164 + f = getStandardProfileFile(fileName);
104.165 + }
104.166 + if (f != null && f.isFile()) {
104.167 return f;
104.168 }
104.169 return null;
104.170 }
104.171
104.172 + /**
104.173 + * Returns a file object corresponding to a built-in profile
104.174 + * specified by fileName.
104.175 + * If there is no built-in profile with such name, then the method
104.176 + * returns null.
104.177 + */
104.178 + private static File getStandardProfileFile(String fileName) {
104.179 + String dir = System.getProperty("java.home") +
104.180 + File.separatorChar + "lib" + File.separatorChar + "cmm";
104.181 + String fullPath = dir + File.separatorChar + fileName;
104.182 + File f = new File(fullPath);
104.183 + if (!f.isFile()) {
104.184 + //make sure file was installed in the kernel mode
104.185 + BootClassLoaderHook hook = BootClassLoaderHook.getHook();
104.186 + if (hook != null) {
104.187 + hook.prefetchFile("lib/cmm/"+fileName);
104.188 + }
104.189 + }
104.190 + return (f.isFile() && isChildOf(f, dir)) ? f : null;
104.191 + }
104.192 +
104.193 + /**
104.194 + * Checks whether given file resides inside give directory.
104.195 + */
104.196 + private static boolean isChildOf(File f, String dirName) {
104.197 + try {
104.198 + File dir = new File(dirName);
104.199 + String canonicalDirName = dir.getCanonicalPath();
104.200 + if (!canonicalDirName.endsWith(File.separator)) {
104.201 + canonicalDirName += File.separator;
104.202 + }
104.203 + String canonicalFileName = f.getCanonicalPath();
104.204 + return canonicalFileName.startsWith(canonicalDirName);
104.205 + } catch (IOException e) {
104.206 + /* we do not expect the IOException here, because invocation
104.207 + * of this function is always preceeded by isFile() call.
104.208 + */
104.209 + return false;
104.210 + }
104.211 + }
104.212 +
104.213 + /**
104.214 + * Checks whether built-in profile specified by fileName exists.
104.215 + */
104.216 + private static boolean standardProfileExists(final String fileName) {
104.217 + return AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
104.218 + public Boolean run() {
104.219 + return getStandardProfileFile(fileName) != null;
104.220 + }
104.221 + });
104.222 + }
104.223 +
104.224
104.225 /*
104.226 * Serialization support.
105.1 --- a/src/share/classes/java/awt/datatransfer/DataFlavor.java Mon Nov 23 10:04:47 2009 +0000
105.2 +++ b/src/share/classes/java/awt/datatransfer/DataFlavor.java Wed Nov 25 11:08:25 2009 -0800
105.3 @@ -1184,7 +1184,7 @@
105.4 */
105.5
105.6 public boolean isRepresentationClassRemote() {
105.7 - return java.rmi.Remote.class.isAssignableFrom(representationClass);
105.8 + return DataTransferer.isRemote(representationClass);
105.9 }
105.10
105.11 /**
106.1 --- a/src/share/classes/java/awt/event/InvocationEvent.java Mon Nov 23 10:04:47 2009 +0000
106.2 +++ b/src/share/classes/java/awt/event/InvocationEvent.java Wed Nov 25 11:08:25 2009 -0800
106.3 @@ -78,11 +78,22 @@
106.4
106.5 /**
106.6 * The (potentially null) Object whose notifyAll() method will be called
106.7 - * immediately after the Runnable.run() method returns.
106.8 + * immediately after the Runnable.run() method has returned or thrown an exception.
106.9 + *
106.10 + * @see #isDispatched
106.11 */
106.12 protected Object notifier;
106.13
106.14 /**
106.15 + * Indicates whether the <code>run()</code> method of the <code>runnable</code>
106.16 + * was executed or not.
106.17 + *
106.18 + * @see #isDispatched
106.19 + * @since 1.7
106.20 + */
106.21 + private volatile boolean dispatched = false;
106.22 +
106.23 + /**
106.24 * Set to true if dispatch() catches Throwable and stores it in the
106.25 * exception instance variable. If false, Throwables are propagated up
106.26 * to the EventDispatchThread's dispatch loop.
106.27 @@ -144,7 +155,7 @@
106.28 * source which will execute the runnable's <code>run</code>
106.29 * method when dispatched. If notifier is non-<code>null</code>,
106.30 * <code>notifyAll()</code> will be called on it
106.31 - * immediately after <code>run</code> returns.
106.32 + * immediately after <code>run</code> has returned or thrown an exception.
106.33 * <p>An invocation of the form <tt>InvocationEvent(source,
106.34 * runnable, notifier, catchThrowables)</tt>
106.35 * behaves in exactly the same way as the invocation of
106.36 @@ -159,7 +170,8 @@
106.37 * executed
106.38 * @param notifier The {@code Object} whose <code>notifyAll</code>
106.39 * method will be called after
106.40 - * <code>Runnable.run</code> has returned
106.41 + * <code>Runnable.run</code> has returned or
106.42 + * thrown an exception
106.43 * @param catchThrowables Specifies whether <code>dispatch</code>
106.44 * should catch Throwable when executing
106.45 * the <code>Runnable</code>'s <code>run</code>
106.46 @@ -180,8 +192,8 @@
106.47 * Constructs an <code>InvocationEvent</code> with the specified
106.48 * source and ID which will execute the runnable's <code>run</code>
106.49 * method when dispatched. If notifier is non-<code>null</code>,
106.50 - * <code>notifyAll</code> will be called on it
106.51 - * immediately after <code>run</code> returns.
106.52 + * <code>notifyAll</code> will be called on it immediately after
106.53 + * <code>run</code> has returned or thrown an exception.
106.54 * <p>This method throws an
106.55 * <code>IllegalArgumentException</code> if <code>source</code>
106.56 * is <code>null</code>.
106.57 @@ -195,7 +207,8 @@
106.58 * <code>run</code> method will be executed
106.59 * @param notifier The <code>Object</code> whose <code>notifyAll</code>
106.60 * method will be called after
106.61 - * <code>Runnable.run</code> has returned
106.62 + * <code>Runnable.run</code> has returned or
106.63 + * thrown an exception
106.64 * @param catchThrowables Specifies whether <code>dispatch</code>
106.65 * should catch Throwable when executing the
106.66 * <code>Runnable</code>'s <code>run</code>
106.67 @@ -217,27 +230,33 @@
106.68
106.69 /**
106.70 * Executes the Runnable's <code>run()</code> method and notifies the
106.71 - * notifier (if any) when <code>run()</code> returns.
106.72 + * notifier (if any) when <code>run()</code> has returned or thrown an exception.
106.73 + *
106.74 + * @see #isDispatched
106.75 */
106.76 public void dispatch() {
106.77 - if (catchExceptions) {
106.78 - try {
106.79 + try {
106.80 + if (catchExceptions) {
106.81 + try {
106.82 + runnable.run();
106.83 + }
106.84 + catch (Throwable t) {
106.85 + if (t instanceof Exception) {
106.86 + exception = (Exception) t;
106.87 + }
106.88 + throwable = t;
106.89 + }
106.90 + }
106.91 + else {
106.92 runnable.run();
106.93 }
106.94 - catch (Throwable t) {
106.95 - if (t instanceof Exception) {
106.96 - exception = (Exception) t;
106.97 + } finally {
106.98 + dispatched = true;
106.99 +
106.100 + if (notifier != null) {
106.101 + synchronized (notifier) {
106.102 + notifier.notifyAll();
106.103 }
106.104 - throwable = t;
106.105 - }
106.106 - }
106.107 - else {
106.108 - runnable.run();
106.109 - }
106.110 -
106.111 - if (notifier != null) {
106.112 - synchronized (notifier) {
106.113 - notifier.notifyAll();
106.114 }
106.115 }
106.116 }
106.117 @@ -278,6 +297,40 @@
106.118 }
106.119
106.120 /**
106.121 + * Returns {@code true} if the event is dispatched or any exception is
106.122 + * thrown while dispatching, {@code false} otherwise. The method should
106.123 + * be called by a waiting thread that calls the {@code notifier.wait()} method.
106.124 + * Since spurious wakeups are possible (as explained in {@link Object#wait()}),
106.125 + * this method should be used in a waiting loop to ensure that the event
106.126 + * got dispatched:
106.127 + * <pre>
106.128 + * while (!event.isDispatched()) {
106.129 + * notifier.wait();
106.130 + * }
106.131 + * </pre>
106.132 + * If the waiting thread wakes up without dispatching the event,
106.133 + * the {@code isDispatched()} method returns {@code false}, and
106.134 + * the {@code while} loop executes once more, thus, causing
106.135 + * the awakened thread to revert to the waiting mode.
106.136 + * <p>
106.137 + * If the {@code notifier.notifyAll()} happens before the waiting thread
106.138 + * enters the {@code notifier.wait()} method, the {@code while} loop ensures
106.139 + * that the waiting thread will not enter the {@code notifier.wait()} method.
106.140 + * Otherwise, there is no guarantee that the waiting thread will ever be woken
106.141 + * from the wait.
106.142 + *
106.143 + * @return {@code true} if the event has been dispatched, or any exception
106.144 + * has been thrown while dispatching, {@code false} otherwise
106.145 + * @see #dispatch
106.146 + * @see #notifier
106.147 + * @see #catchExceptions
106.148 + * @since 1.7
106.149 + */
106.150 + public boolean isDispatched() {
106.151 + return dispatched;
106.152 + }
106.153 +
106.154 + /**
106.155 * Returns a parameter string identifying this event.
106.156 * This method is useful for event-logging and for debugging.
106.157 *
107.1 --- a/src/share/classes/java/awt/font/NumericShaper.java Mon Nov 23 10:04:47 2009 +0000
107.2 +++ b/src/share/classes/java/awt/font/NumericShaper.java Wed Nov 25 11:08:25 2009 -0800
107.3 @@ -1,5 +1,5 @@
107.4 /*
107.5 - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
107.6 + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
107.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
107.8 *
107.9 * This code is free software; you can redistribute it and/or modify it
107.10 @@ -25,6 +25,13 @@
107.11
107.12 package java.awt.font;
107.13
107.14 +import java.io.IOException;
107.15 +import java.io.ObjectOutputStream;
107.16 +import java.util.Arrays;
107.17 +import java.util.Comparator;
107.18 +import java.util.EnumSet;
107.19 +import java.util.Set;
107.20 +
107.21 /**
107.22 * The <code>NumericShaper</code> class is used to convert Latin-1 (European)
107.23 * digits to other Unicode decimal digits. Users of this class will
107.24 @@ -64,13 +71,261 @@
107.25 * NumericShaper.getContextualShaper(NumericShaper.ARABIC |
107.26 * NumericShaper.TAMIL,
107.27 * NumericShaper.EUROPEAN);
107.28 - * shaper.shape(text. start, count);
107.29 + * shaper.shape(text, start, count);
107.30 * </pre></blockquote>
107.31 *
107.32 + * <p><b>Bit mask- and enum-based Unicode ranges</b></p>
107.33 + *
107.34 + * <p>This class supports two different programming interfaces to
107.35 + * represent Unicode ranges for script-specific digits: bit
107.36 + * mask-based ones, such as {@link #ARABIC NumericShaper.ARABIC}, and
107.37 + * enum-based ones, such as {@link NumericShaper.Range#ARABIC}.
107.38 + * Multiple ranges can be specified by ORing bit mask-based constants,
107.39 + * such as:
107.40 + * <blockquote><pre>
107.41 + * NumericShaper.ARABIC | NumericShaper.TAMIL
107.42 + * </pre></blockquote>
107.43 + * or creating a {@code Set} with the {@link NumericShaper.Range}
107.44 + * constants, such as:
107.45 + * <blockquote><pre>
107.46 + * EnumSet.of(NumericShaper.Scirpt.ARABIC, NumericShaper.Range.TAMIL)
107.47 + * </pre></blockquote>
107.48 + * The enum-based ranges are a super set of the bit mask-based ones.
107.49 + *
107.50 + * <p>If the two interfaces are mixed (including serialization),
107.51 + * Unicode range values are mapped to their counterparts where such
107.52 + * mapping is possible, such as {@code NumericShaper.Range.ARABIC}
107.53 + * from/to {@code NumericShaper.ARABIC}. If any unmappable range
107.54 + * values are specified, such as {@code NumericShaper.Range.BALINESE},
107.55 + * those ranges are ignored.
107.56 + *
107.57 * @since 1.4
107.58 */
107.59
107.60 public final class NumericShaper implements java.io.Serializable {
107.61 + /**
107.62 + * A {@code NumericShaper.Range} represents a Unicode range of a
107.63 + * script having its own decimal digits. For example, the {@link
107.64 + * NumericShaper.Range#THAI} range has the Thai digits, THAI DIGIT
107.65 + * ZERO (U+0E50) to THAI DIGIT NINE (U+0E59).
107.66 + *
107.67 + * <p>The <code>Range</code> enum replaces the traditional bit
107.68 + * mask-based values (e.g., {@link NumericShaper#ARABIC}), and
107.69 + * supports more Unicode ranges than the bit mask-based ones. For
107.70 + * example, the following code using the bit mask:
107.71 + * <blockquote><pre>
107.72 + * NumericShaper.getContextualShaper(NumericShaper.ARABIC |
107.73 + * NumericShaper.TAMIL,
107.74 + * NumericShaper.EUROPEAN);
107.75 + * </pre></blockquote>
107.76 + * can be written using this enum as:
107.77 + * <blockquote><pre>
107.78 + * NumericShaper.getContextualShaper(EnumSet.of(
107.79 + * NumericShaper.Range.ARABIC,
107.80 + * NumericShaper.Range.TAMIL),
107.81 + * NumericShaper.Range.EUROPEAN);
107.82 + * </pre></blockquote>
107.83 + *
107.84 + * @since 1.7
107.85 + */
107.86 + public static enum Range {
107.87 + /**
107.88 + * The Latin (European) range with the Latin (ASCII) digits.
107.89 + */
107.90 + EUROPEAN ('\u0030', '\u0000', '\u0300'),
107.91 + /**
107.92 + * The Arabic range with the Arabic-Indic digits.
107.93 + */
107.94 + ARABIC ('\u0660', '\u0600', '\u0780'),
107.95 + /**
107.96 + * The Arabic range with the Eastern Arabic-Indic digits.
107.97 + */
107.98 + EASTERN_ARABIC ('\u06f0', '\u0600', '\u0780'),
107.99 + /**
107.100 + * The Devanagari range with the Devanagari digits.
107.101 + */
107.102 + DEVANAGARI ('\u0966', '\u0900', '\u0980'),
107.103 + /**
107.104 + * The Bengali range with the Bengali digits.
107.105 + */
107.106 + BENGALI ('\u09e6', '\u0980', '\u0a00'),
107.107 + /**
107.108 + * The Gurmukhi range with the Gurmukhi digits.
107.109 + */
107.110 + GURMUKHI ('\u0a66', '\u0a00', '\u0a80'),
107.111 + /**
107.112 + * The Gujarati range with the Gujarati digits.
107.113 + */
107.114 + GUJARATI ('\u0ae6', '\u0b00', '\u0b80'),
107.115 + /**
107.116 + * The Oriya range with the Oriya digits.
107.117 + */
107.118 + ORIYA ('\u0b66', '\u0b00', '\u0b80'),
107.119 + /**
107.120 + * The Tamil range with the Tamil digits.
107.121 + */
107.122 + TAMIL ('\u0be6', '\u0b80', '\u0c00'),
107.123 + /**
107.124 + * The Telugu range with the Telugu digits.
107.125 + */
107.126 + TELUGU ('\u0c66', '\u0c00', '\u0c80'),
107.127 + /**
107.128 + * The Kannada range with the Kannada digits.
107.129 + */
107.130 + KANNADA ('\u0ce6', '\u0c80', '\u0d00'),
107.131 + /**
107.132 + * The Malayalam range with the Malayalam digits.
107.133 + */
107.134 + MALAYALAM ('\u0d66', '\u0d00', '\u0d80'),
107.135 + /**
107.136 + * The Thai range with the Thai digits.
107.137 + */
107.138 + THAI ('\u0e50', '\u0e00', '\u0e80'),
107.139 + /**
107.140 + * The Lao range with the Lao digits.
107.141 + */
107.142 + LAO ('\u0ed0', '\u0e80', '\u0f00'),
107.143 + /**
107.144 + * The Tibetan range with the Tibetan digits.
107.145 + */
107.146 + TIBETAN ('\u0f20', '\u0f00', '\u1000'),
107.147 + /**
107.148 + * The Myanmar range with the Myanmar digits.
107.149 + */
107.150 + MYANMAR ('\u1040', '\u1000', '\u1080'),
107.151 + /**
107.152 + * The Ethiopic range with the Ethiopic digits. Ethiopic
107.153 + * does not have a decimal digit 0 so Latin (European) 0 is
107.154 + * used.
107.155 + */
107.156 + ETHIOPIC ('\u1369', '\u1200', '\u1380') {
107.157 + @Override
107.158 + char getNumericBase() { return 1; }
107.159 + },
107.160 + /**
107.161 + * The Khmer range with the Khmer digits.
107.162 + */
107.163 + KHMER ('\u17e0', '\u1780', '\u1800'),
107.164 + /**
107.165 + * The Mongolian range with the Mongolian digits.
107.166 + */
107.167 + MONGOLIAN ('\u1810', '\u1800', '\u1900'),
107.168 + /**
107.169 + * The N'Ko range with the N'Ko digits.
107.170 + */
107.171 + NKO ('\u07c0', '\u07c0', '\u0800'),
107.172 + /**
107.173 + * The Myanmar range with the Myanmar Shan digits.
107.174 + */
107.175 + MYANMAR_SHAN ('\u1090', '\u1000', '\u10a0'),
107.176 + /**
107.177 + * The Limbu range with the Limbu digits.
107.178 + */
107.179 + LIMBU ('\u1946', '\u1900', '\u1950'),
107.180 + /**
107.181 + * The New Tai Lue range with the New Tai Lue digits.
107.182 + */
107.183 + NEW_TAI_LUE ('\u19d0', '\u1980', '\u19e0'),
107.184 + /**
107.185 + * The Balinese range with the Balinese digits.
107.186 + */
107.187 + BALINESE ('\u1b50', '\u1b00', '\u1b80'),
107.188 + /**
107.189 + * The Sundanese range with the Sundanese digits.
107.190 + */
107.191 + SUNDANESE ('\u1bb0', '\u1b80', '\u1bc0'),
107.192 + /**
107.193 + * The Lepcha range with the Lepcha digits.
107.194 + */
107.195 + LEPCHA ('\u1c40', '\u1c00', '\u1c50'),
107.196 + /**
107.197 + * The Ol Chiki range with the Ol Chiki digits.
107.198 + */
107.199 + OL_CHIKI ('\u1c50', '\u1c50', '\u1c80'),
107.200 + /**
107.201 + * The Vai range with the Vai digits.
107.202 + */
107.203 + VAI ('\ua620', '\ua500', '\ua640'),
107.204 + /**
107.205 + * The Saurashtra range with the Saurashtra digits.
107.206 + */
107.207 + SAURASHTRA ('\ua8d0', '\ua880', '\ua8e0'),
107.208 + /**
107.209 + * The Kayah Li range with the Kayah Li digits.
107.210 + */
107.211 + KAYAH_LI ('\ua900', '\ua900', '\ua930'),
107.212 + /**
107.213 + * The Cham range with the Cham digits.
107.214 + */
107.215 + CHAM ('\uaa50', '\uaa00', '\uaa60');
107.216 +
107.217 + private static final Range[] ranges = Range.class.getEnumConstants();
107.218 + static {
107.219 + // sort ranges[] by base for binary search
107.220 + Arrays.sort(ranges,
107.221 + new Comparator<Range>() {
107.222 + public int compare(Range s1, Range s2) {
107.223 + return s1.base > s2.base ? 1 : s1.base == s2.base ? 0 : -1;
107.224 + }
107.225 + });
107.226 + }
107.227 +
107.228 + private static int toRangeIndex(Range script) {
107.229 + int index = script.ordinal();
107.230 + return index < NUM_KEYS ? index : -1;
107.231 + }
107.232 +
107.233 + private static Range indexToRange(int index) {
107.234 + return index < NUM_KEYS ? Range.values()[index] : null;
107.235 + }
107.236 +
107.237 + private static int toRangeMask(Set<Range> ranges) {
107.238 + int m = 0;
107.239 + for (Range range : ranges) {
107.240 + int index = range.ordinal();
107.241 + if (index < NUM_KEYS) {
107.242 + m |= 1 << index;
107.243 + }
107.244 + }
107.245 + return m;
107.246 + }
107.247 +
107.248 + private static Set<Range> maskToRangeSet(int mask) {
107.249 + Set<Range> set = EnumSet.noneOf(Range.class);
107.250 + Range[] a = Range.values();
107.251 + for (int i = 0; i < NUM_KEYS; i++) {
107.252 + if ((mask & (1 << i)) != 0) {
107.253 + set.add(a[i]);
107.254 + }
107.255 + }
107.256 + return set;
107.257 + }
107.258 +
107.259 + // base character of range digits
107.260 + private final int base;
107.261 + // Unicode range
107.262 + private final int start, // inclusive
107.263 + end; // exclusive
107.264 +
107.265 + private Range(int base, int start, int end) {
107.266 + this.base = base - ('0' + getNumericBase());
107.267 + this.start = start;
107.268 + this.end = end;
107.269 + }
107.270 +
107.271 + private int getDigitBase() {
107.272 + return base;
107.273 + }
107.274 +
107.275 + char getNumericBase() {
107.276 + return 0;
107.277 + }
107.278 +
107.279 + private boolean inRange(int c) {
107.280 + return start <= c && c < end;
107.281 + }
107.282 + }
107.283 +
107.284 /** index of context for contextual shaping - values range from 0 to 18 */
107.285 private int key;
107.286
107.287 @@ -79,6 +334,25 @@
107.288 */
107.289 private int mask;
107.290
107.291 + /**
107.292 + * The context {@code Range} for contextual shaping or the {@code
107.293 + * Range} for non-contextual shaping. {@code null} for the bit
107.294 + * mask-based API.
107.295 + *
107.296 + * @since 1.7
107.297 + */
107.298 + private Range shapingRange;
107.299 +
107.300 + /**
107.301 + * {@code Set<Range>} indicating which Unicode ranges to
107.302 + * shape. {@code null} for the bit mask-based API.
107.303 + *
107.304 + * @since 1.7
107.305 + */
107.306 + private transient Set<Range> rangeSet;
107.307 +
107.308 + private static final long serialVersionUID = -8022764705923730308L;
107.309 +
107.310 /** Identifies the Latin-1 (European) and extended range, and
107.311 * Latin-1 (European) decimal base.
107.312 */
107.313 @@ -105,9 +379,8 @@
107.314 /** Identifies the ORIYA range and decimal base. */
107.315 public static final int ORIYA = 1<<7;
107.316
107.317 - /** Identifies the TAMIL range and decimal base. Tamil does not have a
107.318 - * decimal digit 0 so Latin-1 (European) 0 is used.
107.319 - */
107.320 + /** Identifies the TAMIL range and decimal base. */
107.321 + // TAMIL DIGIT ZERO was added in Unicode 4.1
107.322 public static final int TAMIL = 1<<8;
107.323
107.324 /** Identifies the TELUGU range and decimal base. */
107.325 @@ -140,7 +413,12 @@
107.326 /** Identifies the MONGOLIAN range and decimal base. */
107.327 public static final int MONGOLIAN = 1<<18;
107.328
107.329 - /** Identifies all ranges, for full contextual shaping. */
107.330 + /** Identifies all ranges, for full contextual shaping.
107.331 + *
107.332 + * <p>This constant specifies all of the bit mask-based
107.333 + * ranges. Use {@code EmunSet.allOf(NumericShaper.Range.class)} to
107.334 + * specify all of the enum-based ranges.
107.335 + */
107.336 public static final int ALL_RANGES = 0x0007ffff;
107.337
107.338 private static final int EUROPEAN_KEY = 0;
107.339 @@ -163,42 +441,20 @@
107.340 private static final int KHMER_KEY = 17;
107.341 private static final int MONGOLIAN_KEY = 18;
107.342
107.343 - private static final int NUM_KEYS = 19;
107.344 -
107.345 - private static final String[] keyNames = {
107.346 - "EUROPEAN",
107.347 - "ARABIC",
107.348 - "EASTERN_ARABIC",
107.349 - "DEVANAGARI",
107.350 - "BENGALI",
107.351 - "GURMUKHI",
107.352 - "GUJARATI",
107.353 - "ORIYA",
107.354 - "TAMIL",
107.355 - "TELUGU",
107.356 - "KANNADA",
107.357 - "MALAYALAM",
107.358 - "THAI",
107.359 - "LAO",
107.360 - "TIBETAN",
107.361 - "MYANMAR",
107.362 - "ETHIOPIC",
107.363 - "KHMER",
107.364 - "MONGOLIAN"
107.365 - };
107.366 + private static final int NUM_KEYS = MONGOLIAN_KEY + 1; // fixed
107.367
107.368 private static final int CONTEXTUAL_MASK = 1<<31;
107.369
107.370 private static final char[] bases = {
107.371 '\u0030' - '\u0030', // EUROPEAN
107.372 - '\u0660' - '\u0030', // ARABIC
107.373 - '\u06f0' - '\u0030', // EASTERN_ARABIC
107.374 + '\u0660' - '\u0030', // ARABIC-INDIC
107.375 + '\u06f0' - '\u0030', // EXTENDED ARABIC-INDIC (EASTERN_ARABIC)
107.376 '\u0966' - '\u0030', // DEVANAGARI
107.377 '\u09e6' - '\u0030', // BENGALI
107.378 '\u0a66' - '\u0030', // GURMUKHI
107.379 '\u0ae6' - '\u0030', // GUJARATI
107.380 '\u0b66' - '\u0030', // ORIYA
107.381 - '\u0be7' - '\u0030', // TAMIL - note missing zero
107.382 + '\u0be6' - '\u0030', // TAMIL - zero was added in Unicode 4.1
107.383 '\u0c66' - '\u0030', // TELUGU
107.384 '\u0ce6' - '\u0030', // KANNADA
107.385 '\u0d66' - '\u0030', // MALAYALAM
107.386 @@ -206,7 +462,7 @@
107.387 '\u0ed0' - '\u0030', // LAO
107.388 '\u0f20' - '\u0030', // TIBETAN
107.389 '\u1040' - '\u0030', // MYANMAR
107.390 - '\u1369' - '\u0030', // ETHIOPIC
107.391 + '\u1369' - '\u0031', // ETHIOPIC - no zero
107.392 '\u17e0' - '\u0030', // KHMER
107.393 '\u1810' - '\u0030', // MONGOLIAN
107.394 };
107.395 @@ -215,14 +471,14 @@
107.396
107.397 private static final char[] contexts = {
107.398 '\u0000', '\u0300', // 'EUROPEAN' (really latin-1 and extended)
107.399 - '\u0600', '\u0700', // ARABIC
107.400 - '\u0600', '\u0700', // EASTERN_ARABIC -- note overlap with arabic
107.401 + '\u0600', '\u0780', // ARABIC
107.402 + '\u0600', '\u0780', // EASTERN_ARABIC -- note overlap with arabic
107.403 '\u0900', '\u0980', // DEVANAGARI
107.404 '\u0980', '\u0a00', // BENGALI
107.405 '\u0a00', '\u0a80', // GURMUKHI
107.406 '\u0a80', '\u0b00', // GUJARATI
107.407 '\u0b00', '\u0b80', // ORIYA
107.408 - '\u0b80', '\u0c00', // TAMIL - note missing zero
107.409 + '\u0b80', '\u0c00', // TAMIL
107.410 '\u0c00', '\u0c80', // TELUGU
107.411 '\u0c80', '\u0d00', // KANNADA
107.412 '\u0d00', '\u0d80', // MALAYALAM
107.413 @@ -230,7 +486,7 @@
107.414 '\u0e80', '\u0f00', // LAO
107.415 '\u0f00', '\u1000', // TIBETAN
107.416 '\u1000', '\u1080', // MYANMAR
107.417 - '\u1200', '\u1380', // ETHIOPIC
107.418 + '\u1200', '\u1380', // ETHIOPIC - note missing zero
107.419 '\u1780', '\u1800', // KHMER
107.420 '\u1800', '\u1900', // MONGOLIAN
107.421 '\uffff',
107.422 @@ -254,378 +510,290 @@
107.423 return (ctCache & 0x1) == 0 ? (ctCache / 2) : EUROPEAN_KEY;
107.424 }
107.425
107.426 + // cache for the NumericShaper.Range version
107.427 + private transient volatile Range currentRange = Range.EUROPEAN;
107.428 +
107.429 + private Range rangeForCodePoint(int codepoint) {
107.430 + Range range = currentRange;
107.431 + if (range.inRange(codepoint)) {
107.432 + return range;
107.433 + }
107.434 +
107.435 + final Range[] ranges = Range.ranges;
107.436 + int lo = 0;
107.437 + int hi = ranges.length - 1;
107.438 + while (lo <= hi) {
107.439 + int mid = (lo + hi) / 2;
107.440 + range = ranges[mid];
107.441 + if (codepoint < range.start) {
107.442 + hi = mid - 1;
107.443 + } else if (codepoint >= range.end) {
107.444 + lo = mid + 1;
107.445 + } else {
107.446 + currentRange = range;
107.447 + return range;
107.448 + }
107.449 + }
107.450 + return Range.EUROPEAN;
107.451 + }
107.452 +
107.453 /*
107.454 * A range table of strong directional characters (types L, R, AL).
107.455 * Even (left) indexes are starts of ranges of non-strong-directional (or undefined)
107.456 * characters, odd (right) indexes are starts of ranges of strong directional
107.457 * characters.
107.458 */
107.459 - private static char[] strongTable = {
107.460 - '\u0000', '\u0041',
107.461 - '\u005b', '\u0061',
107.462 - '\u007b', '\u00aa',
107.463 - '\u00ab', '\u00b5',
107.464 - '\u00b6', '\u00ba',
107.465 - '\u00bb', '\u00c0',
107.466 - '\u00d7', '\u00d8',
107.467 - '\u00f7', '\u00f8',
107.468 - '\u0220', '\u0222',
107.469 - '\u0234', '\u0250',
107.470 - '\u02ae', '\u02b0',
107.471 - '\u02b9', '\u02bb',
107.472 - '\u02c2', '\u02d0',
107.473 - '\u02d2', '\u02e0',
107.474 - '\u02e5', '\u02ee',
107.475 - '\u02ef', '\u037a',
107.476 - '\u037b', '\u0386',
107.477 - '\u0387', '\u0388',
107.478 - '\u038b', '\u038c',
107.479 - '\u038d', '\u038e',
107.480 - '\u03a2', '\u03a3',
107.481 - '\u03cf', '\u03d0',
107.482 - '\u03d8', '\u03da',
107.483 - '\u03f4', '\u0400',
107.484 - '\u0483', '\u048c',
107.485 - '\u04c5', '\u04c7',
107.486 - '\u04c9', '\u04cb',
107.487 - '\u04cd', '\u04d0',
107.488 - '\u04f6', '\u04f8',
107.489 - '\u04fa', '\u0531',
107.490 - '\u0557', '\u0559',
107.491 - '\u0560', '\u0561',
107.492 - '\u0588', '\u0589',
107.493 - '\u058a', '\u05be',
107.494 - '\u05bf', '\u05c0',
107.495 - '\u05c1', '\u05c3',
107.496 - '\u05c4', '\u05d0',
107.497 - '\u05eb', '\u05f0',
107.498 - '\u05f5', '\u061b',
107.499 - '\u061c', '\u061f',
107.500 - '\u0620', '\u0621',
107.501 - '\u063b', '\u0640',
107.502 - '\u064b', '\u066d',
107.503 - '\u066e', '\u0671',
107.504 - '\u06d6', '\u06e5',
107.505 - '\u06e7', '\u06fa',
107.506 - '\u06ff', '\u0700',
107.507 - '\u070e', '\u0710',
107.508 - '\u0711', '\u0712',
107.509 - '\u072d', '\u0780',
107.510 - '\u07a6', '\u0903',
107.511 - '\u0904', '\u0905',
107.512 - '\u093a', '\u093d',
107.513 - '\u0941', '\u0949',
107.514 - '\u094d', '\u0950',
107.515 - '\u0951', '\u0958',
107.516 - '\u0962', '\u0964',
107.517 - '\u0971', '\u0982',
107.518 - '\u0984', '\u0985',
107.519 - '\u098d', '\u098f',
107.520 - '\u0991', '\u0993',
107.521 - '\u09a9', '\u09aa',
107.522 - '\u09b1', '\u09b2',
107.523 - '\u09b3', '\u09b6',
107.524 - '\u09ba', '\u09be',
107.525 - '\u09c1', '\u09c7',
107.526 - '\u09c9', '\u09cb',
107.527 - '\u09cd', '\u09d7',
107.528 - '\u09d8', '\u09dc',
107.529 - '\u09de', '\u09df',
107.530 - '\u09e2', '\u09e6',
107.531 - '\u09f2', '\u09f4',
107.532 - '\u09fb', '\u0a05',
107.533 - '\u0a0b', '\u0a0f',
107.534 - '\u0a11', '\u0a13',
107.535 - '\u0a29', '\u0a2a',
107.536 - '\u0a31', '\u0a32',
107.537 - '\u0a34', '\u0a35',
107.538 - '\u0a37', '\u0a38',
107.539 - '\u0a3a', '\u0a3e',
107.540 - '\u0a41', '\u0a59',
107.541 - '\u0a5d', '\u0a5e',
107.542 - '\u0a5f', '\u0a66',
107.543 - '\u0a70', '\u0a72',
107.544 - '\u0a75', '\u0a83',
107.545 - '\u0a84', '\u0a85',
107.546 - '\u0a8c', '\u0a8d',
107.547 - '\u0a8e', '\u0a8f',
107.548 - '\u0a92', '\u0a93',
107.549 - '\u0aa9', '\u0aaa',
107.550 - '\u0ab1', '\u0ab2',
107.551 - '\u0ab4', '\u0ab5',
107.552 - '\u0aba', '\u0abd',
107.553 - '\u0ac1', '\u0ac9',
107.554 - '\u0aca', '\u0acb',
107.555 - '\u0acd', '\u0ad0',
107.556 - '\u0ad1', '\u0ae0',
107.557 - '\u0ae1', '\u0ae6',
107.558 - '\u0af0', '\u0b02',
107.559 - '\u0b04', '\u0b05',
107.560 - '\u0b0d', '\u0b0f',
107.561 - '\u0b11', '\u0b13',
107.562 - '\u0b29', '\u0b2a',
107.563 - '\u0b31', '\u0b32',
107.564 - '\u0b34', '\u0b36',
107.565 - '\u0b3a', '\u0b3d',
107.566 - '\u0b3f', '\u0b40',
107.567 - '\u0b41', '\u0b47',
107.568 - '\u0b49', '\u0b4b',
107.569 - '\u0b4d', '\u0b57',
107.570 - '\u0b58', '\u0b5c',
107.571 - '\u0b5e', '\u0b5f',
107.572 - '\u0b62', '\u0b66',
107.573 - '\u0b71', '\u0b83',
107.574 - '\u0b84', '\u0b85',
107.575 - '\u0b8b', '\u0b8e',
107.576 - '\u0b91', '\u0b92',
107.577 - '\u0b96', '\u0b99',
107.578 - '\u0b9b', '\u0b9c',
107.579 - '\u0b9d', '\u0b9e',
107.580 - '\u0ba0', '\u0ba3',
107.581 - '\u0ba5', '\u0ba8',
107.582 - '\u0bab', '\u0bae',
107.583 - '\u0bb6', '\u0bb7',
107.584 - '\u0bba', '\u0bbe',
107.585 - '\u0bc0', '\u0bc1',
107.586 - '\u0bc3', '\u0bc6',
107.587 - '\u0bc9', '\u0bca',
107.588 - '\u0bcd', '\u0bd7',
107.589 - '\u0bd8', '\u0be7',
107.590 - '\u0bf3', '\u0c01',
107.591 - '\u0c04', '\u0c05',
107.592 - '\u0c0d', '\u0c0e',
107.593 - '\u0c11', '\u0c12',
107.594 - '\u0c29', '\u0c2a',
107.595 - '\u0c34', '\u0c35',
107.596 - '\u0c3a', '\u0c41',
107.597 - '\u0c45', '\u0c60',
107.598 - '\u0c62', '\u0c66',
107.599 - '\u0c70', '\u0c82',
107.600 - '\u0c84', '\u0c85',
107.601 - '\u0c8d', '\u0c8e',
107.602 - '\u0c91', '\u0c92',
107.603 - '\u0ca9', '\u0caa',
107.604 - '\u0cb4', '\u0cb5',
107.605 - '\u0cba', '\u0cbe',
107.606 - '\u0cbf', '\u0cc0',
107.607 - '\u0cc5', '\u0cc7',
107.608 - '\u0cc9', '\u0cca',
107.609 - '\u0ccc', '\u0cd5',
107.610 - '\u0cd7', '\u0cde',
107.611 - '\u0cdf', '\u0ce0',
107.612 - '\u0ce2', '\u0ce6',
107.613 - '\u0cf0', '\u0d02',
107.614 - '\u0d04', '\u0d05',
107.615 - '\u0d0d', '\u0d0e',
107.616 - '\u0d11', '\u0d12',
107.617 - '\u0d29', '\u0d2a',
107.618 - '\u0d3a', '\u0d3e',
107.619 - '\u0d41', '\u0d46',
107.620 - '\u0d49', '\u0d4a',
107.621 - '\u0d4d', '\u0d57',
107.622 - '\u0d58', '\u0d60',
107.623 - '\u0d62', '\u0d66',
107.624 - '\u0d70', '\u0d82',
107.625 - '\u0d84', '\u0d85',
107.626 - '\u0d97', '\u0d9a',
107.627 - '\u0db2', '\u0db3',
107.628 - '\u0dbc', '\u0dbd',
107.629 - '\u0dbe', '\u0dc0',
107.630 - '\u0dc7', '\u0dcf',
107.631 - '\u0dd2', '\u0dd8',
107.632 - '\u0de0', '\u0df2',
107.633 - '\u0df5', '\u0e01',
107.634 - '\u0e31', '\u0e32',
107.635 - '\u0e34', '\u0e40',
107.636 - '\u0e47', '\u0e4f',
107.637 - '\u0e5c', '\u0e81',
107.638 - '\u0e83', '\u0e84',
107.639 - '\u0e85', '\u0e87',
107.640 - '\u0e89', '\u0e8a',
107.641 - '\u0e8b', '\u0e8d',
107.642 - '\u0e8e', '\u0e94',
107.643 - '\u0e98', '\u0e99',
107.644 - '\u0ea0', '\u0ea1',
107.645 - '\u0ea4', '\u0ea5',
107.646 - '\u0ea6', '\u0ea7',
107.647 - '\u0ea8', '\u0eaa',
107.648 - '\u0eac', '\u0ead',
107.649 - '\u0eb1', '\u0eb2',
107.650 - '\u0eb4', '\u0ebd',
107.651 - '\u0ebe', '\u0ec0',
107.652 - '\u0ec5', '\u0ec6',
107.653 - '\u0ec7', '\u0ed0',
107.654 - '\u0eda', '\u0edc',
107.655 - '\u0ede', '\u0f00',
107.656 - '\u0f18', '\u0f1a',
107.657 - '\u0f35', '\u0f36',
107.658 - '\u0f37', '\u0f38',
107.659 - '\u0f39', '\u0f3e',
107.660 - '\u0f48', '\u0f49',
107.661 - '\u0f6b', '\u0f7f',
107.662 - '\u0f80', '\u0f85',
107.663 - '\u0f86', '\u0f88',
107.664 - '\u0f8c', '\u0fbe',
107.665 - '\u0fc6', '\u0fc7',
107.666 - '\u0fcd', '\u0fcf',
107.667 - '\u0fd0', '\u1000',
107.668 - '\u1022', '\u1023',
107.669 - '\u1028', '\u1029',
107.670 - '\u102b', '\u102c',
107.671 - '\u102d', '\u1031',
107.672 - '\u1032', '\u1038',
107.673 - '\u1039', '\u1040',
107.674 - '\u1058', '\u10a0',
107.675 - '\u10c6', '\u10d0',
107.676 - '\u10f7', '\u10fb',
107.677 - '\u10fc', '\u1100',
107.678 - '\u115a', '\u115f',
107.679 - '\u11a3', '\u11a8',
107.680 - '\u11fa', '\u1200',
107.681 - '\u1207', '\u1208',
107.682 - '\u1247', '\u1248',
107.683 - '\u1249', '\u124a',
107.684 - '\u124e', '\u1250',
107.685 - '\u1257', '\u1258',
107.686 - '\u1259', '\u125a',
107.687 - '\u125e', '\u1260',
107.688 - '\u1287', '\u1288',
107.689 - '\u1289', '\u128a',
107.690 - '\u128e', '\u1290',
107.691 - '\u12af', '\u12b0',
107.692 - '\u12b1', '\u12b2',
107.693 - '\u12b6', '\u12b8',
107.694 - '\u12bf', '\u12c0',
107.695 - '\u12c1', '\u12c2',
107.696 - '\u12c6', '\u12c8',
107.697 - '\u12cf', '\u12d0',
107.698 - '\u12d7', '\u12d8',
107.699 - '\u12ef', '\u12f0',
107.700 - '\u130f', '\u1310',
107.701 - '\u1311', '\u1312',
107.702 - '\u1316', '\u1318',
107.703 - '\u131f', '\u1320',
107.704 - '\u1347', '\u1348',
107.705 - '\u135b', '\u1361',
107.706 - '\u137d', '\u13a0',
107.707 - '\u13f5', '\u1401',
107.708 - '\u1677', '\u1681',
107.709 - '\u169b', '\u16a0',
107.710 - '\u16f1', '\u1780',
107.711 - '\u17b7', '\u17be',
107.712 - '\u17c6', '\u17c7',
107.713 - '\u17c9', '\u17d4',
107.714 - '\u17db', '\u17dc',
107.715 - '\u17dd', '\u17e0',
107.716 - '\u17ea', '\u1810',
107.717 - '\u181a', '\u1820',
107.718 - '\u1878', '\u1880',
107.719 - '\u18a9', '\u1e00',
107.720 - '\u1e9c', '\u1ea0',
107.721 - '\u1efa', '\u1f00',
107.722 - '\u1f16', '\u1f18',
107.723 - '\u1f1e', '\u1f20',
107.724 - '\u1f46', '\u1f48',
107.725 - '\u1f4e', '\u1f50',
107.726 - '\u1f58', '\u1f59',
107.727 - '\u1f5a', '\u1f5b',
107.728 - '\u1f5c', '\u1f5d',
107.729 - '\u1f5e', '\u1f5f',
107.730 - '\u1f7e', '\u1f80',
107.731 - '\u1fb5', '\u1fb6',
107.732 - '\u1fbd', '\u1fbe',
107.733 - '\u1fbf', '\u1fc2',
107.734 - '\u1fc5', '\u1fc6',
107.735 - '\u1fcd', '\u1fd0',
107.736 - '\u1fd4', '\u1fd6',
107.737 - '\u1fdc', '\u1fe0',
107.738 - '\u1fed', '\u1ff2',
107.739 - '\u1ff5', '\u1ff6',
107.740 - '\u1ffd', '\u200e',
107.741 - '\u2010', '\u207f',
107.742 - '\u2080', '\u2102',
107.743 - '\u2103', '\u2107',
107.744 - '\u2108', '\u210a',
107.745 - '\u2114', '\u2115',
107.746 - '\u2116', '\u2119',
107.747 - '\u211e', '\u2124',
107.748 - '\u2125', '\u2126',
107.749 - '\u2127', '\u2128',
107.750 - '\u2129', '\u212a',
107.751 - '\u212e', '\u212f',
107.752 - '\u2132', '\u2133',
107.753 - '\u213a', '\u2160',
107.754 - '\u2184', '\u2336',
107.755 - '\u237b', '\u2395',
107.756 - '\u2396', '\u249c',
107.757 - '\u24ea', '\u3005',
107.758 - '\u3008', '\u3021',
107.759 - '\u302a', '\u3031',
107.760 - '\u3036', '\u3038',
107.761 - '\u303b', '\u3041',
107.762 - '\u3095', '\u309d',
107.763 - '\u309f', '\u30a1',
107.764 - '\u30fb', '\u30fc',
107.765 - '\u30ff', '\u3105',
107.766 - '\u312d', '\u3131',
107.767 - '\u318f', '\u3190',
107.768 - '\u31b8', '\u3200',
107.769 - '\u321d', '\u3220',
107.770 - '\u3244', '\u3260',
107.771 - '\u327c', '\u327f',
107.772 - '\u32b1', '\u32c0',
107.773 - '\u32cc', '\u32d0',
107.774 - '\u32ff', '\u3300',
107.775 - '\u3377', '\u337b',
107.776 - '\u33de', '\u33e0',
107.777 - '\u33ff', '\u3400',
107.778 - '\u4db6', '\u4e00',
107.779 - '\u9fa6', '\ua000',
107.780 - '\ua48d', '\uac00',
107.781 - '\ud7a4', '\uf900',
107.782 - '\ufa2e', '\ufb00',
107.783 - '\ufb07', '\ufb13',
107.784 - '\ufb18', '\ufb1d',
107.785 - '\ufb1e', '\ufb1f',
107.786 - '\ufb29', '\ufb2a',
107.787 - '\ufb37', '\ufb38',
107.788 - '\ufb3d', '\ufb3e',
107.789 - '\ufb3f', '\ufb40',
107.790 - '\ufb42', '\ufb43',
107.791 - '\ufb45', '\ufb46',
107.792 - '\ufbb2', '\ufbd3',
107.793 - '\ufd3e', '\ufd50',
107.794 - '\ufd90', '\ufd92',
107.795 - '\ufdc8', '\ufdf0',
107.796 - '\ufdfc', '\ufe70',
107.797 - '\ufe73', '\ufe74',
107.798 - '\ufe75', '\ufe76',
107.799 - '\ufefd', '\uff21',
107.800 - '\uff3b', '\uff41',
107.801 - '\uff5b', '\uff66',
107.802 - '\uffbf', '\uffc2',
107.803 - '\uffc8', '\uffca',
107.804 - '\uffd0', '\uffd2',
107.805 - '\uffd8', '\uffda',
107.806 - '\uffdd', '\uffff' // last entry is sentinel, actually never checked
107.807 + private static int[] strongTable = {
107.808 + 0x0000, 0x0041,
107.809 + 0x005b, 0x0061,
107.810 + 0x007b, 0x00aa,
107.811 + 0x00ab, 0x00b5,
107.812 + 0x00b6, 0x00ba,
107.813 + 0x00bb, 0x00c0,
107.814 + 0x00d7, 0x00d8,
107.815 + 0x00f7, 0x00f8,
107.816 + 0x02b9, 0x02bb,
107.817 + 0x02c2, 0x02d0,
107.818 + 0x02d2, 0x02e0,
107.819 + 0x02e5, 0x02ee,
107.820 + 0x02ef, 0x0370,
107.821 + 0x0374, 0x0376,
107.822 + 0x037e, 0x0386,
107.823 + 0x0387, 0x0388,
107.824 + 0x03f6, 0x03f7,
107.825 + 0x0483, 0x048a,
107.826 + 0x058a, 0x05be,
107.827 + 0x05bf, 0x05c0,
107.828 + 0x05c1, 0x05c3,
107.829 + 0x05c4, 0x05c6,
107.830 + 0x05c7, 0x05d0,
107.831 + 0x0600, 0x0608,
107.832 + 0x0609, 0x060b,
107.833 + 0x060c, 0x060d,
107.834 + 0x060e, 0x061b,
107.835 + 0x064b, 0x066d,
107.836 + 0x0670, 0x0671,
107.837 + 0x06d6, 0x06e5,
107.838 + 0x06e7, 0x06ee,
107.839 + 0x06f0, 0x06fa,
107.840 + 0x070f, 0x0710,
107.841 + 0x0711, 0x0712,
107.842 + 0x0730, 0x074d,
107.843 + 0x07a6, 0x07b1,
107.844 + 0x07eb, 0x07f4,
107.845 + 0x07f6, 0x07fa,
107.846 + 0x0901, 0x0903,
107.847 + 0x093c, 0x093d,
107.848 + 0x0941, 0x0949,
107.849 + 0x094d, 0x0950,
107.850 + 0x0951, 0x0958,
107.851 + 0x0962, 0x0964,
107.852 + 0x0981, 0x0982,
107.853 + 0x09bc, 0x09bd,
107.854 + 0x09c1, 0x09c7,
107.855 + 0x09cd, 0x09ce,
107.856 + 0x09e2, 0x09e6,
107.857 + 0x09f2, 0x09f4,
107.858 + 0x0a01, 0x0a03,
107.859 + 0x0a3c, 0x0a3e,
107.860 + 0x0a41, 0x0a59,
107.861 + 0x0a70, 0x0a72,
107.862 + 0x0a75, 0x0a83,
107.863 + 0x0abc, 0x0abd,
107.864 + 0x0ac1, 0x0ac9,
107.865 + 0x0acd, 0x0ad0,
107.866 + 0x0ae2, 0x0ae6,
107.867 + 0x0af1, 0x0b02,
107.868 + 0x0b3c, 0x0b3d,
107.869 + 0x0b3f, 0x0b40,
107.870 + 0x0b41, 0x0b47,
107.871 + 0x0b4d, 0x0b57,
107.872 + 0x0b62, 0x0b66,
107.873 + 0x0b82, 0x0b83,
107.874 + 0x0bc0, 0x0bc1,
107.875 + 0x0bcd, 0x0bd0,
107.876 + 0x0bf3, 0x0c01,
107.877 + 0x0c3e, 0x0c41,
107.878 + 0x0c46, 0x0c58,
107.879 + 0x0c62, 0x0c66,
107.880 + 0x0c78, 0x0c7f,
107.881 + 0x0cbc, 0x0cbd,
107.882 + 0x0ccc, 0x0cd5,
107.883 + 0x0ce2, 0x0ce6,
107.884 + 0x0cf1, 0x0d02,
107.885 + 0x0d41, 0x0d46,
107.886 + 0x0d4d, 0x0d57,
107.887 + 0x0d62, 0x0d66,
107.888 + 0x0dca, 0x0dcf,
107.889 + 0x0dd2, 0x0dd8,
107.890 + 0x0e31, 0x0e32,
107.891 + 0x0e34, 0x0e40,
107.892 + 0x0e47, 0x0e4f,
107.893 + 0x0eb1, 0x0eb2,
107.894 + 0x0eb4, 0x0ebd,
107.895 + 0x0ec8, 0x0ed0,
107.896 + 0x0f18, 0x0f1a,
107.897 + 0x0f35, 0x0f36,
107.898 + 0x0f37, 0x0f38,
107.899 + 0x0f39, 0x0f3e,
107.900 + 0x0f71, 0x0f7f,
107.901 + 0x0f80, 0x0f85,
107.902 + 0x0f86, 0x0f88,
107.903 + 0x0f90, 0x0fbe,
107.904 + 0x0fc6, 0x0fc7,
107.905 + 0x102d, 0x1031,
107.906 + 0x1032, 0x1038,
107.907 + 0x1039, 0x103b,
107.908 + 0x103d, 0x103f,
107.909 + 0x1058, 0x105a,
107.910 + 0x105e, 0x1061,
107.911 + 0x1071, 0x1075,
107.912 + 0x1082, 0x1083,
107.913 + 0x1085, 0x1087,
107.914 + 0x108d, 0x108e,
107.915 + 0x135f, 0x1360,
107.916 + 0x1390, 0x13a0,
107.917 + 0x1680, 0x1681,
107.918 + 0x169b, 0x16a0,
107.919 + 0x1712, 0x1720,
107.920 + 0x1732, 0x1735,
107.921 + 0x1752, 0x1760,
107.922 + 0x1772, 0x1780,
107.923 + 0x17b7, 0x17be,
107.924 + 0x17c6, 0x17c7,
107.925 + 0x17c9, 0x17d4,
107.926 + 0x17db, 0x17dc,
107.927 + 0x17dd, 0x17e0,
107.928 + 0x17f0, 0x1810,
107.929 + 0x18a9, 0x18aa,
107.930 + 0x1920, 0x1923,
107.931 + 0x1927, 0x1929,
107.932 + 0x1932, 0x1933,
107.933 + 0x1939, 0x1946,
107.934 + 0x19de, 0x1a00,
107.935 + 0x1a17, 0x1a19,
107.936 + 0x1b00, 0x1b04,
107.937 + 0x1b34, 0x1b35,
107.938 + 0x1b36, 0x1b3b,
107.939 + 0x1b3c, 0x1b3d,
107.940 + 0x1b42, 0x1b43,
107.941 + 0x1b6b, 0x1b74,
107.942 + 0x1b80, 0x1b82,
107.943 + 0x1ba2, 0x1ba6,
107.944 + 0x1ba8, 0x1baa,
107.945 + 0x1c2c, 0x1c34,
107.946 + 0x1c36, 0x1c3b,
107.947 + 0x1dc0, 0x1e00,
107.948 + 0x1fbd, 0x1fbe,
107.949 + 0x1fbf, 0x1fc2,
107.950 + 0x1fcd, 0x1fd0,
107.951 + 0x1fdd, 0x1fe0,
107.952 + 0x1fed, 0x1ff2,
107.953 + 0x1ffd, 0x200e,
107.954 + 0x2010, 0x2071,
107.955 + 0x2074, 0x207f,
107.956 + 0x2080, 0x2090,
107.957 + 0x20a0, 0x2102,
107.958 + 0x2103, 0x2107,
107.959 + 0x2108, 0x210a,
107.960 + 0x2114, 0x2115,
107.961 + 0x2116, 0x2119,
107.962 + 0x211e, 0x2124,
107.963 + 0x2125, 0x2126,
107.964 + 0x2127, 0x2128,
107.965 + 0x2129, 0x212a,
107.966 + 0x212e, 0x212f,
107.967 + 0x213a, 0x213c,
107.968 + 0x2140, 0x2145,
107.969 + 0x214a, 0x214e,
107.970 + 0x2153, 0x2160,
107.971 + 0x2190, 0x2336,
107.972 + 0x237b, 0x2395,
107.973 + 0x2396, 0x249c,
107.974 + 0x24ea, 0x26ac,
107.975 + 0x26ad, 0x2800,
107.976 + 0x2900, 0x2c00,
107.977 + 0x2ce5, 0x2d00,
107.978 + 0x2de0, 0x3005,
107.979 + 0x3008, 0x3021,
107.980 + 0x302a, 0x3031,
107.981 + 0x3036, 0x3038,
107.982 + 0x303d, 0x3041,
107.983 + 0x3099, 0x309d,
107.984 + 0x30a0, 0x30a1,
107.985 + 0x30fb, 0x30fc,
107.986 + 0x31c0, 0x31f0,
107.987 + 0x321d, 0x3220,
107.988 + 0x3250, 0x3260,
107.989 + 0x327c, 0x327f,
107.990 + 0x32b1, 0x32c0,
107.991 + 0x32cc, 0x32d0,
107.992 + 0x3377, 0x337b,
107.993 + 0x33de, 0x33e0,
107.994 + 0x33ff, 0x3400,
107.995 + 0x4dc0, 0x4e00,
107.996 + 0xa490, 0xa500,
107.997 + 0xa60d, 0xa610,
107.998 + 0xa66f, 0xa680,
107.999 + 0xa700, 0xa722,
107.1000 + 0xa788, 0xa789,
107.1001 + 0xa802, 0xa803,
107.1002 + 0xa806, 0xa807,
107.1003 + 0xa80b, 0xa80c,
107.1004 + 0xa825, 0xa827,
107.1005 + 0xa828, 0xa840,
107.1006 + 0xa874, 0xa880,
107.1007 + 0xa8c4, 0xa8ce,
107.1008 + 0xa926, 0xa92e,
107.1009 + 0xa947, 0xa952,
107.1010 + 0xaa29, 0xaa2f,
107.1011 + 0xaa31, 0xaa33,
107.1012 + 0xaa35, 0xaa40,
107.1013 + 0xaa43, 0xaa44,
107.1014 + 0xaa4c, 0xaa4d,
107.1015 + 0xfb1e, 0xfb1f,
107.1016 + 0xfb29, 0xfb2a,
107.1017 + 0xfd3e, 0xfd50,
107.1018 + 0xfdfd, 0xfe70,
107.1019 + 0xfeff, 0xff21,
107.1020 + 0xff3b, 0xff41,
107.1021 + 0xff5b, 0xff66,
107.1022 + 0xffe0, 0x10000,
107.1023 + 0x10101, 0x10102,
107.1024 + 0x10140, 0x101d0,
107.1025 + 0x101fd, 0x10280,
107.1026 + 0x1091f, 0x10920,
107.1027 + 0x10a01, 0x10a10,
107.1028 + 0x10a38, 0x10a40,
107.1029 + 0x1d167, 0x1d16a,
107.1030 + 0x1d173, 0x1d183,
107.1031 + 0x1d185, 0x1d18c,
107.1032 + 0x1d1aa, 0x1d1ae,
107.1033 + 0x1d200, 0x1d360,
107.1034 + 0x1d7ce, 0x20000,
107.1035 + 0xe0001, 0xf0000,
107.1036 + 0x10fffe, 0x10ffff // sentinel
107.1037 };
107.1038
107.1039
107.1040 // use a binary search with a cache
107.1041
107.1042 - private static int stCache = 0;
107.1043 + private transient volatile int stCache = 0;
107.1044
107.1045 - // warning, synchronize access to this as it modifies state
107.1046 - private static boolean isStrongDirectional(char c) {
107.1047 - if (c < strongTable[stCache]) {
107.1048 - stCache = search(c, strongTable, 0, stCache);
107.1049 - } else if (c >= strongTable[stCache + 1]) {
107.1050 - stCache = search(c, strongTable, stCache + 1, strongTable.length - stCache - 1);
107.1051 + private boolean isStrongDirectional(char c) {
107.1052 + int cachedIndex = stCache;
107.1053 + if (c < strongTable[cachedIndex]) {
107.1054 + cachedIndex = search(c, strongTable, 0, cachedIndex);
107.1055 + } else if (c >= strongTable[cachedIndex + 1]) {
107.1056 + cachedIndex = search(c, strongTable, cachedIndex + 1,
107.1057 + strongTable.length - cachedIndex - 1);
107.1058 }
107.1059 - return (stCache & 0x1) == 1;
107.1060 + boolean val = (cachedIndex & 0x1) == 1;
107.1061 + stCache = cachedIndex;
107.1062 + return val;
107.1063 }
107.1064
107.1065 - static private int getKeyFromMask(int mask) {
107.1066 + private static int getKeyFromMask(int mask) {
107.1067 int key = 0;
107.1068 while (key < NUM_KEYS && ((mask & (1<<key)) == 0)) {
107.1069 ++key;
107.1070 @@ -644,12 +812,27 @@
107.1071 * @return a non-contextual numeric shaper
107.1072 * @throws IllegalArgumentException if the range is not a single range
107.1073 */
107.1074 - static public NumericShaper getShaper(int singleRange) {
107.1075 + public static NumericShaper getShaper(int singleRange) {
107.1076 int key = getKeyFromMask(singleRange);
107.1077 return new NumericShaper(key, singleRange);
107.1078 }
107.1079
107.1080 /**
107.1081 + * Returns a shaper for the provided Unicode
107.1082 + * range. All Latin-1 (EUROPEAN) digits are converted to the
107.1083 + * corresponding decimal digits of the specified Unicode range.
107.1084 + *
107.1085 + * @param singleRange the Unicode range given by a {@link
107.1086 + * NumericShaper.Range} constant.
107.1087 + * @return a non-contextual {@code NumericShaper}.
107.1088 + * @throws NullPointerException if {@code singleRange} is {@code null}
107.1089 + * @since 1.7
107.1090 + */
107.1091 + public static NumericShaper getShaper(Range singleRange) {
107.1092 + return new NumericShaper(singleRange, EnumSet.of(singleRange));
107.1093 + }
107.1094 +
107.1095 + /**
107.1096 * Returns a contextual shaper for the provided unicode range(s).
107.1097 * Latin-1 (EUROPEAN) digits are converted to the decimal digits
107.1098 * corresponding to the range of the preceding text, if the
107.1099 @@ -663,12 +846,34 @@
107.1100 * @param ranges the specified Unicode ranges
107.1101 * @return a shaper for the specified ranges
107.1102 */
107.1103 - static public NumericShaper getContextualShaper(int ranges) {
107.1104 + public static NumericShaper getContextualShaper(int ranges) {
107.1105 ranges |= CONTEXTUAL_MASK;
107.1106 return new NumericShaper(EUROPEAN_KEY, ranges);
107.1107 }
107.1108
107.1109 /**
107.1110 + * Returns a contextual shaper for the provided Unicode
107.1111 + * range(s). The Latin-1 (EUROPEAN) digits are converted to the
107.1112 + * decimal digits corresponding to the range of the preceding
107.1113 + * text, if the range is one of the provided ranges.
107.1114 + *
107.1115 + * <p>The shaper assumes EUROPEAN as the starting context, that
107.1116 + * is, if EUROPEAN digits are encountered before any strong
107.1117 + * directional text in the string, the context is presumed to be
107.1118 + * EUROPEAN, and so the digits will not shape.
107.1119 + *
107.1120 + * @param ranges the specified Unicode ranges
107.1121 + * @return a contextual shaper for the specified ranges
107.1122 + * @throws NullPointerException if {@code ranges} is {@code null}.
107.1123 + * @since 1.7
107.1124 + */
107.1125 + public static NumericShaper getContextualShaper(Set<Range> ranges) {
107.1126 + NumericShaper shaper = new NumericShaper(Range.EUROPEAN, ranges);
107.1127 + shaper.mask = CONTEXTUAL_MASK;
107.1128 + return shaper;
107.1129 + }
107.1130 +
107.1131 + /**
107.1132 * Returns a contextual shaper for the provided unicode range(s).
107.1133 * Latin-1 (EUROPEAN) digits will be converted to the decimal digits
107.1134 * corresponding to the range of the preceding text, if the
107.1135 @@ -683,13 +888,38 @@
107.1136 * @throws IllegalArgumentException if the specified
107.1137 * <code>defaultContext</code> is not a single valid range.
107.1138 */
107.1139 - static public NumericShaper getContextualShaper(int ranges, int defaultContext) {
107.1140 + public static NumericShaper getContextualShaper(int ranges, int defaultContext) {
107.1141 int key = getKeyFromMask(defaultContext);
107.1142 ranges |= CONTEXTUAL_MASK;
107.1143 return new NumericShaper(key, ranges);
107.1144 }
107.1145
107.1146 /**
107.1147 + * Returns a contextual shaper for the provided Unicode range(s).
107.1148 + * The Latin-1 (EUROPEAN) digits will be converted to the decimal
107.1149 + * digits corresponding to the range of the preceding text, if the
107.1150 + * range is one of the provided ranges. The shaper uses {@code
107.1151 + * defaultContext} as the starting context.
107.1152 + *
107.1153 + * @param ranges the specified Unicode ranges
107.1154 + * @param defaultContext the starting context, such as
107.1155 + * {@code NumericShaper.Range.EUROPEAN}
107.1156 + * @return a contextual shaper for the specified Unicode ranges.
107.1157 + * @throws NullPointerException
107.1158 + * if {@code ranges} or {@code defaultContext} is {@code null}
107.1159 + * @since 1.7
107.1160 + */
107.1161 + public static NumericShaper getContextualShaper(Set<Range> ranges,
107.1162 + Range defaultContext) {
107.1163 + if (defaultContext == null) {
107.1164 + throw new NullPointerException();
107.1165 + }
107.1166 + NumericShaper shaper = new NumericShaper(defaultContext, ranges);
107.1167 + shaper.mask = CONTEXTUAL_MASK;
107.1168 + return shaper;
107.1169 + }
107.1170 +
107.1171 + /**
107.1172 * Private constructor.
107.1173 */
107.1174 private NumericShaper(int key, int mask) {
107.1175 @@ -697,6 +927,11 @@
107.1176 this.mask = mask;
107.1177 }
107.1178
107.1179 + private NumericShaper(Range defaultContext, Set<Range> ranges) {
107.1180 + this.shapingRange = defaultContext;
107.1181 + this.rangeSet = EnumSet.copyOf(ranges); // throws NPE if ranges is null.
107.1182 + }
107.1183 +
107.1184 /**
107.1185 * Converts the digits in the text that occur between start and
107.1186 * start + count.
107.1187 @@ -710,19 +945,13 @@
107.1188 * @throws NullPointerException if text is null
107.1189 */
107.1190 public void shape(char[] text, int start, int count) {
107.1191 - if (text == null) {
107.1192 - throw new NullPointerException("text is null");
107.1193 - }
107.1194 - if ((start < 0)
107.1195 - || (start > text.length)
107.1196 - || ((start + count) < 0)
107.1197 - || ((start + count) > text.length)) {
107.1198 - throw new IndexOutOfBoundsException(
107.1199 - "bad start or count for text of length " + text.length);
107.1200 - }
107.1201 -
107.1202 + checkParams(text, start, count);
107.1203 if (isContextual()) {
107.1204 - shapeContextually(text, start, count, key);
107.1205 + if (rangeSet == null) {
107.1206 + shapeContextually(text, start, count, key);
107.1207 + } else {
107.1208 + shapeContextually(text, start, count, shapingRange);
107.1209 + }
107.1210 } else {
107.1211 shapeNonContextually(text, start, count);
107.1212 }
107.1213 @@ -747,6 +976,60 @@
107.1214 * range.
107.1215 */
107.1216 public void shape(char[] text, int start, int count, int context) {
107.1217 + checkParams(text, start, count);
107.1218 + if (isContextual()) {
107.1219 + int ctxKey = getKeyFromMask(context);
107.1220 + if (rangeSet == null) {
107.1221 + shapeContextually(text, start, count, ctxKey);
107.1222 + } else {
107.1223 + shapeContextually(text, start, count, Range.values()[ctxKey]);
107.1224 + }
107.1225 + } else {
107.1226 + shapeNonContextually(text, start, count);
107.1227 + }
107.1228 + }
107.1229 +
107.1230 + /**
107.1231 + * Converts the digits in the text that occur between {@code
107.1232 + * start} and {@code start + count}, using the provided {@code
107.1233 + * context}. {@code Context} is ignored if the shaper is not a
107.1234 + * contextual shaper.
107.1235 + *
107.1236 + * @param text a {@code char} array
107.1237 + * @param start the index into {@code text} to start converting
107.1238 + * @param count the number of {@code char}s in {@code text}
107.1239 + * to convert
107.1240 + * @param context the context to which to convert the characters,
107.1241 + * such as {@code NumericShaper.Range.EUROPEAN}
107.1242 + * @throws IndexOutOfBoundsException
107.1243 + * if {@code start} or {@code start + count} is out of bounds
107.1244 + * @throws NullPointerException
107.1245 + * if {@code text} or {@code context} is null
107.1246 + * @since 1.7
107.1247 + */
107.1248 + public void shape(char[] text, int start, int count, Range context) {
107.1249 + checkParams(text, start, count);
107.1250 + if (context == null) {
107.1251 + throw new NullPointerException("context is null");
107.1252 + }
107.1253 +
107.1254 + if (isContextual()) {
107.1255 + if (rangeSet != null) {
107.1256 + shapeContextually(text, start, count, context);
107.1257 + } else {
107.1258 + int key = Range.toRangeIndex(context);
107.1259 + if (key >= 0) {
107.1260 + shapeContextually(text, start, count, key);
107.1261 + } else {
107.1262 + shapeContextually(text, start, count, shapingRange);
107.1263 + }
107.1264 + }
107.1265 + } else {
107.1266 + shapeNonContextually(text, start, count);
107.1267 + }
107.1268 + }
107.1269 +
107.1270 + private void checkParams(char[] text, int start, int count) {
107.1271 if (text == null) {
107.1272 throw new NullPointerException("text is null");
107.1273 }
107.1274 @@ -757,13 +1040,6 @@
107.1275 throw new IndexOutOfBoundsException(
107.1276 "bad start or count for text of length " + text.length);
107.1277 }
107.1278 -
107.1279 - if (isContextual()) {
107.1280 - int ctxKey = getKeyFromMask(context);
107.1281 - shapeContextually(text, start, count, ctxKey);
107.1282 - } else {
107.1283 - shapeNonContextually(text, start, count);
107.1284 - }
107.1285 }
107.1286
107.1287 /**
107.1288 @@ -785,6 +1061,10 @@
107.1289 * <blockquote>
107.1290 * <code>if ((shaper.getRanges() & shaper.ARABIC) != 0) { ... </code>
107.1291 * </blockquote>
107.1292 + *
107.1293 + * <p>Note that this method supports only the bit mask-based
107.1294 + * ranges. Call {@link #getRangeSet()} for the enum-based ranges.
107.1295 + *
107.1296 * @return the values for all the ranges to be shaped.
107.1297 */
107.1298 public int getRanges() {
107.1299 @@ -792,11 +1072,34 @@
107.1300 }
107.1301
107.1302 /**
107.1303 + * Returns a {@code Set} representing all the Unicode ranges in
107.1304 + * this {@code NumericShaper} that will be shaped.
107.1305 + *
107.1306 + * @return all the Unicode ranges to be shaped.
107.1307 + * @since 1.7
107.1308 + */
107.1309 + public Set<Range> getRangeSet() {
107.1310 + if (rangeSet != null) {
107.1311 + return EnumSet.copyOf(rangeSet);
107.1312 + }
107.1313 + return Range.maskToRangeSet(mask);
107.1314 + }
107.1315 +
107.1316 + /**
107.1317 * Perform non-contextual shaping.
107.1318 */
107.1319 private void shapeNonContextually(char[] text, int start, int count) {
107.1320 - int base = bases[key];
107.1321 - char minDigit = key == TAMIL_KEY ? '\u0031' : '\u0030'; // Tamil doesn't use decimal zero
107.1322 + int base;
107.1323 + char minDigit = '0';
107.1324 + if (shapingRange != null) {
107.1325 + base = shapingRange.getDigitBase();
107.1326 + minDigit += shapingRange.getNumericBase();
107.1327 + } else {
107.1328 + base = bases[key];
107.1329 + if (key == ETHIOPIC_KEY) {
107.1330 + minDigit++; // Ethiopic doesn't use decimal zero
107.1331 + }
107.1332 + }
107.1333 for (int i = start, e = start + count; i < e; ++i) {
107.1334 char c = text[i];
107.1335 if (c >= minDigit && c <= '\u0039') {
107.1336 @@ -807,7 +1110,7 @@
107.1337
107.1338 /**
107.1339 * Perform contextual shaping.
107.1340 - * Synchronized to protect caches used in getContextKey and isStrongDirectional.
107.1341 + * Synchronized to protect caches used in getContextKey.
107.1342 */
107.1343 private synchronized void shapeContextually(char[] text, int start, int count, int ctxKey) {
107.1344
107.1345 @@ -818,29 +1121,64 @@
107.1346 int lastkey = ctxKey;
107.1347
107.1348 int base = bases[ctxKey];
107.1349 - char minDigit = ctxKey == TAMIL_KEY ? '\u0031' : '\u0030'; // Tamil doesn't use decimal zero
107.1350 + char minDigit = ctxKey == ETHIOPIC_KEY ? '1' : '0'; // Ethiopic doesn't use decimal zero
107.1351
107.1352 - for (int i = start, e = start + count; i < e; ++i) {
107.1353 + synchronized (NumericShaper.class) {
107.1354 + for (int i = start, e = start + count; i < e; ++i) {
107.1355 + char c = text[i];
107.1356 + if (c >= minDigit && c <= '\u0039') {
107.1357 + text[i] = (char)(c + base);
107.1358 + }
107.1359 +
107.1360 + if (isStrongDirectional(c)) {
107.1361 + int newkey = getContextKey(c);
107.1362 + if (newkey != lastkey) {
107.1363 + lastkey = newkey;
107.1364 +
107.1365 + ctxKey = newkey;
107.1366 + if (((mask & EASTERN_ARABIC) != 0) && (ctxKey == ARABIC_KEY || ctxKey == EASTERN_ARABIC_KEY)) {
107.1367 + ctxKey = EASTERN_ARABIC_KEY;
107.1368 + } else if ((mask & (1<<ctxKey)) == 0) {
107.1369 + ctxKey = EUROPEAN_KEY;
107.1370 + }
107.1371 +
107.1372 + base = bases[ctxKey];
107.1373 +
107.1374 + minDigit = ctxKey == ETHIOPIC_KEY ? '1' : '0'; // Ethiopic doesn't use decimal zero
107.1375 + }
107.1376 + }
107.1377 + }
107.1378 + }
107.1379 + }
107.1380 +
107.1381 + private void shapeContextually(char[] text, int start, int count, Range ctxKey) {
107.1382 + if (ctxKey == null) {
107.1383 + ctxKey = Range.EUROPEAN;
107.1384 + }
107.1385 +
107.1386 + Range lastKey = ctxKey;
107.1387 + int base = ctxKey.getDigitBase();
107.1388 + char minDigit = (char)('0' + ctxKey.getNumericBase());
107.1389 + for (int i = start, end = start + count; i < end; ++i) {
107.1390 char c = text[i];
107.1391 - if (c >= minDigit && c <= '\u0039') {
107.1392 + if (c >= minDigit && c <= '9') {
107.1393 text[i] = (char)(c + base);
107.1394 + continue;
107.1395 }
107.1396 -
107.1397 if (isStrongDirectional(c)) {
107.1398 - int newkey = getContextKey(c);
107.1399 - if (newkey != lastkey) {
107.1400 - lastkey = newkey;
107.1401 -
107.1402 - ctxKey = newkey;
107.1403 - if (((mask & EASTERN_ARABIC) != 0) && (ctxKey == ARABIC_KEY || ctxKey == EASTERN_ARABIC_KEY)) {
107.1404 - ctxKey = EASTERN_ARABIC_KEY;
107.1405 - } else if ((mask & (1<<ctxKey)) == 0) {
107.1406 - ctxKey = EUROPEAN_KEY;
107.1407 + Range newKey = rangeForCodePoint(c);
107.1408 + if (newKey != lastKey) {
107.1409 + lastKey = newKey;
107.1410 + ctxKey = newKey;
107.1411 + if (rangeSet.contains(Range.EUROPEAN)
107.1412 + && (ctxKey == Range.ARABIC || ctxKey == Range.EASTERN_ARABIC)) {
107.1413 + ctxKey = Range.EASTERN_ARABIC;
107.1414 + } else if (!rangeSet.contains(ctxKey)) {
107.1415 + ctxKey = Range.EUROPEAN;
107.1416 }
107.1417
107.1418 - base = bases[ctxKey];
107.1419 -
107.1420 - minDigit = ctxKey == TAMIL_KEY ? '\u0031' : '\u0030'; // Tamil doesn't use decimal zero
107.1421 + base = ctxKey.getDigitBase();
107.1422 + minDigit = (char)('0' + ctxKey.getNumericBase());
107.1423 }
107.1424 }
107.1425 }
107.1426 @@ -852,12 +1190,28 @@
107.1427 * @see java.lang.Object#hashCode
107.1428 */
107.1429 public int hashCode() {
107.1430 - return mask;
107.1431 + int hash = mask;
107.1432 + if (rangeSet != null) {
107.1433 + // Use the CONTEXTUAL_MASK bit only for the enum-based
107.1434 + // NumericShaper. A deserialized NumericShaper might have
107.1435 + // bit masks.
107.1436 + hash &= CONTEXTUAL_MASK;
107.1437 + hash ^= rangeSet.hashCode();
107.1438 + }
107.1439 + return hash;
107.1440 }
107.1441
107.1442 /**
107.1443 - * Returns true if the specified object is an instance of
107.1444 - * <code>NumericShaper</code> and shapes identically to this one.
107.1445 + * Returns {@code true} if the specified object is an instance of
107.1446 + * <code>NumericShaper</code> and shapes identically to this one,
107.1447 + * regardless of the range representations, the bit mask or the
107.1448 + * enum. For example, the following code produces {@code "true"}.
107.1449 + * <blockquote><pre>
107.1450 + * NumericShaper ns1 = NumericShaper.getShaper(NumericShaper.ARABIC);
107.1451 + * NumericShaper ns2 = NumericShaper.getShaper(NumericShaper.Range.ARABIC);
107.1452 + * System.out.println(ns1.equals(ns2));
107.1453 + * </pre></blockquote>
107.1454 + *
107.1455 * @param o the specified object to compare to this
107.1456 * <code>NumericShaper</code>
107.1457 * @return <code>true</code> if <code>o</code> is an instance
107.1458 @@ -869,6 +1223,22 @@
107.1459 if (o != null) {
107.1460 try {
107.1461 NumericShaper rhs = (NumericShaper)o;
107.1462 + if (rangeSet != null) {
107.1463 + if (rhs.rangeSet != null) {
107.1464 + return isContextual() == rhs.isContextual()
107.1465 + && rangeSet.equals(rhs.rangeSet)
107.1466 + && shapingRange == rhs.shapingRange;
107.1467 + }
107.1468 + return isContextual() == rhs.isContextual()
107.1469 + && rangeSet.equals(Range.maskToRangeSet(rhs.mask))
107.1470 + && shapingRange == Range.indexToRange(rhs.key);
107.1471 + } else if (rhs.rangeSet != null) {
107.1472 + Set<Range> rset = Range.maskToRangeSet(mask);
107.1473 + Range srange = Range.indexToRange(key);
107.1474 + return isContextual() == rhs.isContextual()
107.1475 + && rset.equals(rhs.rangeSet)
107.1476 + && srange == rhs.shapingRange;
107.1477 + }
107.1478 return rhs.mask == mask && rhs.key == key;
107.1479 }
107.1480 catch (ClassCastException e) {
107.1481 @@ -885,23 +1255,29 @@
107.1482 public String toString() {
107.1483 StringBuilder buf = new StringBuilder(super.toString());
107.1484
107.1485 - buf.append("[contextual:" + isContextual());
107.1486 + buf.append("[contextual:").append(isContextual());
107.1487
107.1488 + String[] keyNames = null;
107.1489 if (isContextual()) {
107.1490 - buf.append(", context:" + keyNames[key]);
107.1491 + buf.append(", context:");
107.1492 + buf.append(shapingRange == null ? Range.values()[key] : shapingRange);
107.1493 }
107.1494
107.1495 - buf.append(", range(s): ");
107.1496 - boolean first = true;
107.1497 - for (int i = 0; i < NUM_KEYS; ++i) {
107.1498 - if ((mask & (1 << i)) != 0) {
107.1499 - if (first) {
107.1500 - first = false;
107.1501 - } else {
107.1502 - buf.append(", ");
107.1503 + if (rangeSet == null) {
107.1504 + buf.append(", range(s): ");
107.1505 + boolean first = true;
107.1506 + for (int i = 0; i < NUM_KEYS; ++i) {
107.1507 + if ((mask & (1 << i)) != 0) {
107.1508 + if (first) {
107.1509 + first = false;
107.1510 + } else {
107.1511 + buf.append(", ");
107.1512 + }
107.1513 + buf.append(Range.values()[i]);
107.1514 }
107.1515 - buf.append(keyNames[i]);
107.1516 }
107.1517 + } else {
107.1518 + buf.append(", range set: ").append(rangeSet);
107.1519 }
107.1520 buf.append(']');
107.1521
107.1522 @@ -940,7 +1316,6 @@
107.1523 }
107.1524
107.1525 if (value >= 1 << 1) {
107.1526 - value >>= 1;
107.1527 bit += 1;
107.1528 }
107.1529
107.1530 @@ -950,7 +1325,7 @@
107.1531 /**
107.1532 * fast binary search over subrange of array.
107.1533 */
107.1534 - private static int search(char value, char[] array, int start, int length)
107.1535 + private static int search(int value, int[] array, int start, int length)
107.1536 {
107.1537 int power = 1 << getHighBit(length);
107.1538 int extra = length - power;
107.1539 @@ -971,4 +1346,27 @@
107.1540
107.1541 return index;
107.1542 }
107.1543 +
107.1544 + /**
107.1545 + * Converts the {@code NumericShaper.Range} enum-based parameters,
107.1546 + * if any, to the bit mask-based counterparts and writes this
107.1547 + * object to the {@code stream}. Any enum constants that have no
107.1548 + * bit mask-based counterparts are ignored in the conversion.
107.1549 + *
107.1550 + * @param stream the output stream to write to
107.1551 + * @throws IOException if an I/O error occurs while writing to {@code stream}
107.1552 + * @since 1.7
107.1553 + */
107.1554 + private void writeObject(ObjectOutputStream stream) throws IOException {
107.1555 + if (shapingRange != null) {
107.1556 + int index = Range.toRangeIndex(shapingRange);
107.1557 + if (index >= 0) {
107.1558 + key = index;
107.1559 + }
107.1560 + }
107.1561 + if (rangeSet != null) {
107.1562 + mask |= Range.toRangeMask(rangeSet);
107.1563 + }
107.1564 + stream.defaultWriteObject();
107.1565 + }
107.1566 }
108.1 --- a/src/share/classes/java/beans/MetaData.java Mon Nov 23 10:04:47 2009 +0000
108.2 +++ b/src/share/classes/java/beans/MetaData.java Wed Nov 25 11:08:25 2009 -0800
108.3 @@ -42,12 +42,11 @@
108.4 import java.lang.reflect.Constructor;
108.5 import java.lang.reflect.Field;
108.6 import java.lang.reflect.Method;
108.7 +import java.lang.reflect.InvocationTargetException;
108.8
108.9 import java.security.AccessController;
108.10 import java.security.PrivilegedAction;
108.11
108.12 -import java.sql.Timestamp;
108.13 -
108.14 import java.util.*;
108.15
108.16 import javax.swing.Box;
108.17 @@ -290,13 +289,44 @@
108.18 * @author Sergey A. Malenkov
108.19 */
108.20 final class java_sql_Timestamp_PersistenceDelegate extends java_util_Date_PersistenceDelegate {
108.21 + private static final Method getNanosMethod = getNanosMethod();
108.22 +
108.23 + private static Method getNanosMethod() {
108.24 + try {
108.25 + Class<?> c = Class.forName("java.sql.Timestamp", true, null);
108.26 + return c.getMethod("getNanos");
108.27 + } catch (ClassNotFoundException e) {
108.28 + return null;
108.29 + } catch (NoSuchMethodException e) {
108.30 + throw new AssertionError(e);
108.31 + }
108.32 + }
108.33 +
108.34 + /**
108.35 + * Invoke Timstamp getNanos.
108.36 + */
108.37 + private static int getNanos(Object obj) {
108.38 + if (getNanosMethod == null)
108.39 + throw new AssertionError("Should not get here");
108.40 + try {
108.41 + return (Integer)getNanosMethod.invoke(obj);
108.42 + } catch (InvocationTargetException e) {
108.43 + Throwable cause = e.getCause();
108.44 + if (cause instanceof RuntimeException)
108.45 + throw (RuntimeException)cause;
108.46 + if (cause instanceof Error)
108.47 + throw (Error)cause;
108.48 + throw new AssertionError(e);
108.49 + } catch (IllegalAccessException iae) {
108.50 + throw new AssertionError(iae);
108.51 + }
108.52 + }
108.53 +
108.54 protected void initialize(Class<?> type, Object oldInstance, Object newInstance, Encoder out) {
108.55 - Timestamp oldTime = (Timestamp)oldInstance;
108.56 - Timestamp newTime = (Timestamp)newInstance;
108.57 -
108.58 - int nanos = oldTime.getNanos();
108.59 - if (nanos != newTime.getNanos()) {
108.60 - out.writeStatement(new Statement(oldTime, "setNanos", new Object[] {nanos}));
108.61 + // assumes oldInstance and newInstance are Timestamps
108.62 + int nanos = getNanos(oldInstance);
108.63 + if (nanos != getNanos(newInstance)) {
108.64 + out.writeStatement(new Statement(oldInstance, "setNanos", new Object[] {nanos}));
108.65 }
108.66 }
108.67 }
109.1 --- a/src/share/classes/java/io/ObjectStreamClass.java Mon Nov 23 10:04:47 2009 +0000
109.2 +++ b/src/share/classes/java/io/ObjectStreamClass.java Wed Nov 25 11:08:25 2009 -0800
109.3 @@ -99,7 +99,7 @@
109.4 }
109.5
109.6 /** class associated with this descriptor (if any) */
109.7 - private Class cl;
109.8 + private Class<?> cl;
109.9 /** name of class represented by this descriptor */
109.10 private String name;
109.11 /** serialVersionUID of represented class (null if not computed yet) */
109.12 @@ -276,7 +276,7 @@
109.13 * @param all if true, return descriptors for all classes; if false, only
109.14 * return descriptors for serializable classes
109.15 */
109.16 - static ObjectStreamClass lookup(Class cl, boolean all) {
109.17 + static ObjectStreamClass lookup(Class<?> cl, boolean all) {
109.18 if (!(all || Serializable.class.isAssignableFrom(cl))) {
109.19 return null;
109.20 }
109.21 @@ -414,7 +414,7 @@
109.22 /**
109.23 * Creates local class descriptor representing given class.
109.24 */
109.25 - private ObjectStreamClass(final Class cl) {
109.26 + private ObjectStreamClass(final Class<?> cl) {
109.27 this.cl = cl;
109.28 name = cl.getName();
109.29 isProxy = Proxy.isProxyClass(cl);
109.30 @@ -422,7 +422,7 @@
109.31 serializable = Serializable.class.isAssignableFrom(cl);
109.32 externalizable = Externalizable.class.isAssignableFrom(cl);
109.33
109.34 - Class superCl = cl.getSuperclass();
109.35 + Class<?> superCl = cl.getSuperclass();
109.36 superDesc = (superCl != null) ? lookup(superCl, false) : null;
109.37 localDesc = this;
109.38
109.39 @@ -453,10 +453,10 @@
109.40 } else {
109.41 cons = getSerializableConstructor(cl);
109.42 writeObjectMethod = getPrivateMethod(cl, "writeObject",
109.43 - new Class[] { ObjectOutputStream.class },
109.44 + new Class<?>[] { ObjectOutputStream.class },
109.45 Void.TYPE);
109.46 readObjectMethod = getPrivateMethod(cl, "readObject",
109.47 - new Class[] { ObjectInputStream.class },
109.48 + new Class<?>[] { ObjectInputStream.class },
109.49 Void.TYPE);
109.50 readObjectNoDataMethod = getPrivateMethod(
109.51 cl, "readObjectNoData", null, Void.TYPE);
109.52 @@ -507,7 +507,7 @@
109.53 /**
109.54 * Initializes class descriptor representing a proxy class.
109.55 */
109.56 - void initProxy(Class cl,
109.57 + void initProxy(Class<?> cl,
109.58 ClassNotFoundException resolveEx,
109.59 ObjectStreamClass superDesc)
109.60 throws InvalidClassException
109.61 @@ -540,7 +540,7 @@
109.62 * Initializes class descriptor representing a non-proxy class.
109.63 */
109.64 void initNonProxy(ObjectStreamClass model,
109.65 - Class cl,
109.66 + Class<?> cl,
109.67 ClassNotFoundException resolveEx,
109.68 ObjectStreamClass superDesc)
109.69 throws InvalidClassException
109.70 @@ -1131,7 +1131,7 @@
109.71 throws InvalidClassException
109.72 {
109.73 ArrayList<ClassDataSlot> slots = new ArrayList<ClassDataSlot>();
109.74 - Class start = cl, end = cl;
109.75 + Class<?> start = cl, end = cl;
109.76
109.77 // locate closest non-serializable superclass
109.78 while (end != null && Serializable.class.isAssignableFrom(end)) {
109.79 @@ -1142,8 +1142,8 @@
109.80
109.81 // search up inheritance hierarchy for class with matching name
109.82 String searchName = (d.cl != null) ? d.cl.getName() : d.name;
109.83 - Class match = null;
109.84 - for (Class c = start; c != end; c = c.getSuperclass()) {
109.85 + Class<?> match = null;
109.86 + for (Class<?> c = start; c != end; c = c.getSuperclass()) {
109.87 if (searchName.equals(c.getName())) {
109.88 match = c;
109.89 break;
109.90 @@ -1152,7 +1152,7 @@
109.91
109.92 // add "no data" slot for each unmatched class below match
109.93 if (match != null) {
109.94 - for (Class c = start; c != match; c = c.getSuperclass()) {
109.95 + for (Class<?> c = start; c != match; c = c.getSuperclass()) {
109.96 slots.add(new ClassDataSlot(
109.97 ObjectStreamClass.lookup(c, true), false));
109.98 }
109.99 @@ -1164,7 +1164,7 @@
109.100 }
109.101
109.102 // add "no data" slot for any leftover unmatched classes
109.103 - for (Class c = start; c != end; c = c.getSuperclass()) {
109.104 + for (Class<?> c = start; c != end; c = c.getSuperclass()) {
109.105 slots.add(new ClassDataSlot(
109.106 ObjectStreamClass.lookup(c, true), false));
109.107 }
109.108 @@ -1288,7 +1288,7 @@
109.109 * descriptor, returns reference to this class descriptor. Otherwise,
109.110 * returns variant of this class descriptor bound to given class.
109.111 */
109.112 - private ObjectStreamClass getVariantFor(Class cl)
109.113 + private ObjectStreamClass getVariantFor(Class<?> cl)
109.114 throws InvalidClassException
109.115 {
109.116 if (this.cl == cl) {
109.117 @@ -1355,8 +1355,8 @@
109.118 * method (if any).
109.119 */
109.120 private static Method getInheritableMethod(Class<?> cl, String name,
109.121 - Class[] argTypes,
109.122 - Class returnType)
109.123 + Class<?>[] argTypes,
109.124 + Class<?> returnType)
109.125 {
109.126 Method meth = null;
109.127 Class<?> defCl = cl;
109.128 @@ -1410,7 +1410,7 @@
109.129 * Returns true if classes are defined in the same runtime package, false
109.130 * otherwise.
109.131 */
109.132 - private static boolean packageEquals(Class cl1, Class cl2) {
109.133 + private static boolean packageEquals(Class<?> cl1, Class<?> cl2) {
109.134 return (cl1.getClassLoader() == cl2.getClassLoader() &&
109.135 getPackageName(cl1).equals(getPackageName(cl2)));
109.136 }
109.137 @@ -1418,7 +1418,7 @@
109.138 /**
109.139 * Returns package name of given class.
109.140 */
109.141 - private static String getPackageName(Class cl) {
109.142 + private static String getPackageName(Class<?> cl) {
109.143 String s = cl.getName();
109.144 int i = s.lastIndexOf('[');
109.145 if (i >= 0) {
109.146 @@ -1441,7 +1441,7 @@
109.147 /**
109.148 * Returns JVM type signature for given class.
109.149 */
109.150 - static String getClassSignature(Class cl) {
109.151 + private static String getClassSignature(Class<?> cl) {
109.152 StringBuilder sbuf = new StringBuilder();
109.153 while (cl.isArray()) {
109.154 sbuf.append('[');
109.155 @@ -1478,8 +1478,8 @@
109.156 /**
109.157 * Returns JVM type signature for given list of parameters and return type.
109.158 */
109.159 - private static String getMethodSignature(Class[] paramTypes,
109.160 - Class retType)
109.161 + private static String getMethodSignature(Class<?>[] paramTypes,
109.162 + Class<?> retType)
109.163 {
109.164 StringBuilder sbuf = new StringBuilder();
109.165 sbuf.append('(');
109.166 @@ -1515,7 +1515,7 @@
109.167 * Field objects. Throws InvalidClassException if the (explicitly
109.168 * declared) serializable fields are invalid.
109.169 */
109.170 - private static ObjectStreamField[] getSerialFields(Class cl)
109.171 + private static ObjectStreamField[] getSerialFields(Class<?> cl)
109.172 throws InvalidClassException
109.173 {
109.174 ObjectStreamField[] fields;
109.175 @@ -1545,7 +1545,7 @@
109.176 * InvalidClassException if the declared serializable fields are
109.177 * invalid--e.g., if multiple fields share the same name.
109.178 */
109.179 - private static ObjectStreamField[] getDeclaredSerialFields(Class cl)
109.180 + private static ObjectStreamField[] getDeclaredSerialFields(Class<?> cl)
109.181 throws InvalidClassException
109.182 {
109.183 ObjectStreamField[] serialPersistentFields = null;
109.184 @@ -1602,7 +1602,7 @@
109.185 * contains a Field object for the field it represents. If no default
109.186 * serializable fields exist, NO_FIELDS is returned.
109.187 */
109.188 - private static ObjectStreamField[] getDefaultSerialFields(Class cl) {
109.189 + private static ObjectStreamField[] getDefaultSerialFields(Class<?> cl) {
109.190 Field[] clFields = cl.getDeclaredFields();
109.191 ArrayList<ObjectStreamField> list = new ArrayList<ObjectStreamField>();
109.192 int mask = Modifier.STATIC | Modifier.TRANSIENT;
109.193 @@ -1621,7 +1621,7 @@
109.194 * Returns explicit serial version UID value declared by given class, or
109.195 * null if none.
109.196 */
109.197 - private static Long getDeclaredSUID(Class cl) {
109.198 + private static Long getDeclaredSUID(Class<?> cl) {
109.199 try {
109.200 Field f = cl.getDeclaredField("serialVersionUID");
109.201 int mask = Modifier.STATIC | Modifier.FINAL;
109.202 @@ -1637,7 +1637,7 @@
109.203 /**
109.204 * Computes the default serial version UID value for the given class.
109.205 */
109.206 - private static long computeDefaultSUID(Class cl) {
109.207 + private static long computeDefaultSUID(Class<?> cl) {
109.208 if (!Serializable.class.isAssignableFrom(cl) || Proxy.isProxyClass(cl))
109.209 {
109.210 return 0L;
109.211 @@ -1671,7 +1671,7 @@
109.212 * Class.getInterfaces() was modified to return Cloneable and
109.213 * Serializable for array classes.
109.214 */
109.215 - Class[] interfaces = cl.getInterfaces();
109.216 + Class<?>[] interfaces = cl.getInterfaces();
109.217 String[] ifaceNames = new String[interfaces.length];
109.218 for (int i = 0; i < interfaces.length; i++) {
109.219 ifaceNames[i] = interfaces[i].getName();
109.220 @@ -1784,7 +1784,7 @@
109.221 * Returns true if the given class defines a static initializer method,
109.222 * false otherwise.
109.223 */
109.224 - private native static boolean hasStaticInitializer(Class cl);
109.225 + private native static boolean hasStaticInitializer(Class<?> cl);
109.226
109.227 /**
109.228 * Class for computing and caching field/constructor/method signatures
109.229 @@ -1837,7 +1837,7 @@
109.230 /** field type codes */
109.231 private final char[] typeCodes;
109.232 /** field types */
109.233 - private final Class[] types;
109.234 + private final Class<?>[] types;
109.235
109.236 /**
109.237 * Constructs FieldReflector capable of setting/getting values from the
109.238 @@ -2071,7 +2071,7 @@
109.239 throws InvalidClassException
109.240 {
109.241 // class irrelevant if no fields
109.242 - Class cl = (localDesc != null && fields.length > 0) ?
109.243 + Class<?> cl = (localDesc != null && fields.length > 0) ?
109.244 localDesc.cl : null;
109.245 processQueue(Caches.reflectorsQueue, Caches.reflectors);
109.246 FieldReflectorKey key = new FieldReflectorKey(cl, fields,
109.247 @@ -2136,7 +2136,7 @@
109.248 private final int hash;
109.249 private final boolean nullClass;
109.250
109.251 - FieldReflectorKey(Class cl, ObjectStreamField[] fields,
109.252 + FieldReflectorKey(Class<?> cl, ObjectStreamField[] fields,
109.253 ReferenceQueue<Class<?>> queue)
109.254 {
109.255 super(cl, queue);
110.1 --- a/src/share/classes/java/io/ObjectStreamField.java Mon Nov 23 10:04:47 2009 +0000
110.2 +++ b/src/share/classes/java/io/ObjectStreamField.java Wed Nov 25 11:08:25 2009 -0800
110.3 @@ -45,7 +45,7 @@
110.4 /** canonical JVM signature of field type */
110.5 private final String signature;
110.6 /** field type (Object.class if unknown non-primitive type) */
110.7 - private final Class type;
110.8 + private final Class<?> type;
110.9 /** whether or not to (de)serialize field values as unshared */
110.10 private final boolean unshared;
110.11 /** corresponding reflective field object, if any */
110.12 @@ -88,7 +88,7 @@
110.13 this.name = name;
110.14 this.type = type;
110.15 this.unshared = unshared;
110.16 - signature = ObjectStreamClass.getClassSignature(type).intern();
110.17 + signature = getClassSignature(type).intern();
110.18 field = null;
110.19 }
110.20
110.21 @@ -132,9 +132,9 @@
110.22 this.field = field;
110.23 this.unshared = unshared;
110.24 name = field.getName();
110.25 - Class ftype = field.getType();
110.26 + Class<?> ftype = field.getType();
110.27 type = (showType || ftype.isPrimitive()) ? ftype : Object.class;
110.28 - signature = ObjectStreamClass.getClassSignature(ftype).intern();
110.29 + signature = getClassSignature(ftype).intern();
110.30 }
110.31
110.32 /**
110.33 @@ -274,4 +274,41 @@
110.34 String getSignature() {
110.35 return signature;
110.36 }
110.37 +
110.38 + /**
110.39 + * Returns JVM type signature for given class.
110.40 + */
110.41 + private static String getClassSignature(Class<?> cl) {
110.42 + StringBuilder sbuf = new StringBuilder();
110.43 + while (cl.isArray()) {
110.44 + sbuf.append('[');
110.45 + cl = cl.getComponentType();
110.46 + }
110.47 + if (cl.isPrimitive()) {
110.48 + if (cl == Integer.TYPE) {
110.49 + sbuf.append('I');
110.50 + } else if (cl == Byte.TYPE) {
110.51 + sbuf.append('B');
110.52 + } else if (cl == Long.TYPE) {
110.53 + sbuf.append('J');
110.54 + } else if (cl == Float.TYPE) {
110.55 + sbuf.append('F');
110.56 + } else if (cl == Double.TYPE) {
110.57 + sbuf.append('D');
110.58 + } else if (cl == Short.TYPE) {
110.59 + sbuf.append('S');
110.60 + } else if (cl == Character.TYPE) {
110.61 + sbuf.append('C');
110.62 + } else if (cl == Boolean.TYPE) {
110.63 + sbuf.append('Z');
110.64 + } else if (cl == Void.TYPE) {
110.65 + sbuf.append('V');
110.66 + } else {
110.67 + throw new InternalError();
110.68 + }
110.69 + } else {
110.70 + sbuf.append('L' + cl.getName().replace('.', '/') + ';');
110.71 + }
110.72 + return sbuf.toString();
110.73 + }
110.74 }
111.1 --- a/src/share/classes/java/lang/ClassLoader.java Mon Nov 23 10:04:47 2009 +0000
111.2 +++ b/src/share/classes/java/lang/ClassLoader.java Wed Nov 25 11:08:25 2009 -0800
111.3 @@ -186,11 +186,6 @@
111.4 parallelLoaders.add(ClassLoader.class);
111.5 }
111.6
111.7 - // If initialization succeed this is set to true and security checks will
111.8 - // succeed. Otherwise the object is not initialized and the object is
111.9 - // useless.
111.10 - private final boolean initialized;
111.11 -
111.12 // The parent class loader for delegation
111.13 // Note: VM hardcoded the offset of this field, thus all new fields
111.14 // must be added *after* it.
111.15 @@ -232,6 +227,31 @@
111.16 private final HashMap<String, Package> packages =
111.17 new HashMap<String, Package>();
111.18
111.19 + private static Void checkCreateClassLoader() {
111.20 + SecurityManager security = System.getSecurityManager();
111.21 + if (security != null) {
111.22 + security.checkCreateClassLoader();
111.23 + }
111.24 + return null;
111.25 + }
111.26 +
111.27 + private ClassLoader(Void unused, ClassLoader parent) {
111.28 + this.parent = parent;
111.29 + if (parallelLoaders.contains(this.getClass())) {
111.30 + parallelLockMap = new ConcurrentHashMap<String, Object>();
111.31 + package2certs = new ConcurrentHashMap<String, Certificate[]>();
111.32 + domains =
111.33 + Collections.synchronizedSet(new HashSet<ProtectionDomain>());
111.34 + assertionLock = new Object();
111.35 + } else {
111.36 + // no finer-grained lock; lock on the classloader instance
111.37 + parallelLockMap = null;
111.38 + package2certs = new Hashtable<String, Certificate[]>();
111.39 + domains = new HashSet<ProtectionDomain>();
111.40 + assertionLock = this;
111.41 + }
111.42 + }
111.43 +
111.44 /**
111.45 * Creates a new class loader using the specified parent class loader for
111.46 * delegation.
111.47 @@ -252,25 +272,7 @@
111.48 * @since 1.2
111.49 */
111.50 protected ClassLoader(ClassLoader parent) {
111.51 - SecurityManager security = System.getSecurityManager();
111.52 - if (security != null) {
111.53 - security.checkCreateClassLoader();
111.54 - }
111.55 - this.parent = parent;
111.56 - if (parallelLoaders.contains(this.getClass())) {
111.57 - parallelLockMap = new ConcurrentHashMap<String, Object>();
111.58 - package2certs = new ConcurrentHashMap<String, Certificate[]>();
111.59 - domains =
111.60 - Collections.synchronizedSet(new HashSet<ProtectionDomain>());
111.61 - assertionLock = new Object();
111.62 - } else {
111.63 - // no finer-grained lock; lock on the classloader instance
111.64 - parallelLockMap = null;
111.65 - package2certs = new Hashtable<String, Certificate[]>();
111.66 - domains = new HashSet<ProtectionDomain>();
111.67 - assertionLock = this;
111.68 - }
111.69 - initialized = true;
111.70 + this(checkCreateClassLoader(), parent);
111.71 }
111.72
111.73 /**
111.74 @@ -289,25 +291,7 @@
111.75 * of a new class loader.
111.76 */
111.77 protected ClassLoader() {
111.78 - SecurityManager security = System.getSecurityManager();
111.79 - if (security != null) {
111.80 - security.checkCreateClassLoader();
111.81 - }
111.82 - this.parent = getSystemClassLoader();
111.83 - if (parallelLoaders.contains(this.getClass())) {
111.84 - parallelLockMap = new ConcurrentHashMap<String, Object>();
111.85 - package2certs = new ConcurrentHashMap<String, Certificate[]>();
111.86 - domains =
111.87 - Collections.synchronizedSet(new HashSet<ProtectionDomain>());
111.88 - assertionLock = new Object();
111.89 - } else {
111.90 - // no finer-grained lock; lock on the classloader instance
111.91 - parallelLockMap = null;
111.92 - package2certs = new Hashtable<String, Certificate[]>();
111.93 - domains = new HashSet<ProtectionDomain>();
111.94 - assertionLock = this;
111.95 - }
111.96 - initialized = true;
111.97 + this(checkCreateClassLoader(), getSystemClassLoader());
111.98 }
111.99
111.100 // -- Class --
111.101 @@ -754,7 +738,6 @@
111.102 ProtectionDomain protectionDomain)
111.103 throws ClassFormatError
111.104 {
111.105 - check();
111.106 protectionDomain = preDefineClass(name, protectionDomain);
111.107
111.108 Class c = null;
111.109 @@ -838,8 +821,6 @@
111.110 ProtectionDomain protectionDomain)
111.111 throws ClassFormatError
111.112 {
111.113 - check();
111.114 -
111.115 int len = b.remaining();
111.116
111.117 // Use byte[] if not a direct ByteBufer:
111.118 @@ -984,7 +965,6 @@
111.119 * @see #defineClass(String, byte[], int, int)
111.120 */
111.121 protected final void resolveClass(Class<?> c) {
111.122 - check();
111.123 resolveClass0(c);
111.124 }
111.125
111.126 @@ -1015,7 +995,6 @@
111.127 protected final Class<?> findSystemClass(String name)
111.128 throws ClassNotFoundException
111.129 {
111.130 - check();
111.131 ClassLoader system = getSystemClassLoader();
111.132 if (system == null) {
111.133 if (!checkName(name))
111.134 @@ -1035,7 +1014,6 @@
111.135 */
111.136 private Class findBootstrapClassOrNull(String name)
111.137 {
111.138 - check();
111.139 if (!checkName(name)) return null;
111.140
111.141 return findBootstrapClass(name);
111.142 @@ -1044,13 +1022,6 @@
111.143 // return null if not found
111.144 private native Class findBootstrapClass(String name);
111.145
111.146 - // Check to make sure the class loader has been initialized.
111.147 - private void check() {
111.148 - if (!initialized) {
111.149 - throw new SecurityException("ClassLoader object not initialized");
111.150 - }
111.151 - }
111.152 -
111.153 /**
111.154 * Returns the class with the given <a href="#name">binary name</a> if this
111.155 * loader has been recorded by the Java virtual machine as an initiating
111.156 @@ -1066,7 +1037,6 @@
111.157 * @since 1.1
111.158 */
111.159 protected final Class<?> findLoadedClass(String name) {
111.160 - check();
111.161 if (!checkName(name))
111.162 return null;
111.163 return findLoadedClass0(name);
111.164 @@ -1087,7 +1057,6 @@
111.165 * @since 1.1
111.166 */
111.167 protected final void setSigners(Class<?> c, Object[] signers) {
111.168 - check();
111.169 c.setSigners(signers);
111.170 }
111.171
111.172 @@ -2205,3 +2174,4 @@
111.173 return sys;
111.174 }
111.175 }
111.176 +
112.1 --- a/src/share/classes/java/lang/management/PlatformComponent.java Mon Nov 23 10:04:47 2009 +0000
112.2 +++ b/src/share/classes/java/lang/management/PlatformComponent.java Wed Nov 25 11:08:25 2009 -0800
112.3 @@ -30,8 +30,7 @@
112.4 import java.util.List;
112.5 import java.util.HashSet;
112.6 import java.util.Set;
112.7 -import java.util.logging.LoggingMXBean;
112.8 -import java.util.logging.LogManager;
112.9 +import java.util.logging.PlatformLoggingMXBean;
112.10 import java.nio.BufferPoolMXBean;
112.11 import javax.management.MBeanServerConnection;
112.12 import javax.management.ObjectName;
112.13 @@ -40,6 +39,7 @@
112.14 import com.sun.management.UnixOperatingSystemMXBean;
112.15
112.16 import sun.management.ManagementFactoryHelper;
112.17 +import sun.management.Util;
112.18
112.19 /**
112.20 * This enum class defines the list of platform components
112.21 @@ -180,15 +180,14 @@
112.22 * Logging facility.
112.23 */
112.24 LOGGING(
112.25 - "java.util.logging.LoggingMXBean",
112.26 + "java.util.logging.PlatformLoggingMXBean",
112.27 "java.util.logging", "Logging", defaultKeyProperties(),
112.28 - new MXBeanFetcher<LoggingMXBean>() {
112.29 - public List<LoggingMXBean> getMXBeans() {
112.30 - return Collections.singletonList(LogManager.getLoggingMXBean());
112.31 + new MXBeanFetcher<PlatformLoggingMXBean>() {
112.32 + public List<PlatformLoggingMXBean> getMXBeans() {
112.33 + return ManagementFactoryHelper.getLoggingMXBean();
112.34 }
112.35 }),
112.36
112.37 -
112.38 /**
112.39 * Buffer pools.
112.40 */
112.41 @@ -384,7 +383,7 @@
112.42 // if there are more than 1 key properties (i.e. other than "type")
112.43 domainAndType += ",*";
112.44 }
112.45 - ObjectName on = ObjectName.valueOf(domainAndType);
112.46 + ObjectName on = Util.newObjectName(domainAndType);
112.47 Set<ObjectName> set = mbs.queryNames(on, null);
112.48 for (PlatformComponent pc : subComponents) {
112.49 set.addAll(pc.getObjectNames(mbs));
113.1 --- a/src/share/classes/java/math/BigInteger.java Mon Nov 23 10:04:47 2009 +0000
113.2 +++ b/src/share/classes/java/math/BigInteger.java Wed Nov 25 11:08:25 2009 -0800
113.3 @@ -288,11 +288,11 @@
113.4 */
113.5 public BigInteger(String val, int radix) {
113.6 int cursor = 0, numDigits;
113.7 - int len = val.length();
113.8 + final int len = val.length();
113.9
113.10 if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)
113.11 throw new NumberFormatException("Radix out of range");
113.12 - if (val.length() == 0)
113.13 + if (len == 0)
113.14 throw new NumberFormatException("Zero length BigInteger");
113.15
113.16 // Check for at most one leading sign
113.17 @@ -303,7 +303,7 @@
113.18 // No leading sign character or at most one leading sign character
113.19 if (index1 == 0 || index2 == 0) {
113.20 cursor = 1;
113.21 - if (val.length() == 1)
113.22 + if (len == 1)
113.23 throw new NumberFormatException("Zero length BigInteger");
113.24 }
113.25 if (index1 == 0)
113.26 @@ -342,7 +342,7 @@
113.27 // Process remaining digit groups
113.28 int superRadix = intRadix[radix];
113.29 int groupVal = 0;
113.30 - while (cursor < val.length()) {
113.31 + while (cursor < len) {
113.32 group = val.substring(cursor, cursor += digitsPerInt[radix]);
113.33 groupVal = Integer.parseInt(group, radix);
113.34 if (groupVal < 0)
113.35 @@ -478,7 +478,7 @@
113.36
113.37 /**
113.38 * Constructs a randomly generated BigInteger, uniformly distributed over
113.39 - * the range {@code 0} to (2<sup>{@code numBits}</sup> - 1), inclusive.
113.40 + * the range 0 to (2<sup>{@code numBits}</sup> - 1), inclusive.
113.41 * The uniformity of the distribution assumes that a fair source of random
113.42 * bits is provided in {@code rnd}. Note that this constructor always
113.43 * constructs a non-negative BigInteger.
113.44 @@ -1332,7 +1332,7 @@
113.45 *
113.46 * @param val value by which this BigInteger is to be divided.
113.47 * @return {@code this / val}
113.48 - * @throws ArithmeticException {@code val==0}
113.49 + * @throws ArithmeticException if {@code val} is zero.
113.50 */
113.51 public BigInteger divide(BigInteger val) {
113.52 MutableBigInteger q = new MutableBigInteger(),
113.53 @@ -1352,7 +1352,7 @@
113.54 * @return an array of two BigIntegers: the quotient {@code (this / val)}
113.55 * is the initial element, and the remainder {@code (this % val)}
113.56 * is the final element.
113.57 - * @throws ArithmeticException {@code val==0}
113.58 + * @throws ArithmeticException if {@code val} is zero.
113.59 */
113.60 public BigInteger[] divideAndRemainder(BigInteger val) {
113.61 BigInteger[] result = new BigInteger[2];
113.62 @@ -1371,7 +1371,7 @@
113.63 * @param val value by which this BigInteger is to be divided, and the
113.64 * remainder computed.
113.65 * @return {@code this % val}
113.66 - * @throws ArithmeticException {@code val==0}
113.67 + * @throws ArithmeticException if {@code val} is zero.
113.68 */
113.69 public BigInteger remainder(BigInteger val) {
113.70 MutableBigInteger q = new MutableBigInteger(),
113.71 @@ -1547,7 +1547,7 @@
113.72 *
113.73 * @param m the modulus.
113.74 * @return {@code this mod m}
113.75 - * @throws ArithmeticException {@code m <= 0}
113.76 + * @throws ArithmeticException {@code m} ≤ 0
113.77 * @see #remainder
113.78 */
113.79 public BigInteger mod(BigInteger m) {
113.80 @@ -1566,7 +1566,9 @@
113.81 * @param exponent the exponent.
113.82 * @param m the modulus.
113.83 * @return <tt>this<sup>exponent</sup> mod m</tt>
113.84 - * @throws ArithmeticException {@code m <= 0}
113.85 + * @throws ArithmeticException {@code m} ≤ 0 or the exponent is
113.86 + * negative and this BigInteger is not <i>relatively
113.87 + * prime</i> to {@code m}.
113.88 * @see #modInverse
113.89 */
113.90 public BigInteger modPow(BigInteger exponent, BigInteger m) {
113.91 @@ -2015,7 +2017,7 @@
113.92 *
113.93 * @param m the modulus.
113.94 * @return {@code this}<sup>-1</sup> {@code mod m}.
113.95 - * @throws ArithmeticException {@code m <= 0}, or this BigInteger
113.96 + * @throws ArithmeticException {@code m} ≤ 0, or this BigInteger
113.97 * has no multiplicative inverse mod m (that is, this BigInteger
113.98 * is not <i>relatively prime</i> to m).
113.99 */
113.100 @@ -2051,6 +2053,8 @@
113.101 *
113.102 * @param n shift distance, in bits.
113.103 * @return {@code this << n}
113.104 + * @throws ArithmeticException if the shift distance is {@code
113.105 + * Integer.MIN_VALUE}.
113.106 * @see #shiftRight
113.107 */
113.108 public BigInteger shiftLeft(int n) {
113.109 @@ -2058,8 +2062,13 @@
113.110 return ZERO;
113.111 if (n==0)
113.112 return this;
113.113 - if (n<0)
113.114 - return shiftRight(-n);
113.115 + if (n<0) {
113.116 + if (n == Integer.MIN_VALUE) {
113.117 + throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported.");
113.118 + } else {
113.119 + return shiftRight(-n);
113.120 + }
113.121 + }
113.122
113.123 int nInts = n >>> 5;
113.124 int nBits = n & 0x1f;
113.125 @@ -2097,13 +2106,20 @@
113.126 *
113.127 * @param n shift distance, in bits.
113.128 * @return {@code this >> n}
113.129 + * @throws ArithmeticException if the shift distance is {@code
113.130 + * Integer.MIN_VALUE}.
113.131 * @see #shiftLeft
113.132 */
113.133 public BigInteger shiftRight(int n) {
113.134 if (n==0)
113.135 return this;
113.136 - if (n<0)
113.137 - return shiftLeft(-n);
113.138 + if (n<0) {
113.139 + if (n == Integer.MIN_VALUE) {
113.140 + throw new ArithmeticException("Shift distance of Integer.MIN_VALUE not supported.");
113.141 + } else {
113.142 + return shiftLeft(-n);
113.143 + }
113.144 + }
113.145
113.146 int nInts = n >>> 5;
113.147 int nBits = n & 0x1f;
113.148 @@ -2435,7 +2451,7 @@
113.149 /**
113.150 * Returns {@code true} if this BigInteger is probably prime,
113.151 * {@code false} if it's definitely composite. If
113.152 - * {@code certainty} is {@code <= 0}, {@code true} is
113.153 + * {@code certainty} is ≤ 0, {@code true} is
113.154 * returned.
113.155 *
113.156 * @param certainty a measure of the uncertainty that the caller is
114.1 --- a/src/share/classes/java/net/CookieHandler.java Mon Nov 23 10:04:47 2009 +0000
114.2 +++ b/src/share/classes/java/net/CookieHandler.java Wed Nov 25 11:08:25 2009 -0800
114.3 @@ -101,11 +101,21 @@
114.4 * Gets all the applicable cookies from a cookie cache for the
114.5 * specified uri in the request header.
114.6 *
114.7 - * HTTP protocol implementers should make sure that this method is
114.8 + * <P>The {@code URI} passed as an argument specifies the intended use for
114.9 + * the cookies. In particular the scheme should reflect whether the cookies
114.10 + * will be sent over http, https or used in another context like javascript.
114.11 + * The host part should reflect either the destination of the cookies or
114.12 + * their origin in the case of javascript.</P>
114.13 + * <P>It is up to the implementation to take into account the {@code URI} and
114.14 + * the cookies attributes and security settings to determine which ones
114.15 + * should be returned.</P>
114.16 + *
114.17 + * <P>HTTP protocol implementers should make sure that this method is
114.18 * called after all request headers related to choosing cookies
114.19 - * are added, and before the request is sent.
114.20 + * are added, and before the request is sent.</P>
114.21 *
114.22 - * @param uri a <code>URI</code> to send cookies to in a request
114.23 + * @param uri a <code>URI</code> representing the intended use for the
114.24 + * cookies
114.25 * @param requestHeaders - a Map from request header
114.26 * field names to lists of field values representing
114.27 * the current request headers
115.1 --- a/src/share/classes/java/net/CookieManager.java Mon Nov 23 10:04:47 2009 +0000
115.2 +++ b/src/share/classes/java/net/CookieManager.java Wed Nov 25 11:08:25 2009 -0800
115.3 @@ -218,6 +218,13 @@
115.4 // 'secure' cookies over unsecure links)
115.5 if (pathMatches(path, cookie.getPath()) &&
115.6 (secureLink || !cookie.getSecure())) {
115.7 + // Enforce httponly attribute
115.8 + if (cookie.isHttpOnly()) {
115.9 + String s = uri.getScheme();
115.10 + if (!"http".equalsIgnoreCase(s) && !"https".equalsIgnoreCase(s)) {
115.11 + continue;
115.12 + }
115.13 + }
115.14 // Let's check the authorize port list if it exists
115.15 String ports = cookie.getPortlist();
115.16 if (ports != null && !ports.isEmpty()) {
116.1 --- a/src/share/classes/java/security/MessageDigest.java Mon Nov 23 10:04:47 2009 +0000
116.2 +++ b/src/share/classes/java/security/MessageDigest.java Wed Nov 25 11:08:25 2009 -0800
116.3 @@ -1,5 +1,5 @@
116.4 /*
116.5 - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
116.6 + * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
116.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
116.8 *
116.9 * This code is free software; you can redistribute it and/or modify it
116.10 @@ -414,16 +414,17 @@
116.11 *
116.12 * @return true if the digests are equal, false otherwise.
116.13 */
116.14 - public static boolean isEqual(byte digesta[], byte digestb[]) {
116.15 - if (digesta.length != digestb.length)
116.16 + public static boolean isEqual(byte[] digesta, byte[] digestb) {
116.17 + if (digesta.length != digestb.length) {
116.18 return false;
116.19 + }
116.20
116.21 + int result = 0;
116.22 + // time-constant comparison
116.23 for (int i = 0; i < digesta.length; i++) {
116.24 - if (digesta[i] != digestb[i]) {
116.25 - return false;
116.26 - }
116.27 + result |= digesta[i] ^ digestb[i];
116.28 }
116.29 - return true;
116.30 + return result == 0;
116.31 }
116.32
116.33 /**
117.1 --- a/src/share/classes/java/util/Arrays.java Mon Nov 23 10:04:47 2009 +0000
117.2 +++ b/src/share/classes/java/util/Arrays.java Wed Nov 25 11:08:25 2009 -0800
117.3 @@ -1,5 +1,5 @@
117.4 /*
117.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
117.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
117.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
117.8 *
117.9 * This code is free software; you can redistribute it and/or modify it
117.10 @@ -29,1047 +29,353 @@
117.11
117.12 /**
117.13 * This class contains various methods for manipulating arrays (such as
117.14 - * sorting and searching). This class also contains a static factory
117.15 + * sorting and searching). This class also contains a static factory
117.16 * that allows arrays to be viewed as lists.
117.17 *
117.18 - * <p>The methods in this class all throw a <tt>NullPointerException</tt> if
117.19 - * the specified array reference is null, except where noted.
117.20 + * <p>The methods in this class all throw a {@code NullPointerException},
117.21 + * if the specified array reference is null, except where noted.
117.22 *
117.23 * <p>The documentation for the methods contained in this class includes
117.24 - * briefs description of the <i>implementations</i>. Such descriptions should
117.25 + * briefs description of the <i>implementations</i>. Such descriptions should
117.26 * be regarded as <i>implementation notes</i>, rather than parts of the
117.27 - * <i>specification</i>. Implementors should feel free to substitute other
117.28 - * algorithms, so long as the specification itself is adhered to. (For
117.29 - * example, the algorithm used by <tt>sort(Object[])</tt> does not have to be
117.30 - * a mergesort, but it does have to be <i>stable</i>.)
117.31 + * <i>specification</i>. Implementors should feel free to substitute other
117.32 + * algorithms, so long as the specification itself is adhered to. (For
117.33 + * example, the algorithm used by {@code sort(Object[])} does not have to be
117.34 + * a MergeSort, but it does have to be <i>stable</i>.)
117.35 *
117.36 * <p>This class is a member of the
117.37 * <a href="{@docRoot}/../technotes/guides/collections/index.html">
117.38 * Java Collections Framework</a>.
117.39 *
117.40 - * @author Josh Bloch
117.41 - * @author Neal Gafter
117.42 - * @author John Rose
117.43 - * @since 1.2
117.44 + * @author Josh Bloch
117.45 + * @author Neal Gafter
117.46 + * @author John Rose
117.47 + * @since 1.2
117.48 */
117.49 +public class Arrays {
117.50
117.51 -public class Arrays {
117.52 // Suppresses default constructor, ensuring non-instantiability.
117.53 - private Arrays() {
117.54 + private Arrays() {}
117.55 +
117.56 + /*
117.57 + * Sorting of primitive type arrays.
117.58 + */
117.59 +
117.60 + /**
117.61 + * Sorts the specified array into ascending numerical order.
117.62 + *
117.63 + * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
117.64 + * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
117.65 + * offers O(n log(n)) performance on many data sets that cause other
117.66 + * quicksorts to degrade to quadratic performance, and is typically
117.67 + * faster than traditional (one-pivot) Quicksort implementations.
117.68 + *
117.69 + * @param a the array to be sorted
117.70 + */
117.71 + public static void sort(int[] a) {
117.72 + DualPivotQuicksort.sort(a);
117.73 }
117.74
117.75 - // Sorting
117.76 + /**
117.77 + * Sorts the specified range of the array into ascending order. The range
117.78 + * to be sorted extends from the index {@code fromIndex}, inclusive, to
117.79 + * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
117.80 + * the range to be sorted is empty.
117.81 + *
117.82 + * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
117.83 + * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
117.84 + * offers O(n log(n)) performance on many data sets that cause other
117.85 + * quicksorts to degrade to quadratic performance, and is typically
117.86 + * faster than traditional (one-pivot) Quicksort implementations.
117.87 + *
117.88 + * @param a the array to be sorted
117.89 + * @param fromIndex the index of the first element, inclusive, to be sorted
117.90 + * @param toIndex the index of the last element, exclusive, to be sorted
117.91 + *
117.92 + * @throws IllegalArgumentException if {@code fromIndex > toIndex}
117.93 + * @throws ArrayIndexOutOfBoundsException
117.94 + * if {@code fromIndex < 0} or {@code toIndex > a.length}
117.95 + */
117.96 + public static void sort(int[] a, int fromIndex, int toIndex) {
117.97 + DualPivotQuicksort.sort(a, fromIndex, toIndex);
117.98 + }
117.99
117.100 /**
117.101 - * Sorts the specified array of longs into ascending numerical order.
117.102 - * The sorting algorithm is a tuned quicksort, adapted from Jon
117.103 - * L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function",
117.104 - * Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
117.105 - * 1993). This algorithm offers n*log(n) performance on many data sets
117.106 - * that cause other quicksorts to degrade to quadratic performance.
117.107 + * Sorts the specified array into ascending numerical order.
117.108 + *
117.109 + * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
117.110 + * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
117.111 + * offers O(n log(n)) performance on many data sets that cause other
117.112 + * quicksorts to degrade to quadratic performance, and is typically
117.113 + * faster than traditional (one-pivot) Quicksort implementations.
117.114 *
117.115 * @param a the array to be sorted
117.116 */
117.117 public static void sort(long[] a) {
117.118 - sort1(a, 0, a.length);
117.119 + DualPivotQuicksort.sort(a);
117.120 }
117.121
117.122 /**
117.123 - * Sorts the specified range of the specified array of longs into
117.124 - * ascending numerical order. The range to be sorted extends from index
117.125 - * <tt>fromIndex</tt>, inclusive, to index <tt>toIndex</tt>, exclusive.
117.126 - * (If <tt>fromIndex==toIndex</tt>, the range to be sorted is empty.)
117.127 + * Sorts the specified range of the array into ascending order. The range
117.128 + * to be sorted extends from the index {@code fromIndex}, inclusive, to
117.129 + * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
117.130 + * the range to be sorted is empty.
117.131 *
117.132 - * <p>The sorting algorithm is a tuned quicksort, adapted from Jon
117.133 - * L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function",
117.134 - * Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
117.135 - * 1993). This algorithm offers n*log(n) performance on many data sets
117.136 - * that cause other quicksorts to degrade to quadratic performance.
117.137 + * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
117.138 + * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
117.139 + * offers O(n log(n)) performance on many data sets that cause other
117.140 + * quicksorts to degrade to quadratic performance, and is typically
117.141 + * faster than traditional (one-pivot) Quicksort implementations.
117.142 *
117.143 * @param a the array to be sorted
117.144 - * @param fromIndex the index of the first element (inclusive) to be
117.145 - * sorted
117.146 - * @param toIndex the index of the last element (exclusive) to be sorted
117.147 - * @throws IllegalArgumentException if <tt>fromIndex > toIndex</tt>
117.148 - * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex < 0</tt> or
117.149 - * <tt>toIndex > a.length</tt>
117.150 + * @param fromIndex the index of the first element, inclusive, to be sorted
117.151 + * @param toIndex the index of the last element, exclusive, to be sorted
117.152 + *
117.153 + * @throws IllegalArgumentException if {@code fromIndex > toIndex}
117.154 + * @throws ArrayIndexOutOfBoundsException
117.155 + * if {@code fromIndex < 0} or {@code toIndex > a.length}
117.156 */
117.157 public static void sort(long[] a, int fromIndex, int toIndex) {
117.158 - rangeCheck(a.length, fromIndex, toIndex);
117.159 - sort1(a, fromIndex, toIndex-fromIndex);
117.160 + DualPivotQuicksort.sort(a, fromIndex, toIndex);
117.161 }
117.162
117.163 /**
117.164 - * Sorts the specified array of ints into ascending numerical order.
117.165 - * The sorting algorithm is a tuned quicksort, adapted from Jon
117.166 - * L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function",
117.167 - * Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
117.168 - * 1993). This algorithm offers n*log(n) performance on many data sets
117.169 - * that cause other quicksorts to degrade to quadratic performance.
117.170 + * Sorts the specified array into ascending numerical order.
117.171 *
117.172 - * @param a the array to be sorted
117.173 - */
117.174 - public static void sort(int[] a) {
117.175 - sort1(a, 0, a.length);
117.176 - }
117.177 -
117.178 - /**
117.179 - * Sorts the specified range of the specified array of ints into
117.180 - * ascending numerical order. The range to be sorted extends from index
117.181 - * <tt>fromIndex</tt>, inclusive, to index <tt>toIndex</tt>, exclusive.
117.182 - * (If <tt>fromIndex==toIndex</tt>, the range to be sorted is empty.)<p>
117.183 - *
117.184 - * The sorting algorithm is a tuned quicksort, adapted from Jon
117.185 - * L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function",
117.186 - * Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
117.187 - * 1993). This algorithm offers n*log(n) performance on many data sets
117.188 - * that cause other quicksorts to degrade to quadratic performance.
117.189 - *
117.190 - * @param a the array to be sorted
117.191 - * @param fromIndex the index of the first element (inclusive) to be
117.192 - * sorted
117.193 - * @param toIndex the index of the last element (exclusive) to be sorted
117.194 - * @throws IllegalArgumentException if <tt>fromIndex > toIndex</tt>
117.195 - * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex < 0</tt> or
117.196 - * <tt>toIndex > a.length</tt>
117.197 - */
117.198 - public static void sort(int[] a, int fromIndex, int toIndex) {
117.199 - rangeCheck(a.length, fromIndex, toIndex);
117.200 - sort1(a, fromIndex, toIndex-fromIndex);
117.201 - }
117.202 -
117.203 - /**
117.204 - * Sorts the specified array of shorts into ascending numerical order.
117.205 - * The sorting algorithm is a tuned quicksort, adapted from Jon
117.206 - * L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function",
117.207 - * Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
117.208 - * 1993). This algorithm offers n*log(n) performance on many data sets
117.209 - * that cause other quicksorts to degrade to quadratic performance.
117.210 + * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
117.211 + * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
117.212 + * offers O(n log(n)) performance on many data sets that cause other
117.213 + * quicksorts to degrade to quadratic performance, and is typically
117.214 + * faster than traditional (one-pivot) Quicksort implementations.
117.215 *
117.216 * @param a the array to be sorted
117.217 */
117.218 public static void sort(short[] a) {
117.219 - sort1(a, 0, a.length);
117.220 + DualPivotQuicksort.sort(a);
117.221 }
117.222
117.223 /**
117.224 - * Sorts the specified range of the specified array of shorts into
117.225 - * ascending numerical order. The range to be sorted extends from index
117.226 - * <tt>fromIndex</tt>, inclusive, to index <tt>toIndex</tt>, exclusive.
117.227 - * (If <tt>fromIndex==toIndex</tt>, the range to be sorted is empty.)<p>
117.228 + * Sorts the specified range of the array into ascending order. The range
117.229 + * to be sorted extends from the index {@code fromIndex}, inclusive, to
117.230 + * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
117.231 + * the range to be sorted is empty.
117.232 *
117.233 - * The sorting algorithm is a tuned quicksort, adapted from Jon
117.234 - * L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function",
117.235 - * Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
117.236 - * 1993). This algorithm offers n*log(n) performance on many data sets
117.237 - * that cause other quicksorts to degrade to quadratic performance.
117.238 + * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
117.239 + * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
117.240 + * offers O(n log(n)) performance on many data sets that cause other
117.241 + * quicksorts to degrade to quadratic performance, and is typically
117.242 + * faster than traditional (one-pivot) Quicksort implementations.
117.243 *
117.244 * @param a the array to be sorted
117.245 - * @param fromIndex the index of the first element (inclusive) to be
117.246 - * sorted
117.247 - * @param toIndex the index of the last element (exclusive) to be sorted
117.248 - * @throws IllegalArgumentException if <tt>fromIndex > toIndex</tt>
117.249 - * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex < 0</tt> or
117.250 - * <tt>toIndex > a.length</tt>
117.251 + * @param fromIndex the index of the first element, inclusive, to be sorted
117.252 + * @param toIndex the index of the last element, exclusive, to be sorted
117.253 + *
117.254 + * @throws IllegalArgumentException if {@code fromIndex > toIndex}
117.255 + * @throws ArrayIndexOutOfBoundsException
117.256 + * if {@code fromIndex < 0} or {@code toIndex > a.length}
117.257 */
117.258 public static void sort(short[] a, int fromIndex, int toIndex) {
117.259 - rangeCheck(a.length, fromIndex, toIndex);
117.260 - sort1(a, fromIndex, toIndex-fromIndex);
117.261 + DualPivotQuicksort.sort(a, fromIndex, toIndex);
117.262 }
117.263
117.264 /**
117.265 - * Sorts the specified array of chars into ascending numerical order.
117.266 - * The sorting algorithm is a tuned quicksort, adapted from Jon
117.267 - * L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function",
117.268 - * Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
117.269 - * 1993). This algorithm offers n*log(n) performance on many data sets
117.270 - * that cause other quicksorts to degrade to quadratic performance.
117.271 + * Sorts the specified array into ascending numerical order.
117.272 + *
117.273 + * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
117.274 + * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
117.275 + * offers O(n log(n)) performance on many data sets that cause other
117.276 + * quicksorts to degrade to quadratic performance, and is typically
117.277 + * faster than traditional (one-pivot) Quicksort implementations.
117.278 *
117.279 * @param a the array to be sorted
117.280 */
117.281 public static void sort(char[] a) {
117.282 - sort1(a, 0, a.length);
117.283 + DualPivotQuicksort.sort(a);
117.284 }
117.285
117.286 /**
117.287 - * Sorts the specified range of the specified array of chars into
117.288 - * ascending numerical order. The range to be sorted extends from index
117.289 - * <tt>fromIndex</tt>, inclusive, to index <tt>toIndex</tt>, exclusive.
117.290 - * (If <tt>fromIndex==toIndex</tt>, the range to be sorted is empty.)<p>
117.291 + * Sorts the specified range of the array into ascending order. The range
117.292 + * to be sorted extends from the index {@code fromIndex}, inclusive, to
117.293 + * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
117.294 + * the range to be sorted is empty.
117.295 *
117.296 - * The sorting algorithm is a tuned quicksort, adapted from Jon
117.297 - * L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function",
117.298 - * Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
117.299 - * 1993). This algorithm offers n*log(n) performance on many data sets
117.300 - * that cause other quicksorts to degrade to quadratic performance.
117.301 + * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
117.302 + * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
117.303 + * offers O(n log(n)) performance on many data sets that cause other
117.304 + * quicksorts to degrade to quadratic performance, and is typically
117.305 + * faster than traditional (one-pivot) Quicksort implementations.
117.306 *
117.307 * @param a the array to be sorted
117.308 - * @param fromIndex the index of the first element (inclusive) to be
117.309 - * sorted
117.310 - * @param toIndex the index of the last element (exclusive) to be sorted
117.311 - * @throws IllegalArgumentException if <tt>fromIndex > toIndex</tt>
117.312 - * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex < 0</tt> or
117.313 - * <tt>toIndex > a.length</tt>
117.314 + * @param fromIndex the index of the first element, inclusive, to be sorted
117.315 + * @param toIndex the index of the last element, exclusive, to be sorted
117.316 + *
117.317 + * @throws IllegalArgumentException if {@code fromIndex > toIndex}
117.318 + * @throws ArrayIndexOutOfBoundsException
117.319 + * if {@code fromIndex < 0} or {@code toIndex > a.length}
117.320 */
117.321 public static void sort(char[] a, int fromIndex, int toIndex) {
117.322 - rangeCheck(a.length, fromIndex, toIndex);
117.323 - sort1(a, fromIndex, toIndex-fromIndex);
117.324 + DualPivotQuicksort.sort(a, fromIndex, toIndex);
117.325 }
117.326
117.327 /**
117.328 - * Sorts the specified array of bytes into ascending numerical order.
117.329 - * The sorting algorithm is a tuned quicksort, adapted from Jon
117.330 - * L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function",
117.331 - * Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
117.332 - * 1993). This algorithm offers n*log(n) performance on many data sets
117.333 - * that cause other quicksorts to degrade to quadratic performance.
117.334 + * Sorts the specified array into ascending numerical order.
117.335 + *
117.336 + * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
117.337 + * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
117.338 + * offers O(n log(n)) performance on many data sets that cause other
117.339 + * quicksorts to degrade to quadratic performance, and is typically
117.340 + * faster than traditional (one-pivot) Quicksort implementations.
117.341 *
117.342 * @param a the array to be sorted
117.343 */
117.344 public static void sort(byte[] a) {
117.345 - sort1(a, 0, a.length);
117.346 + DualPivotQuicksort.sort(a);
117.347 }
117.348
117.349 /**
117.350 - * Sorts the specified range of the specified array of bytes into
117.351 - * ascending numerical order. The range to be sorted extends from index
117.352 - * <tt>fromIndex</tt>, inclusive, to index <tt>toIndex</tt>, exclusive.
117.353 - * (If <tt>fromIndex==toIndex</tt>, the range to be sorted is empty.)<p>
117.354 + * Sorts the specified range of the array into ascending order. The range
117.355 + * to be sorted extends from the index {@code fromIndex}, inclusive, to
117.356 + * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
117.357 + * the range to be sorted is empty.
117.358 *
117.359 - * The sorting algorithm is a tuned quicksort, adapted from Jon
117.360 - * L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function",
117.361 - * Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
117.362 - * 1993). This algorithm offers n*log(n) performance on many data sets
117.363 - * that cause other quicksorts to degrade to quadratic performance.
117.364 + * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
117.365 + * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
117.366 + * offers O(n log(n)) performance on many data sets that cause other
117.367 + * quicksorts to degrade to quadratic performance, and is typically
117.368 + * faster than traditional (one-pivot) Quicksort implementations.
117.369 *
117.370 * @param a the array to be sorted
117.371 - * @param fromIndex the index of the first element (inclusive) to be
117.372 - * sorted
117.373 - * @param toIndex the index of the last element (exclusive) to be sorted
117.374 - * @throws IllegalArgumentException if <tt>fromIndex > toIndex</tt>
117.375 - * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex < 0</tt> or
117.376 - * <tt>toIndex > a.length</tt>
117.377 + * @param fromIndex the index of the first element, inclusive, to be sorted
117.378 + * @param toIndex the index of the last element, exclusive, to be sorted
117.379 + *
117.380 + * @throws IllegalArgumentException if {@code fromIndex > toIndex}
117.381 + * @throws ArrayIndexOutOfBoundsException
117.382 + * if {@code fromIndex < 0} or {@code toIndex > a.length}
117.383 */
117.384 public static void sort(byte[] a, int fromIndex, int toIndex) {
117.385 - rangeCheck(a.length, fromIndex, toIndex);
117.386 - sort1(a, fromIndex, toIndex-fromIndex);
117.387 + DualPivotQuicksort.sort(a, fromIndex, toIndex);
117.388 }
117.389
117.390 /**
117.391 - * Sorts the specified array of doubles into ascending numerical order.
117.392 - * <p>
117.393 - * The <code><</code> relation does not provide a total order on
117.394 - * all floating-point values; although they are distinct numbers
117.395 - * <code>-0.0 == 0.0</code> is <code>true</code> and a NaN value
117.396 - * compares neither less than, greater than, nor equal to any
117.397 - * floating-point value, even itself. To allow the sort to
117.398 - * proceed, instead of using the <code><</code> relation to
117.399 - * determine ascending numerical order, this method uses the total
117.400 - * order imposed by {@link Double#compareTo}. This ordering
117.401 - * differs from the <code><</code> relation in that
117.402 - * <code>-0.0</code> is treated as less than <code>0.0</code> and
117.403 - * NaN is considered greater than any other floating-point value.
117.404 - * For the purposes of sorting, all NaN values are considered
117.405 - * equivalent and equal.
117.406 - * <p>
117.407 - * The sorting algorithm is a tuned quicksort, adapted from Jon
117.408 - * L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function",
117.409 - * Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
117.410 - * 1993). This algorithm offers n*log(n) performance on many data sets
117.411 - * that cause other quicksorts to degrade to quadratic performance.
117.412 + * Sorts the specified array into ascending numerical order.
117.413 + *
117.414 + * <p>The {@code <} relation does not provide a total order on all float
117.415 + * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
117.416 + * value compares neither less than, greater than, nor equal to any value,
117.417 + * even itself. This method uses the total order imposed by the method
117.418 + * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
117.419 + * {@code 0.0f} and {@code Float.NaN} is considered greater than any
117.420 + * other value and all {@code Float.NaN} values are considered equal.
117.421 + *
117.422 + * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
117.423 + * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
117.424 + * offers O(n log(n)) performance on many data sets that cause other
117.425 + * quicksorts to degrade to quadratic performance, and is typically
117.426 + * faster than traditional (one-pivot) Quicksort implementations.
117.427 + *
117.428 + * @param a the array to be sorted
117.429 + */
117.430 + public static void sort(float[] a) {
117.431 + DualPivotQuicksort.sort(a);
117.432 + }
117.433 +
117.434 + /**
117.435 + * Sorts the specified range of the array into ascending order. The range
117.436 + * to be sorted extends from the index {@code fromIndex}, inclusive, to
117.437 + * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
117.438 + * the range to be sorted is empty.
117.439 + *
117.440 + * <p>The {@code <} relation does not provide a total order on all float
117.441 + * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
117.442 + * value compares neither less than, greater than, nor equal to any value,
117.443 + * even itself. This method uses the total order imposed by the method
117.444 + * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
117.445 + * {@code 0.0f} and {@code Float.NaN} is considered greater than any
117.446 + * other value and all {@code Float.NaN} values are considered equal.
117.447 + *
117.448 + * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
117.449 + * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
117.450 + * offers O(n log(n)) performance on many data sets that cause other
117.451 + * quicksorts to degrade to quadratic performance, and is typically
117.452 + * faster than traditional (one-pivot) Quicksort implementations.
117.453 + *
117.454 + * @param a the array to be sorted
117.455 + * @param fromIndex the index of the first element, inclusive, to be sorted
117.456 + * @param toIndex the index of the last element, exclusive, to be sorted
117.457 + *
117.458 + * @throws IllegalArgumentException if {@code fromIndex > toIndex}
117.459 + * @throws ArrayIndexOutOfBoundsException
117.460 + * if {@code fromIndex < 0} or {@code toIndex > a.length}
117.461 + */
117.462 + public static void sort(float[] a, int fromIndex, int toIndex) {
117.463 + DualPivotQuicksort.sort(a, fromIndex, toIndex);
117.464 + }
117.465 +
117.466 + /**
117.467 + * Sorts the specified array into ascending numerical order.
117.468 + *
117.469 + * <p>The {@code <} relation does not provide a total order on all double
117.470 + * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
117.471 + * value compares neither less than, greater than, nor equal to any value,
117.472 + * even itself. This method uses the total order imposed by the method
117.473 + * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
117.474 + * {@code 0.0d} and {@code Double.NaN} is considered greater than any
117.475 + * other value and all {@code Double.NaN} values are considered equal.
117.476 + *
117.477 + * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
117.478 + * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
117.479 + * offers O(n log(n)) performance on many data sets that cause other
117.480 + * quicksorts to degrade to quadratic performance, and is typically
117.481 + * faster than traditional (one-pivot) Quicksort implementations.
117.482 *
117.483 * @param a the array to be sorted
117.484 */
117.485 public static void sort(double[] a) {
117.486 - sort2(a, 0, a.length);
117.487 + DualPivotQuicksort.sort(a);
117.488 }
117.489
117.490 /**
117.491 - * Sorts the specified range of the specified array of doubles into
117.492 - * ascending numerical order. The range to be sorted extends from index
117.493 - * <tt>fromIndex</tt>, inclusive, to index <tt>toIndex</tt>, exclusive.
117.494 - * (If <tt>fromIndex==toIndex</tt>, the range to be sorted is empty.)
117.495 - * <p>
117.496 - * The <code><</code> relation does not provide a total order on
117.497 - * all floating-point values; although they are distinct numbers
117.498 - * <code>-0.0 == 0.0</code> is <code>true</code> and a NaN value
117.499 - * compares neither less than, greater than, nor equal to any
117.500 - * floating-point value, even itself. To allow the sort to
117.501 - * proceed, instead of using the <code><</code> relation to
117.502 - * determine ascending numerical order, this method uses the total
117.503 - * order imposed by {@link Double#compareTo}. This ordering
117.504 - * differs from the <code><</code> relation in that
117.505 - * <code>-0.0</code> is treated as less than <code>0.0</code> and
117.506 - * NaN is considered greater than any other floating-point value.
117.507 - * For the purposes of sorting, all NaN values are considered
117.508 - * equivalent and equal.
117.509 - * <p>
117.510 - * The sorting algorithm is a tuned quicksort, adapted from Jon
117.511 - * L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function",
117.512 - * Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
117.513 - * 1993). This algorithm offers n*log(n) performance on many data sets
117.514 - * that cause other quicksorts to degrade to quadratic performance.
117.515 + * Sorts the specified range of the array into ascending order. The range
117.516 + * to be sorted extends from the index {@code fromIndex}, inclusive, to
117.517 + * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
117.518 + * the range to be sorted is empty.
117.519 + *
117.520 + * <p>The {@code <} relation does not provide a total order on all double
117.521 + * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
117.522 + * value compares neither less than, greater than, nor equal to any value,
117.523 + * even itself. This method uses the total order imposed by the method
117.524 + * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
117.525 + * {@code 0.0d} and {@code Double.NaN} is considered greater than any
117.526 + * other value and all {@code Double.NaN} values are considered equal.
117.527 + *
117.528 + * <p>Implementation note: The sorting algorithm is a Dual-Pivot Quicksort
117.529 + * by Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. This algorithm
117.530 + * offers O(n log(n)) performance on many data sets that cause other
117.531 + * quicksorts to degrade to quadratic performance, and is typically
117.532 + * faster than traditional (one-pivot) Quicksort implementations.
117.533 *
117.534 * @param a the array to be sorted
117.535 - * @param fromIndex the index of the first element (inclusive) to be
117.536 - * sorted
117.537 - * @param toIndex the index of the last element (exclusive) to be sorted
117.538 - * @throws IllegalArgumentException if <tt>fromIndex > toIndex</tt>
117.539 - * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex < 0</tt> or
117.540 - * <tt>toIndex > a.length</tt>
117.541 + * @param fromIndex the index of the first element, inclusive, to be sorted
117.542 + * @param toIndex the index of the last element, exclusive, to be sorted
117.543 + *
117.544 + * @throws IllegalArgumentException if {@code fromIndex > toIndex}
117.545 + * @throws ArrayIndexOutOfBoundsException
117.546 + * if {@code fromIndex < 0} or {@code toIndex > a.length}
117.547 */
117.548 public static void sort(double[] a, int fromIndex, int toIndex) {
117.549 - rangeCheck(a.length, fromIndex, toIndex);
117.550 - sort2(a, fromIndex, toIndex);
117.551 + DualPivotQuicksort.sort(a, fromIndex, toIndex);
117.552 }
117.553
117.554 - /**
117.555 - * Sorts the specified array of floats into ascending numerical order.
117.556 - * <p>
117.557 - * The <code><</code> relation does not provide a total order on
117.558 - * all floating-point values; although they are distinct numbers
117.559 - * <code>-0.0f == 0.0f</code> is <code>true</code> and a NaN value
117.560 - * compares neither less than, greater than, nor equal to any
117.561 - * floating-point value, even itself. To allow the sort to
117.562 - * proceed, instead of using the <code><</code> relation to
117.563 - * determine ascending numerical order, this method uses the total
117.564 - * order imposed by {@link Float#compareTo}. This ordering
117.565 - * differs from the <code><</code> relation in that
117.566 - * <code>-0.0f</code> is treated as less than <code>0.0f</code> and
117.567 - * NaN is considered greater than any other floating-point value.
117.568 - * For the purposes of sorting, all NaN values are considered
117.569 - * equivalent and equal.
117.570 - * <p>
117.571 - * The sorting algorithm is a tuned quicksort, adapted from Jon
117.572 - * L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function",
117.573 - * Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
117.574 - * 1993). This algorithm offers n*log(n) performance on many data sets
117.575 - * that cause other quicksorts to degrade to quadratic performance.
117.576 + /*
117.577 + * Sorting of complex type arrays.
117.578 *
117.579 - * @param a the array to be sorted
117.580 */
117.581 - public static void sort(float[] a) {
117.582 - sort2(a, 0, a.length);
117.583 - }
117.584 -
117.585 - /**
117.586 - * Sorts the specified range of the specified array of floats into
117.587 - * ascending numerical order. The range to be sorted extends from index
117.588 - * <tt>fromIndex</tt>, inclusive, to index <tt>toIndex</tt>, exclusive.
117.589 - * (If <tt>fromIndex==toIndex</tt>, the range to be sorted is empty.)
117.590 - * <p>
117.591 - * The <code><</code> relation does not provide a total order on
117.592 - * all floating-point values; although they are distinct numbers
117.593 - * <code>-0.0f == 0.0f</code> is <code>true</code> and a NaN value
117.594 - * compares neither less than, greater than, nor equal to any
117.595 - * floating-point value, even itself. To allow the sort to
117.596 - * proceed, instead of using the <code><</code> relation to
117.597 - * determine ascending numerical order, this method uses the total
117.598 - * order imposed by {@link Float#compareTo}. This ordering
117.599 - * differs from the <code><</code> relation in that
117.600 - * <code>-0.0f</code> is treated as less than <code>0.0f</code> and
117.601 - * NaN is considered greater than any other floating-point value.
117.602 - * For the purposes of sorting, all NaN values are considered
117.603 - * equivalent and equal.
117.604 - * <p>
117.605 - * The sorting algorithm is a tuned quicksort, adapted from Jon
117.606 - * L. Bentley and M. Douglas McIlroy's "Engineering a Sort Function",
117.607 - * Software-Practice and Experience, Vol. 23(11) P. 1249-1265 (November
117.608 - * 1993). This algorithm offers n*log(n) performance on many data sets
117.609 - * that cause other quicksorts to degrade to quadratic performance.
117.610 - *
117.611 - * @param a the array to be sorted
117.612 - * @param fromIndex the index of the first element (inclusive) to be
117.613 - * sorted
117.614 - * @param toIndex the index of the last element (exclusive) to be sorted
117.615 - * @throws IllegalArgumentException if <tt>fromIndex > toIndex</tt>
117.616 - * @throws ArrayIndexOutOfBoundsException if <tt>fromIndex < 0</tt> or
117.617 - * <tt>toIndex > a.length</tt>
117.618 - */
117.619 - public static void sort(float[] a, int fromIndex, int toIndex) {
117.620 - rangeCheck(a.length, fromIndex, toIndex);
117.621 - sort2(a, fromIndex, toIndex);
117.622 - }
117.623 -
117.624 - private static void sort2(double a[], int fromIndex, int toIndex) {
117.625 - final long NEG_ZERO_BITS = Double.doubleToLongBits(-0.0d);
117.626 - /*
117.627 - * The sort is done in three phases to avoid the expense of using
117.628 - * NaN and -0.0 aware comparisons during the main sort.
117.629 - */
117.630 -
117.631 - /*
117.632 - * Preprocessing phase: Move any NaN's to end of array, count the
117.633 - * number of -0.0's, and turn them into 0.0's.
117.634 - */
117.635 - int numNegZeros = 0;
117.636 - int i = fromIndex, n = toIndex;
117.637 - while(i < n) {
117.638 - if (a[i] != a[i]) {
117.639 - swap(a, i, --n);
117.640 - } else {
117.641 - if (a[i]==0 && Double.doubleToLongBits(a[i])==NEG_ZERO_BITS) {
117.642 - a[i] = 0.0d;
117.643 - numNegZeros++;
117.644 - }
117.645 - i++;
117.646 - }
117.647 - }
117.648 -
117.649 - // Main sort phase: quicksort everything but the NaN's
117.650 - sort1(a, fromIndex, n-fromIndex);
117.651 -
117.652 - // Postprocessing phase: change 0.0's to -0.0's as required
117.653 - if (numNegZeros != 0) {
117.654 - int j = binarySearch0(a, fromIndex, n, 0.0d); // posn of ANY zero
117.655 - do {
117.656 - j--;
117.657 - } while (j>=fromIndex && a[j]==0.0d);
117.658 -
117.659 - // j is now one less than the index of the FIRST zero
117.660 - for (int k=0; k<numNegZeros; k++)
117.661 - a[++j] = -0.0d;
117.662 - }
117.663 - }
117.664 -
117.665 -
117.666 - private static void sort2(float a[], int fromIndex, int toIndex) {
117.667 - final int NEG_ZERO_BITS = Float.floatToIntBits(-0.0f);
117.668 - /*
117.669 - * The sort is done in three phases to avoid the expense of using
117.670 - * NaN and -0.0 aware comparisons during the main sort.
117.671 - */
117.672 -
117.673 - /*
117.674 - * Preprocessing phase: Move any NaN's to end of array, count the
117.675 - * number of -0.0's, and turn them into 0.0's.
117.676 - */
117.677 - int numNegZeros = 0;
117.678 - int i = fromIndex, n = toIndex;
117.679 - while(i < n) {
117.680 - if (a[i] != a[i]) {
117.681 - swap(a, i, --n);
117.682 - } else {
117.683 - if (a[i]==0 && Float.floatToIntBits(a[i])==NEG_ZERO_BITS) {
117.684 - a[i] = 0.0f;
117.685 - numNegZeros++;
117.686 - }
117.687 - i++;
117.688 - }
117.689 - }
117.690 -
117.691 - // Main sort phase: quicksort everything but the NaN's
117.692 - sort1(a, fromIndex, n-fromIndex);
117.693 -
117.694 - // Postprocessing phase: change 0.0's to -0.0's as required
117.695 - if (numNegZeros != 0) {
117.696 - int j = binarySearch0(a, fromIndex, n, 0.0f); // posn of ANY zero
117.697 - do {
117.698 - j--;
117.699 - } while (j>=fromIndex && a[j]==0.0f);
117.700 -
117.701 - // j is now one less than the index of the FIRST zero
117.702 - for (int k=0; k<numNegZeros; k++)
117.703 - a[++j] = -0.0f;
117.704 - }
117.705 - }
117.706 -
117.707 -
117.708 - /*
117.709 - * The code for each of the seven primitive types is largely identical.
117.710 - * C'est la vie.
117.711 - */
117.712 -
117.713 - /**
117.714 - * Sorts the specified sub-array of longs into ascending order.
117.715 - */
117.716 - private static void sort1(long x[], int off, int len) {
117.717 - // Insertion sort on smallest arrays
117.718 - if (len < 7) {
117.719 - for (int i=off; i<len+off; i++)
117.720 - for (int j=i; j>off && x[j-1]>x[j]; j--)
117.721 - swap(x, j, j-1);
117.722 - return;
117.723 - }
117.724 -
117.725 - // Choose a partition element, v
117.726 - int m = off + (len >> 1); // Small arrays, middle element
117.727 - if (len > 7) {
117.728 - int l = off;
117.729 - int n = off + len - 1;
117.730 - if (len > 40) { // Big arrays, pseudomedian of 9
117.731 - int s = len/8;
117.732 - l = med3(x, l, l+s, l+2*s);
117.733 - m = med3(x, m-s, m, m+s);
117.734 - n = med3(x, n-2*s, n-s, n);
117.735 - }
117.736 - m = med3(x, l, m, n); // Mid-size, med of 3
117.737 - }
117.738 - long v = x[m];
117.739 -
117.740 - // Establish Invariant: v* (<v)* (>v)* v*
117.741 - int a = off, b = a, c = off + len - 1, d = c;
117.742 - while(true) {
117.743 - while (b <= c && x[b] <= v) {
117.744 - if (x[b] == v)
117.745 - swap(x, a++, b);
117.746 - b++;
117.747 - }
117.748 - while (c >= b && x[c] >= v) {
117.749 - if (x[c] == v)
117.750 - swap(x, c, d--);
117.751 - c--;
117.752 - }
117.753 - if (b > c)
117.754 - break;
117.755 - swap(x, b++, c--);
117.756 - }
117.757 -
117.758 - // Swap partition elements back to middle
117.759 - int s, n = off + len;
117.760 - s = Math.min(a-off, b-a ); vecswap(x, off, b-s, s);
117.761 - s = Math.min(d-c, n-d-1); vecswap(x, b, n-s, s);
117.762 -
117.763 - // Recursively sort non-partition-elements
117.764 - if ((s = b-a) > 1)
117.765 - sort1(x, off, s);
117.766 - if ((s = d-c) > 1)
117.767 - sort1(x, n-s, s);
117.768 - }
117.769 -
117.770 - /**
117.771 - * Swaps x[a] with x[b].
117.772 - */
117.773 - private static void swap(long x[], int a, int b) {
117.774 - long t = x[a];
117.775 - x[a] = x[b];
117.776 - x[b] = t;
117.777 - }
117.778 -
117.779 - /**
117.780 - * Swaps x[a .. (a+n-1)] with x[b .. (b+n-1)].
117.781 - */
117.782 - private static void vecswap(long x[], int a, int b, int n) {
117.783 - for (int i=0; i<n; i++, a++, b++)
117.784 - swap(x, a, b);
117.785 - }
117.786 -
117.787 - /**
117.788 - * Returns the index of the median of the three indexed longs.
117.789 - */
117.790 - private static int med3(long x[], int a, int b, int c) {
117.791 - return (x[a] < x[b] ?
117.792 - (x[b] < x[c] ? b : x[a] < x[c] ? c : a) :
117.793 - (x[b] > x[c] ? b : x[a] > x[c] ? c : a));
117.794 - }
117.795 -
117.796 - /**
117.797 - * Sorts the specified sub-array of integers into ascending order.
117.798 - */
117.799 - private static void sort1(int x[], int off, int len) {
117.800 - // Insertion sort on smallest arrays
117.801 - if (len < 7) {
117.802 - for (int i=off; i<len+off; i++)
117.803 - for (int j=i; j>off && x[j-1]>x[j]; j--)
117.804 - swap(x, j, j-1);
117.805 - return;
117.806 - }
117.807 -
117.808 - // Choose a partition element, v
117.809 - int m = off + (len >> 1); // Small arrays, middle element
117.810 - if (len > 7) {
117.811 - int l = off;
117.812 - int n = off + len - 1;
117.813 - if (len > 40) { // Big arrays, pseudomedian of 9
117.814 - int s = len/8;
117.815 - l = med3(x, l, l+s, l+2*s);
117.816 - m = med3(x, m-s, m, m+s);
117.817 - n = med3(x, n-2*s, n-s, n);
117.818 - }
117.819 - m = med3(x, l, m, n); // Mid-size, med of 3
117.820 - }
117.821 - int v = x[m];
117.822 -
117.823 - // Establish Invariant: v* (<v)* (>v)* v*
117.824 - int a = off, b = a, c = off + len - 1, d = c;
117.825 - while(true) {
117.826 - while (b <= c && x[b] <= v) {
117.827 - if (x[b] == v)
117.828 - swap(x, a++, b);
117.829 - b++;
117.830 - }
117.831 - while (c >= b && x[c] >= v) {
117.832 - if (x[c] == v)
117.833 - swap(x, c, d--);
117.834 - c--;
117.835 - }
117.836 - if (b > c)
117.837 - break;
117.838 - swap(x, b++, c--);
117.839 - }
117.840 -
117.841 - // Swap partition elements back to middle
117.842 - int s, n = off + len;
117.843 - s = Math.min(a-off, b-a ); vecswap(x, off, b-s, s);
117.844 - s = Math.min(d-c, n-d-1); vecswap(x, b, n-s, s);
117.845 -
117.846 - // Recursively sort non-partition-elements
117.847 - if ((s = b-a) > 1)
117.848 - sort1(x, off, s);
117.849 - if ((s = d-c) > 1)
117.850 - sort1(x, n-s, s);
117.851 - }
117.852 -
117.853 - /**
117.854 - * Swaps x[a] with x[b].
117.855 - */
117.856 - private static void swap(int x[], int a, int b) {
117.857 - int t = x[a];
117.858 - x[a] = x[b];
117.859 - x[b] = t;
117.860 - }
117.861 -
117.862 - /**
117.863 - * Swaps x[a .. (a+n-1)] with x[b .. (b+n-1)].
117.864 - */
117.865 - private static void vecswap(int x[], int a, int b, int n) {
117.866 - for (int i=0; i<n; i++, a++, b++)
117.867 - swap(x, a, b);
117.868 - }
117.869 -
117.870 - /**
117.871 - * Returns the index of the median of the three indexed integers.
117.872 - */
117.873 - private static int med3(int x[], int a, int b, int c) {
117.874 - return (x[a] < x[b] ?
117.875 - (x[b] < x[c] ? b : x[a] < x[c] ? c : a) :
117.876 - (x[b] > x[c] ? b : x[a] > x[c] ? c : a));
117.877 - }
117.878 -
117.879 - /**
117.880 - * Sorts the specified sub-array of shorts into ascending order.
117.881 - */
117.882 - private static void sort1(short x[], int off, int len) {
117.883 - // Insertion sort on smallest arrays
117.884 - if (len < 7) {
117.885 - for (int i=off; i<len+off; i++)
117.886 - for (int j=i; j>off && x[j-1]>x[j]; j--)
117.887 - swap(x, j, j-1);
117.888 - return;
117.889 - }
117.890 -
117.891 - // Choose a partition element, v
117.892 - int m = off + (len >> 1); // Small arrays, middle element
117.893 - if (len > 7) {
117.894 - int l = off;
117.895 - int n = off + len - 1;
117.896 - if (len > 40) { // Big arrays, pseudomedian of 9
117.897 - int s = len/8;
117.898 - l = med3(x, l, l+s, l+2*s);
117.899 - m = med3(x, m-s, m, m+s);
117.900 - n = med3(x, n-2*s, n-s, n);
117.901 - }
117.902 - m = med3(x, l, m, n); // Mid-size, med of 3
117.903 - }
117.904 - short v = x[m];
117.905 -
117.906 - // Establish Invariant: v* (<v)* (>v)* v*
117.907 - int a = off, b = a, c = off + len - 1, d = c;
117.908 - while(true) {
117.909 - while (b <= c && x[b] <= v) {
117.910 - if (x[b] == v)
117.911 - swap(x, a++, b);
117.912 - b++;
117.913 - }
117.914 - while (c >= b && x[c] >= v) {
117.915 - if (x[c] == v)
117.916 - swap(x, c, d--);
117.917 - c--;
117.918 - }
117.919 - if (b > c)
117.920 - break;
117.921 - swap(x, b++, c--);
117.922 - }
117.923 -
117.924 - // Swap partition elements back to middle
117.925 - int s, n = off + len;
117.926 - s = Math.min(a-off, b-a ); vecswap(x, off, b-s, s);
117.927 - s = Math.min(d-c, n-d-1); vecswap(x, b, n-s, s);
117.928 -
117.929 - // Recursively sort non-partition-elements
117.930 - if ((s = b-a) > 1)
117.931 - sort1(x, off, s);
117.932 - if ((s = d-c) > 1)
117.933 - sort1(x, n-s, s);
117.934 - }
117.935 -
117.936 - /**
117.937 - * Swaps x[a] with x[b].
117.938 - */
117.939 - private static void swap(short x[], int a, int b) {
117.940 - short t = x[a];
117.941 - x[a] = x[b];
117.942 - x[b] = t;
117.943 - }
117.944 -
117.945 - /**
117.946 - * Swaps x[a .. (a+n-1)] with x[b .. (b+n-1)].
117.947 - */
117.948 - private static void vecswap(short x[], int a, int b, int n) {
117.949 - for (int i=0; i<n; i++, a++, b++)
117.950 - swap(x, a, b);
117.951 - }
117.952 -
117.953 - /**
117.954 - * Returns the index of the median of the three indexed shorts.
117.955 - */
117.956 - private static int med3(short x[], int a, int b, int c) {
117.957 - return (x[a] < x[b] ?
117.958 - (x[b] < x[c] ? b : x[a] < x[c] ? c : a) :
117.959 - (x[b] > x[c] ? b : x[a] > x[c] ? c : a));
117.960 - }
117.961 -
117.962 -
117.963 - /**
117.964 - * Sorts the specified sub-array of chars into ascending order.
117.965 - */
117.966 - private static void sort1(char x[], int off, int len) {
117.967 - // Insertion sort on smallest arrays
117.968 - if (len < 7) {
117.969 - for (int i=off; i<len+off; i++)
117.970 - for (int j=i; j>off && x[j-1]>x[j]; j--)
117.971 - swap(x, j, j-1);
117.972 - return;
117.973 - }
117.974 -
117.975 - // Choose a partition element, v
117.976 - int m = off + (len >> 1); // Small arrays, middle element
117.977 - if (len > 7) {
117.978 - int l = off;
117.979 - int n = off + len - 1;
117.980 - if (len > 40) { // Big arrays, pseudomedian of 9
117.981 - int s = len/8;
117.982 - l = med3(x, l, l+s, l+2*s);
117.983 - m = med3(x, m-s, m, m+s);
117.984 - n = med3(x, n-2*s, n-s, n);
117.985 - }
117.986 - m = med3(x, l, m, n); // Mid-size, med of 3
117.987 - }
117.988 - char v = x[m];
117.989 -
117.990 - // Establish Invariant: v* (<v)* (>v)* v*
117.991 - int a = off, b = a, c = off + len - 1, d = c;
117.992 - while(true) {
117.993 - while (b <= c && x[b] <= v) {
117.994 - if (x[b] == v)
117.995 - swap(x, a++, b);
117.996 - b++;
117.997 - }
117.998 - while (c >= b && x[c] >= v) {
117.999 - if (x[c] == v)
117.1000 - swap(x, c, d--);
117.1001 - c--;
117.1002 - }
117.1003 - if (b > c)
117.1004 - break;
117.1005 - swap(x, b++, c--);
117.1006 - }
117.1007 -
117.1008 - // Swap partition elements back to middle
117.1009 - int s, n = off + len;
117.1010 - s = Math.min(a-off, b-a ); vecswap(x, off, b-s, s);
117.1011 - s = Math.min(d-c, n-d-1); vecswap(x, b, n-s, s);
117.1012 -
117.1013 - // Recursively sort non-partition-elements
117.1014 - if ((s = b-a) > 1)
117.1015 - sort1(x, off, s);
117.1016 - if ((s = d-c) > 1)
117.1017 - sort1(x, n-s, s);
117.1018 - }
117.1019 -
117.1020 - /**
117.1021 - * Swaps x[a] with x[b].
117.1022 - */
117.1023 - private static void swap(char x[], int a, int b) {
117.1024 - char t = x[a];
117.1025 - x[a] = x[b];
117.1026 - x[b] = t;
117.1027 - }
117.1028 -
117.1029 - /**
117.1030 - * Swaps x[a .. (a+n-1)] with x[b .. (b+n-1)].
117.1031 - */
117.1032 - private static void vecswap(char x[], int a, int b, int n) {
117.1033 - for (int i=0; i<n; i++, a++, b++)
117.1034 - swap(x, a, b);
117.1035 - }
117.1036 -
117.1037 - /**
117.1038 - * Returns the index of the median of the three indexed chars.
117.1039 - */
117.1040 - private static int med3(char x[], int a, int b, int c) {
117.1041 - return (x[a] < x[b] ?
117.1042 - (x[b] < x[c] ? b : x[a] < x[c] ? c : a) :
117.1043 - (x[b] > x[c] ? b : x[a] > x[c] ? c : a));
117.1044 - }
117.1045 -
117.1046 -
117.1047 - /**
117.1048 - * Sorts the specified sub-array of bytes into ascending order.
117.1049 - */
117.1050 - private static void sort1(byte x[], int off, int len) {
117.1051 - // Insertion sort on smallest arrays
117.1052 - if (len < 7) {
117.1053 - for (int i=off; i<len+off; i++)
117.1054 - for (int j=i; j>off && x[j-1]>x[j]; j--)
117.1055 - swap(x, j, j-1);
117.1056 - return;
117.1057 - }
117.1058 -
117.1059 - // Choose a partition element, v
117.1060 - int m = off + (len >> 1); // Small arrays, middle element
117.1061 - if (len > 7) {
117.1062 - int l = off;
117.1063 - int n = off + len - 1;
117.1064 - if (len > 40) { // Big arrays, pseudomedian of 9
117.1065 - int s = len/8;
117.1066 - l = med3(x, l, l+s, l+2*s);
117.1067 - m = med3(x, m-s, m, m+s);
117.1068 - n = med3(x, n-2*s, n-s, n);
117.1069 - }
117.1070 - m = med3(x, l, m, n); // Mid-size, med of 3
117.1071 - }
117.1072 - byte v = x[m];
117.1073 -
117.1074 - // Establish Invariant: v* (<v)* (>v)* v*
117.1075 - int a = off, b = a, c = off + len - 1, d = c;
117.1076 - while(true) {
117.1077 - while (b <= c && x[b] <= v) {
117.1078 - if (x[b] == v)
117.1079 - swap(x, a++, b);
117.1080 - b++;
117.1081 - }
117.1082 - while (c >= b && x[c] >= v) {
117.1083 - if (x[c] == v)
117.1084 - swap(x, c, d--);
117.1085 - c--;
117.1086 - }
117.1087 - if (b > c)
117.1088 - break;
117.1089 - swap(x, b++, c--);
117.1090 - }
117.1091 -
117.1092 - // Swap partition elements back to middle
117.1093 - int s, n = off + len;
117.1094 - s = Math.min(a-off, b-a ); vecswap(x, off, b-s, s);
117.1095 - s = Math.min(d-c, n-d-1); vecswap(x, b, n-s, s);
117.1096 -
117.1097 - // Recursively sort non-partition-elements
117.1098 - if ((s = b-a) > 1)
117.1099 - sort1(x, off, s);
117.1100 - if ((s = d-c) > 1)
117.1101 - sort1(x, n-s, s);
117.1102 - }
117.1103 -
117.1104 - /**
117.1105 - * Swaps x[a] with x[b].
117.1106 - */
117.1107 - private static void swap(byte x[], int a, int b) {
117.1108 - byte t = x[a];
117.1109 - x[a] = x[b];
117.1110 - x[b] = t;
117.1111 - }
117.1112 -
117.1113 - /**
117.1114 - * Swaps x[a .. (a+n-1)] with x[b .. (b+n-1)].
117.1115 - */
117.1116 - private static void vecswap(byte x[], int a, int b, int n) {
117.1117 - for (int i=0; i<n; i++, a++, b++)
117.1118 - swap(x, a, b);
117.1119 - }
117.1120 -
117.1121 - /**
117.1122 - * Returns the index of the median of the three indexed bytes.
117.1123 - */
117.1124 - private static int med3(byte x[], int a, int b, int c) {
117.1125 - return (x[a] < x[b] ?
117.1126 - (x[b] < x[c] ? b : x[a] < x[c] ? c : a) :
117.1127 - (x[b] > x[c] ? b : x[a] > x[c] ? c : a));
117.1128 - }
117.1129 -
117.1130 -
117.1131 - /**
117.1132 - * Sorts the specified sub-array of doubles into ascending order.
117.1133 - */
117.1134 - private static void sort1(double x[], int off, int len) {
117.1135 - // Insertion sort on smallest arrays
117.1136 - if (len < 7) {
117.1137 - for (int i=off; i<len+off; i++)
117.1138 - for (int j=i; j>off && x[j-1]>x[j]; j--)
117.1139 - swap(x, j, j-1);
117.1140 - return;
117.1141 - }
117.1142 -
117.1143 - // Choose a partition element, v
117.1144 - int m = off + (len >> 1); // Small arrays, middle element
117.1145 - if (len > 7) {
117.1146 - int l = off;
117.1147 - int n = off + len - 1;
117.1148 - if (len > 40) { // Big arrays, pseudomedian of 9
117.1149 - int s = len/8;
117.1150 - l = med3(x, l, l+s, l+2*s);
117.1151 - m = med3(x, m-s, m, m+s);
117.1152 - n = med3(x, n-2*s, n-s, n);
117.1153 - }
117.1154 - m = med3(x, l, m, n); // Mid-size, med of 3
117.1155 - }
117.1156 - double v = x[m];
117.1157 -
117.1158 - // Establish Invariant: v* (<v)* (>v)* v*
117.1159 - int a = off, b = a, c = off + len - 1, d = c;
117.1160 - while(true) {
117.1161 - while (b <= c && x[b] <= v) {
117.1162 - if (x[b] == v)
117.1163 - swap(x, a++, b);
117.1164 - b++;
117.1165 - }
117.1166 - while (c >= b && x[c] >= v) {
117.1167 - if (x[c] == v)
117.1168 - swap(x, c, d--);
117.1169 - c--;
117.1170 - }
117.1171 - if (b > c)
117.1172 - break;
117.1173 - swap(x, b++, c--);
117.1174 - }
117.1175 -
117.1176 - // Swap partition elements back to middle
117.1177 - int s, n = off + len;
117.1178 - s = Math.min(a-off, b-a ); vecswap(x, off, b-s, s);
117.1179 - s = Math.min(d-c, n-d-1); vecswap(x, b, n-s, s);
117.1180 -
117.1181 - // Recursively sort non-partition-elements
117.1182 - if ((s = b-a) > 1)
117.1183 - sort1(x, off, s);
117.1184 - if ((s = d-c) > 1)
117.1185 - sort1(x, n-s, s);
117.1186 - }
117.1187 -
117.1188 - /**
117.1189 - * Swaps x[a] with x[b].
117.1190 - */
117.1191 - private static void swap(double x[], int a, int b) {
117.1192 - double t = x[a];
117.1193 - x[a] = x[b];
117.1194 - x[b] = t;
117.1195 - }
117.1196 -
117.1197 - /**
117.1198 - * Swaps x[a .. (a+n-1)] with x[b .. (b+n-1)].
117.1199 - */
117.1200 - private static void vecswap(double x[], int a, int b, int n) {
117.1201 - for (int i=0; i<n; i++, a++, b++)
117.1202 - swap(x, a, b);
117.1203 - }
117.1204 -
117.1205 - /**
117.1206 - * Returns the index of the median of the three indexed doubles.
117.1207 - */
117.1208 - private static int med3(double x[], int a, int b, int c) {
117.1209 - return (x[a] < x[b] ?
117.1210 - (x[b] < x[c] ? b : x[a] < x[c] ? c : a) :
117.1211 - (x[b] > x[c] ? b : x[a] > x[c] ? c : a));
117.1212 - }
117.1213 -
117.1214 -
117.1215 - /**
117.1216 - * Sorts the specified sub-array of floats into ascending order.
117.1217 - */
117.1218 - private static void sort1(float x[], int off, int len) {
117.1219 - // Insertion sort on smallest arrays
117.1220 - if (len < 7) {
117.1221 - for (int i=off; i<len+off; i++)
117.1222 - for (int j=i; j>off && x[j-1]>x[j]; j--)
117.1223 - swap(x, j, j-1);
117.1224 - return;
117.1225 - }
117.1226 -
117.1227 - // Choose a partition element, v
117.1228 - int m = off + (len >> 1); // Small arrays, middle element
117.1229 - if (len > 7) {
117.1230 - int l = off;
117.1231 - int n = off + len - 1;
117.1232 - if (len > 40) { // Big arrays, pseudomedian of 9
117.1233 - int s = len/8;
117.1234 - l = med3(x, l, l+s, l+2*s);
117.1235 - m = med3(x, m-s, m, m+s);
117.1236 - n = med3(x, n-2*s, n-s, n);
117.1237 - }
117.1238 - m = med3(x, l, m, n); // Mid-size, med of 3
117.1239 - }
117.1240 - float v = x[m];
117.1241 -
117.1242 - // Establish Invariant: v* (<v)* (>v)* v*
117.1243 - int a = off, b = a, c = off + len - 1, d = c;
117.1244 - while(true) {
117.1245 - while (b <= c && x[b] <= v) {
117.1246 - if (x[b] == v)
117.1247 - swap(x, a++, b);
117.1248 - b++;
117.1249 - }
117.1250 - while (c >= b && x[c] >= v) {
117.1251 - if (x[c] == v)
117.1252 - swap(x, c, d--);
117.1253 - c--;
117.1254 - }
117.1255 - if (b > c)
117.1256 - break;
117.1257 - swap(x, b++, c--);
117.1258 - }
117.1259 -
117.1260 - // Swap partition elements back to middle
117.1261 - int s, n = off + len;
117.1262 - s = Math.min(a-off, b-a ); vecswap(x, off, b-s, s);
117.1263 - s = Math.min(d-c, n-d-1); vecswap(x, b, n-s, s);
117.1264 -
117.1265 - // Recursively sort non-partition-elements
117.1266 - if ((s = b-a) > 1)
117.1267 - sort1(x, off, s);
117.1268 - if ((s = d-c) > 1)
117.1269 - sort1(x, n-s, s);
117.1270 - }
117.1271 -
117.1272 - /**
117.1273 - * Swaps x[a] with x[b].
117.1274 - */
117.1275 - private static void swap(float x[], int a, int b) {
117.1276 - float t = x[a];
117.1277 - x[a] = x[b];
117.1278 - x[b] = t;
117.1279 - }
117.1280 -
117.1281 - /**
117.1282 - * Swaps x[a .. (a+n-1)] with x[b .. (b+n-1)].
117.1283 - */
117.1284 - private static void vecswap(float x[], int a, int b, int n) {
117.1285 - for (int i=0; i<n; i++, a++, b++)
117.1286 - swap(x, a, b);
117.1287 - }
117.1288 -
117.1289 - /**
117.1290 - * Returns the index of the median of the three indexed floats.
117.1291 - */
117.1292 - private static int med3(float x[], int a, int b, int c) {
117.1293 - return (x[a] < x[b] ?
117.1294 - (x[b] < x[c] ? b : x[a] < x[c] ? c : a) :
117.1295 - (x[b] > x[c] ? b : x[a] > x[c] ? c : a));
117.1296 - }
117.1297
117.1298 /**
117.1299 * Old merge sort implementation can be selected (for
117.1300 * compatibility with broken comparators) using a system property.
117.1301 * Cannot be a static boolean in the enclosing class due to
117.1302 - * circular dependencies. To be removed in a future release.
117.1303 + * circular dependencies. To be removed in a future release.
117.1304 */
117.1305 static final class LegacyMergeSort {
117.1306 private static final boolean userRequested =
117.1307 @@ -1235,7 +541,7 @@
117.1308
117.1309 /**
117.1310 * Tuning parameter: list size at or below which insertion sort will be
117.1311 - * used in preference to mergesort or quicksort.
117.1312 + * used in preference to mergesort.
117.1313 * To be removed in a future release.
117.1314 */
117.1315 private static final int INSERTIONSORT_THRESHOLD = 7;
117.1316 @@ -1474,17 +780,20 @@
117.1317 }
117.1318
117.1319 /**
117.1320 - * Check that fromIndex and toIndex are in range, and throw an
117.1321 - * appropriate exception if they aren't.
117.1322 + * Checks that {@code fromIndex} and {@code toIndex} are in
117.1323 + * the range and throws an appropriate exception, if they aren't.
117.1324 */
117.1325 - private static void rangeCheck(int arrayLen, int fromIndex, int toIndex) {
117.1326 - if (fromIndex > toIndex)
117.1327 - throw new IllegalArgumentException("fromIndex(" + fromIndex +
117.1328 - ") > toIndex(" + toIndex+")");
117.1329 - if (fromIndex < 0)
117.1330 + private static void rangeCheck(int length, int fromIndex, int toIndex) {
117.1331 + if (fromIndex > toIndex) {
117.1332 + throw new IllegalArgumentException(
117.1333 + "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
117.1334 + }
117.1335 + if (fromIndex < 0) {
117.1336 throw new ArrayIndexOutOfBoundsException(fromIndex);
117.1337 - if (toIndex > arrayLen)
117.1338 + }
117.1339 + if (toIndex > length) {
117.1340 throw new ArrayIndexOutOfBoundsException(toIndex);
117.1341 + }
117.1342 }
117.1343
117.1344 // Searching
117.1345 @@ -1987,21 +1296,21 @@
117.1346
117.1347 /**
117.1348 * Searches the specified array of floats for the specified value using
117.1349 - * the binary search algorithm. The array must be sorted
117.1350 - * (as by the {@link #sort(float[])} method) prior to making this call. If
117.1351 - * it is not sorted, the results are undefined. If the array contains
117.1352 + * the binary search algorithm. The array must be sorted
117.1353 + * (as by the {@link #sort(float[])} method) prior to making this call. If
117.1354 + * it is not sorted, the results are undefined. If the array contains
117.1355 * multiple elements with the specified value, there is no guarantee which
117.1356 - * one will be found. This method considers all NaN values to be
117.1357 + * one will be found. This method considers all NaN values to be
117.1358 * equivalent and equal.
117.1359 *
117.1360 * @param a the array to be searched
117.1361 * @param key the value to be searched for
117.1362 * @return index of the search key, if it is contained in the array;
117.1363 - * otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>. The
117.1364 + * otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>. The
117.1365 * <i>insertion point</i> is defined as the point at which the
117.1366 * key would be inserted into the array: the index of the first
117.1367 * element greater than the key, or <tt>a.length</tt> if all
117.1368 - * elements in the array are less than the specified key. Note
117.1369 + * elements in the array are less than the specified key. Note
117.1370 * that this guarantees that the return value will be >= 0 if
117.1371 * and only if the key is found.
117.1372 */
117.1373 @@ -2015,10 +1324,10 @@
117.1374 * the binary search algorithm.
117.1375 * The range must be sorted
117.1376 * (as by the {@link #sort(float[], int, int)} method)
117.1377 - * prior to making this call. If
117.1378 - * it is not sorted, the results are undefined. If the range contains
117.1379 + * prior to making this call. If
117.1380 + * it is not sorted, the results are undefined. If the range contains
117.1381 * multiple elements with the specified value, there is no guarantee which
117.1382 - * one will be found. This method considers all NaN values to be
117.1383 + * one will be found. This method considers all NaN values to be
117.1384 * equivalent and equal.
117.1385 *
117.1386 * @param a the array to be searched
117.1387 @@ -2028,12 +1337,12 @@
117.1388 * @param key the value to be searched for
117.1389 * @return index of the search key, if it is contained in the array
117.1390 * within the specified range;
117.1391 - * otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>. The
117.1392 + * otherwise, <tt>(-(<i>insertion point</i>) - 1)</tt>. The
117.1393 * <i>insertion point</i> is defined as the point at which the
117.1394 * key would be inserted into the array: the index of the first
117.1395 * element in the range greater than the key,
117.1396 * or <tt>toIndex</tt> if all
117.1397 - * elements in the range are less than the specified key. Note
117.1398 + * elements in the range are less than the specified key. Note
117.1399 * that this guarantees that the return value will be >= 0 if
117.1400 * and only if the key is found.
117.1401 * @throws IllegalArgumentException
117.1402 @@ -2076,10 +1385,9 @@
117.1403 return -(low + 1); // key not found.
117.1404 }
117.1405
117.1406 -
117.1407 /**
117.1408 * Searches the specified array for the specified object using the binary
117.1409 - * search algorithm. The array must be sorted into ascending order
117.1410 + * search algorithm. The array must be sorted into ascending order
117.1411 * according to the
117.1412 * {@linkplain Comparable natural ordering}
117.1413 * of its elements (as by the
117.1414 @@ -2269,7 +1577,6 @@
117.1415 int mid = (low + high) >>> 1;
117.1416 T midVal = a[mid];
117.1417 int cmp = c.compare(midVal, key);
117.1418 -
117.1419 if (cmp < 0)
117.1420 low = mid + 1;
117.1421 else if (cmp > 0)
117.1422 @@ -2280,7 +1587,6 @@
117.1423 return -(low + 1); // key not found.
117.1424 }
117.1425
117.1426 -
117.1427 // Equality Testing
117.1428
117.1429 /**
117.1430 @@ -2527,7 +1833,6 @@
117.1431 return true;
117.1432 }
117.1433
117.1434 -
117.1435 /**
117.1436 * Returns <tt>true</tt> if the two specified arrays of Objects are
117.1437 * <i>equal</i> to one another. The two arrays are considered equal if
117.1438 @@ -2562,7 +1867,6 @@
117.1439 return true;
117.1440 }
117.1441
117.1442 -
117.1443 // Filling
117.1444
117.1445 /**
117.1446 @@ -2885,8 +2189,8 @@
117.1447 a[i] = val;
117.1448 }
117.1449
117.1450 + // Cloning
117.1451
117.1452 - // Cloning
117.1453 /**
117.1454 * Copies the specified array, truncating or padding with nulls (if necessary)
117.1455 * so the copy has the specified length. For all indices that are
117.1456 @@ -3495,7 +2799,6 @@
117.1457 return copy;
117.1458 }
117.1459
117.1460 -
117.1461 // Misc
117.1462
117.1463 /**
117.1464 @@ -3928,6 +3231,7 @@
117.1465 * @param a2 the other array to be tested for equality
117.1466 * @return <tt>true</tt> if the two arrays are equal
117.1467 * @see #equals(Object[],Object[])
117.1468 + * @see Objects#deepEquals(Object, Object)
117.1469 * @since 1.5
117.1470 */
117.1471 public static boolean deepEquals(Object[] a1, Object[] a2) {
117.1472 @@ -3949,27 +3253,7 @@
117.1473 return false;
117.1474
117.1475 // Figure out whether the two elements are equal
117.1476 - boolean eq;
117.1477 - if (e1 instanceof Object[] && e2 instanceof Object[])
117.1478 - eq = deepEquals ((Object[]) e1, (Object[]) e2);
117.1479 - else if (e1 instanceof byte[] && e2 instanceof byte[])
117.1480 - eq = equals((byte[]) e1, (byte[]) e2);
117.1481 - else if (e1 instanceof short[] && e2 instanceof short[])
117.1482 - eq = equals((short[]) e1, (short[]) e2);
117.1483 - else if (e1 instanceof int[] && e2 instanceof int[])
117.1484 - eq = equals((int[]) e1, (int[]) e2);
117.1485 - else if (e1 instanceof long[] && e2 instanceof long[])
117.1486 - eq = equals((long[]) e1, (long[]) e2);
117.1487 - else if (e1 instanceof char[] && e2 instanceof char[])
117.1488 - eq = equals((char[]) e1, (char[]) e2);
117.1489 - else if (e1 instanceof float[] && e2 instanceof float[])
117.1490 - eq = equals((float[]) e1, (float[]) e2);
117.1491 - else if (e1 instanceof double[] && e2 instanceof double[])
117.1492 - eq = equals((double[]) e1, (double[]) e2);
117.1493 - else if (e1 instanceof boolean[] && e2 instanceof boolean[])
117.1494 - eq = equals((boolean[]) e1, (boolean[]) e2);
117.1495 - else
117.1496 - eq = e1.equals(e2);
117.1497 + boolean eq = deepEquals0(e1, e2);
117.1498
117.1499 if (!eq)
117.1500 return false;
117.1501 @@ -3977,6 +3261,32 @@
117.1502 return true;
117.1503 }
117.1504
117.1505 + static boolean deepEquals0(Object e1, Object e2) {
117.1506 + assert e1 != null;
117.1507 + boolean eq;
117.1508 + if (e1 instanceof Object[] && e2 instanceof Object[])
117.1509 + eq = deepEquals ((Object[]) e1, (Object[]) e2);
117.1510 + else if (e1 instanceof byte[] && e2 instanceof byte[])
117.1511 + eq = equals((byte[]) e1, (byte[]) e2);
117.1512 + else if (e1 instanceof short[] && e2 instanceof short[])
117.1513 + eq = equals((short[]) e1, (short[]) e2);
117.1514 + else if (e1 instanceof int[] && e2 instanceof int[])
117.1515 + eq = equals((int[]) e1, (int[]) e2);
117.1516 + else if (e1 instanceof long[] && e2 instanceof long[])
117.1517 + eq = equals((long[]) e1, (long[]) e2);
117.1518 + else if (e1 instanceof char[] && e2 instanceof char[])
117.1519 + eq = equals((char[]) e1, (char[]) e2);
117.1520 + else if (e1 instanceof float[] && e2 instanceof float[])
117.1521 + eq = equals((float[]) e1, (float[]) e2);
117.1522 + else if (e1 instanceof double[] && e2 instanceof double[])
117.1523 + eq = equals((double[]) e1, (double[]) e2);
117.1524 + else if (e1 instanceof boolean[] && e2 instanceof boolean[])
117.1525 + eq = equals((boolean[]) e1, (boolean[]) e2);
117.1526 + else
117.1527 + eq = e1.equals(e2);
117.1528 + return eq;
117.1529 + }
117.1530 +
117.1531 /**
117.1532 * Returns a string representation of the contents of the specified array.
117.1533 * The string representation consists of a list of the array's elements,
117.1534 @@ -4173,6 +3483,7 @@
117.1535 public static String toString(float[] a) {
117.1536 if (a == null)
117.1537 return "null";
117.1538 +
117.1539 int iMax = a.length - 1;
117.1540 if (iMax == -1)
117.1541 return "[]";
117.1542 @@ -4236,6 +3547,7 @@
117.1543 public static String toString(Object[] a) {
117.1544 if (a == null)
117.1545 return "null";
117.1546 +
117.1547 int iMax = a.length - 1;
117.1548 if (iMax == -1)
117.1549 return "[]";
118.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
118.2 +++ b/src/share/classes/java/util/DualPivotQuicksort.java Wed Nov 25 11:08:25 2009 -0800
118.3 @@ -0,0 +1,2051 @@
118.4 +/*
118.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
118.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
118.7 + *
118.8 + * This code is free software; you can redistribute it and/or modify it
118.9 + * under the terms of the GNU General Public License version 2 only, as
118.10 + * published by the Free Software Foundation. Sun designates this
118.11 + * particular file as subject to the "Classpath" exception as provided
118.12 + * by Sun in the LICENSE file that accompanied this code.
118.13 + *
118.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
118.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
118.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
118.17 + * version 2 for more details (a copy is included in the LICENSE file that
118.18 + * accompanied this code).
118.19 + *
118.20 + * You should have received a copy of the GNU General Public License version
118.21 + * 2 along with this work; if not, write to the Free Software Foundation,
118.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
118.23 + *
118.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
118.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
118.26 + * have any questions.
118.27 + */
118.28 +
118.29 +package java.util;
118.30 +
118.31 +/**
118.32 + * This class implements the Dual-Pivot Quicksort algorithm by
118.33 + * Vladimir Yaroslavskiy, Jon Bentley, and Joshua Bloch. The algorithm
118.34 + * offers O(n log(n)) performance on many data sets that cause other
118.35 + * quicksorts to degrade to quadratic performance, and is typically
118.36 + * faster than traditional (one-pivot) Quicksort implementations.
118.37 + *
118.38 + * @author Vladimir Yaroslavskiy
118.39 + * @author Jon Bentley
118.40 + * @author Josh Bloch
118.41 + *
118.42 + * @version 2009.11.16 m765.827.v12a
118.43 + */
118.44 +final class DualPivotQuicksort {
118.45 +
118.46 + /**
118.47 + * Suppresses default constructor.
118.48 + */
118.49 + private DualPivotQuicksort() {}
118.50 +
118.51 + /*
118.52 + * Tuning parameters.
118.53 + */
118.54 +
118.55 + /**
118.56 + * If the length of an array to be sorted is less than this
118.57 + * constant, insertion sort is used in preference to Quicksort.
118.58 + */
118.59 + private static final int INSERTION_SORT_THRESHOLD = 32;
118.60 +
118.61 + /**
118.62 + * If the length of a byte array to be sorted is greater than
118.63 + * this constant, counting sort is used in preference to Quicksort.
118.64 + */
118.65 + private static final int COUNTING_SORT_THRESHOLD_FOR_BYTE = 128;
118.66 +
118.67 + /**
118.68 + * If the length of a short or char array to be sorted is greater
118.69 + * than this constant, counting sort is used in preference to Quicksort.
118.70 + */
118.71 + private static final int COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR = 32768;
118.72 +
118.73 + /*
118.74 + * Sorting methods for 7 primitive types.
118.75 + */
118.76 +
118.77 + /**
118.78 + * Sorts the specified array into ascending numerical order.
118.79 + *
118.80 + * @param a the array to be sorted
118.81 + */
118.82 + public static void sort(int[] a) {
118.83 + doSort(a, 0, a.length - 1);
118.84 + }
118.85 +
118.86 + /**
118.87 + * Sorts the specified range of the array into ascending order. The range
118.88 + * to be sorted extends from the index {@code fromIndex}, inclusive, to
118.89 + * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
118.90 + * the range to be sorted is empty.
118.91 + *
118.92 + * @param a the array to be sorted
118.93 + * @param fromIndex the index of the first element, inclusive, to be sorted
118.94 + * @param toIndex the index of the last element, exclusive, to be sorted
118.95 + * @throws IllegalArgumentException if {@code fromIndex > toIndex}
118.96 + * @throws ArrayIndexOutOfBoundsException
118.97 + * if {@code fromIndex < 0} or {@code toIndex > a.length}
118.98 + */
118.99 + public static void sort(int[] a, int fromIndex, int toIndex) {
118.100 + rangeCheck(a.length, fromIndex, toIndex);
118.101 + doSort(a, fromIndex, toIndex - 1);
118.102 + }
118.103 +
118.104 + /**
118.105 + * Sorts the specified range of the array into ascending order. This
118.106 + * method differs from the public {@code sort} method in that the
118.107 + * {@code right} index is inclusive, and it does no range checking on
118.108 + * {@code left} or {@code right}.
118.109 + *
118.110 + * @param a the array to be sorted
118.111 + * @param left the index of the first element, inclusive, to be sorted
118.112 + * @param right the index of the last element, inclusive, to be sorted
118.113 + */
118.114 + private static void doSort(int[] a, int left, int right) {
118.115 + // Use insertion sort on tiny arrays
118.116 + if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
118.117 + for (int k = left + 1; k <= right; k++) {
118.118 + int ak = a[k];
118.119 + int j;
118.120 + for (j = k - 1; j >= left && ak < a[j]; j--) {
118.121 + a[j + 1] = a[j];
118.122 + }
118.123 + a[j + 1] = ak;
118.124 + }
118.125 + } else { // Use Dual-Pivot Quicksort on large arrays
118.126 + dualPivotQuicksort(a, left, right);
118.127 + }
118.128 + }
118.129 +
118.130 + /**
118.131 + * Sorts the specified range of the array into ascending order by the
118.132 + * Dual-Pivot Quicksort algorithm.
118.133 + *
118.134 + * @param a the array to be sorted
118.135 + * @param left the index of the first element, inclusive, to be sorted
118.136 + * @param right the index of the last element, inclusive, to be sorted
118.137 + */
118.138 + private static void dualPivotQuicksort(int[] a, int left, int right) {
118.139 + // Compute indices of five evenly spaced elements
118.140 + int sixth = (right - left + 1) / 6;
118.141 + int e1 = left + sixth;
118.142 + int e5 = right - sixth;
118.143 + int e3 = (left + right) >>> 1; // The midpoint
118.144 + int e4 = e3 + sixth;
118.145 + int e2 = e3 - sixth;
118.146 +
118.147 + // Sort these elements using a 5-element sorting network
118.148 + int ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
118.149 +
118.150 + if (ae1 > ae2) { int t = ae1; ae1 = ae2; ae2 = t; }
118.151 + if (ae4 > ae5) { int t = ae4; ae4 = ae5; ae5 = t; }
118.152 + if (ae1 > ae3) { int t = ae1; ae1 = ae3; ae3 = t; }
118.153 + if (ae2 > ae3) { int t = ae2; ae2 = ae3; ae3 = t; }
118.154 + if (ae1 > ae4) { int t = ae1; ae1 = ae4; ae4 = t; }
118.155 + if (ae3 > ae4) { int t = ae3; ae3 = ae4; ae4 = t; }
118.156 + if (ae2 > ae5) { int t = ae2; ae2 = ae5; ae5 = t; }
118.157 + if (ae2 > ae3) { int t = ae2; ae2 = ae3; ae3 = t; }
118.158 + if (ae4 > ae5) { int t = ae4; ae4 = ae5; ae5 = t; }
118.159 +
118.160 + a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
118.161 +
118.162 + /*
118.163 + * Use the second and fourth of the five sorted elements as pivots.
118.164 + * These values are inexpensive approximations of the first and
118.165 + * second terciles of the array. Note that pivot1 <= pivot2.
118.166 + *
118.167 + * The pivots are stored in local variables, and the first and
118.168 + * the last of the sorted elements are moved to the locations
118.169 + * formerly occupied by the pivots. When partitioning is complete,
118.170 + * the pivots are swapped back into their final positions, and
118.171 + * excluded from subsequent sorting.
118.172 + */
118.173 + int pivot1 = ae2; a[e2] = a[left];
118.174 + int pivot2 = ae4; a[e4] = a[right];
118.175 +
118.176 + /*
118.177 + * Partitioning
118.178 + *
118.179 + * left part center part right part
118.180 + * ------------------------------------------------------------
118.181 + * [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
118.182 + * ------------------------------------------------------------
118.183 + * ^ ^ ^
118.184 + * | | |
118.185 + * less k great
118.186 + */
118.187 +
118.188 + // Pointers
118.189 + int less = left + 1; // The index of first element of center part
118.190 + int great = right - 1; // The index before first element of right part
118.191 +
118.192 + boolean pivotsDiffer = pivot1 != pivot2;
118.193 +
118.194 + if (pivotsDiffer) {
118.195 + /*
118.196 + * Invariants:
118.197 + * all in (left, less) < pivot1
118.198 + * pivot1 <= all in [less, k) <= pivot2
118.199 + * all in (great, right) > pivot2
118.200 + *
118.201 + * Pointer k is the first index of ?-part
118.202 + */
118.203 + outer:
118.204 + for (int k = less; k <= great; k++) {
118.205 + int ak = a[k];
118.206 + if (ak < pivot1) {
118.207 + if (k > less) {
118.208 + a[k] = a[less];
118.209 + a[less] = ak;
118.210 + }
118.211 + less++;
118.212 + } else if (ak > pivot2) {
118.213 + while (a[great] > pivot2) {
118.214 + if (k == great--) {
118.215 + break outer;
118.216 + }
118.217 + }
118.218 + a[k] = a[great];
118.219 + a[great--] = ak;
118.220 +
118.221 + if ((ak = a[k]) < pivot1) {
118.222 + a[k] = a[less];
118.223 + a[less++] = ak;
118.224 + }
118.225 + }
118.226 + }
118.227 + } else { // Pivots are equal
118.228 + /*
118.229 + * Partition degenerates to the traditional 3-way
118.230 + * (or "Dutch National Flag") partition:
118.231 + *
118.232 + * left part center part right part
118.233 + * -------------------------------------------------
118.234 + * [ < pivot | == pivot | ? | > pivot ]
118.235 + * -------------------------------------------------
118.236 + *
118.237 + * ^ ^ ^
118.238 + * | | |
118.239 + * less k great
118.240 + *
118.241 + * Invariants:
118.242 + *
118.243 + * all in (left, less) < pivot
118.244 + * all in [less, k) == pivot
118.245 + * all in (great, right) > pivot
118.246 + *
118.247 + * Pointer k is the first index of ?-part
118.248 + */
118.249 + outer:
118.250 + for (int k = less; k <= great; k++) {
118.251 + int ak = a[k];
118.252 + if (ak == pivot1) {
118.253 + continue;
118.254 + }
118.255 + if (ak < pivot1) {
118.256 + if (k > less) {
118.257 + a[k] = a[less];
118.258 + a[less] = ak;
118.259 + }
118.260 + less++;
118.261 + } else { // a[k] > pivot
118.262 + while (a[great] > pivot1) {
118.263 + if (k == great--) {
118.264 + break outer;
118.265 + }
118.266 + }
118.267 + a[k] = a[great];
118.268 + a[great--] = ak;
118.269 +
118.270 + if ((ak = a[k]) < pivot1) {
118.271 + a[k] = a[less];
118.272 + a[less++] = ak;
118.273 + }
118.274 + }
118.275 + }
118.276 + }
118.277 +
118.278 + // Swap pivots into their final positions
118.279 + a[left] = a[less - 1]; a[less - 1] = pivot1;
118.280 + a[right] = a[great + 1]; a[great + 1] = pivot2;
118.281 +
118.282 + // Sort left and right parts recursively, excluding known pivot values
118.283 + doSort(a, left, less - 2);
118.284 + doSort(a, great + 2, right);
118.285 +
118.286 + /*
118.287 + * If pivot1 == pivot2, all elements from center
118.288 + * part are equal and, therefore, already sorted
118.289 + */
118.290 + if (!pivotsDiffer) {
118.291 + return;
118.292 + }
118.293 +
118.294 + /*
118.295 + * If center part is too large (comprises > 5/6 of
118.296 + * the array), swap internal pivot values to ends
118.297 + */
118.298 + if (less < e1 && e5 < great) {
118.299 + while (a[less] == pivot1) {
118.300 + less++;
118.301 + }
118.302 + while (a[great] == pivot2) {
118.303 + great--;
118.304 + }
118.305 + for (int k = less + 1; k <= great; ) {
118.306 + int ak = a[k];
118.307 + if (ak == pivot1) {
118.308 + a[k++] = a[less];
118.309 + a[less++] = pivot1;
118.310 + } else if (ak == pivot2) {
118.311 + a[k] = a[great];
118.312 + a[great--] = pivot2;
118.313 + } else {
118.314 + k++;
118.315 + }
118.316 + }
118.317 + }
118.318 +
118.319 + // Sort center part recursively, excluding known pivot values
118.320 + doSort(a, less, great);
118.321 + }
118.322 +
118.323 + /**
118.324 + * Sorts the specified array into ascending numerical order.
118.325 + *
118.326 + * @param a the array to be sorted
118.327 + */
118.328 + public static void sort(long[] a) {
118.329 + doSort(a, 0, a.length - 1);
118.330 + }
118.331 +
118.332 + /**
118.333 + * Sorts the specified range of the array into ascending order. The range
118.334 + * to be sorted extends from the index {@code fromIndex}, inclusive, to
118.335 + * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
118.336 + * the range to be sorted is empty.
118.337 + *
118.338 + * @param a the array to be sorted
118.339 + * @param fromIndex the index of the first element, inclusive, to be sorted
118.340 + * @param toIndex the index of the last element, exclusive, to be sorted
118.341 + * @throws IllegalArgumentException if {@code fromIndex > toIndex}
118.342 + * @throws ArrayIndexOutOfBoundsException
118.343 + * if {@code fromIndex < 0} or {@code toIndex > a.length}
118.344 + */
118.345 + public static void sort(long[] a, int fromIndex, int toIndex) {
118.346 + rangeCheck(a.length, fromIndex, toIndex);
118.347 + doSort(a, fromIndex, toIndex - 1);
118.348 + }
118.349 +
118.350 + /**
118.351 + * Sorts the specified range of the array into ascending order. This
118.352 + * method differs from the public {@code sort} method in that the
118.353 + * {@code right} index is inclusive, and it does no range checking on
118.354 + * {@code left} or {@code right}.
118.355 + *
118.356 + * @param a the array to be sorted
118.357 + * @param left the index of the first element, inclusive, to be sorted
118.358 + * @param right the index of the last element, inclusive, to be sorted
118.359 + */
118.360 + private static void doSort(long[] a, int left, int right) {
118.361 + // Use insertion sort on tiny arrays
118.362 + if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
118.363 + for (int k = left + 1; k <= right; k++) {
118.364 + long ak = a[k];
118.365 + int j;
118.366 + for (j = k - 1; j >= left && ak < a[j]; j--) {
118.367 + a[j + 1] = a[j];
118.368 + }
118.369 + a[j + 1] = ak;
118.370 + }
118.371 + } else { // Use Dual-Pivot Quicksort on large arrays
118.372 + dualPivotQuicksort(a, left, right);
118.373 + }
118.374 + }
118.375 +
118.376 + /**
118.377 + * Sorts the specified range of the array into ascending order by the
118.378 + * Dual-Pivot Quicksort algorithm.
118.379 + *
118.380 + * @param a the array to be sorted
118.381 + * @param left the index of the first element, inclusive, to be sorted
118.382 + * @param right the index of the last element, inclusive, to be sorted
118.383 + */
118.384 + private static void dualPivotQuicksort(long[] a, int left, int right) {
118.385 + // Compute indices of five evenly spaced elements
118.386 + int sixth = (right - left + 1) / 6;
118.387 + int e1 = left + sixth;
118.388 + int e5 = right - sixth;
118.389 + int e3 = (left + right) >>> 1; // The midpoint
118.390 + int e4 = e3 + sixth;
118.391 + int e2 = e3 - sixth;
118.392 +
118.393 + // Sort these elements using a 5-element sorting network
118.394 + long ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
118.395 +
118.396 + if (ae1 > ae2) { long t = ae1; ae1 = ae2; ae2 = t; }
118.397 + if (ae4 > ae5) { long t = ae4; ae4 = ae5; ae5 = t; }
118.398 + if (ae1 > ae3) { long t = ae1; ae1 = ae3; ae3 = t; }
118.399 + if (ae2 > ae3) { long t = ae2; ae2 = ae3; ae3 = t; }
118.400 + if (ae1 > ae4) { long t = ae1; ae1 = ae4; ae4 = t; }
118.401 + if (ae3 > ae4) { long t = ae3; ae3 = ae4; ae4 = t; }
118.402 + if (ae2 > ae5) { long t = ae2; ae2 = ae5; ae5 = t; }
118.403 + if (ae2 > ae3) { long t = ae2; ae2 = ae3; ae3 = t; }
118.404 + if (ae4 > ae5) { long t = ae4; ae4 = ae5; ae5 = t; }
118.405 +
118.406 + a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
118.407 +
118.408 + /*
118.409 + * Use the second and fourth of the five sorted elements as pivots.
118.410 + * These values are inexpensive approximations of the first and
118.411 + * second terciles of the array. Note that pivot1 <= pivot2.
118.412 + *
118.413 + * The pivots are stored in local variables, and the first and
118.414 + * the last of the sorted elements are moved to the locations
118.415 + * formerly occupied by the pivots. When partitioning is complete,
118.416 + * the pivots are swapped back into their final positions, and
118.417 + * excluded from subsequent sorting.
118.418 + */
118.419 + long pivot1 = ae2; a[e2] = a[left];
118.420 + long pivot2 = ae4; a[e4] = a[right];
118.421 +
118.422 + /*
118.423 + * Partitioning
118.424 + *
118.425 + * left part center part right part
118.426 + * ------------------------------------------------------------
118.427 + * [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
118.428 + * ------------------------------------------------------------
118.429 + * ^ ^ ^
118.430 + * | | |
118.431 + * less k great
118.432 + */
118.433 +
118.434 + // Pointers
118.435 + int less = left + 1; // The index of first element of center part
118.436 + int great = right - 1; // The index before first element of right part
118.437 +
118.438 + boolean pivotsDiffer = pivot1 != pivot2;
118.439 +
118.440 + if (pivotsDiffer) {
118.441 + /*
118.442 + * Invariants:
118.443 + * all in (left, less) < pivot1
118.444 + * pivot1 <= all in [less, k) <= pivot2
118.445 + * all in (great, right) > pivot2
118.446 + *
118.447 + * Pointer k is the first index of ?-part
118.448 + */
118.449 + outer:
118.450 + for (int k = less; k <= great; k++) {
118.451 + long ak = a[k];
118.452 + if (ak < pivot1) {
118.453 + if (k > less) {
118.454 + a[k] = a[less];
118.455 + a[less] = ak;
118.456 + }
118.457 + less++;
118.458 + } else if (ak > pivot2) {
118.459 + while (a[great] > pivot2) {
118.460 + if (k == great--) {
118.461 + break outer;
118.462 + }
118.463 + }
118.464 + a[k] = a[great];
118.465 + a[great--] = ak;
118.466 +
118.467 + if ((ak = a[k]) < pivot1) {
118.468 + a[k] = a[less];
118.469 + a[less++] = ak;
118.470 + }
118.471 + }
118.472 + }
118.473 + } else { // Pivots are equal
118.474 + /*
118.475 + * Partition degenerates to the traditional 3-way
118.476 + * (or "Dutch National Flag") partition:
118.477 + *
118.478 + * left part center part right part
118.479 + * -------------------------------------------------
118.480 + * [ < pivot | == pivot | ? | > pivot ]
118.481 + * -------------------------------------------------
118.482 + *
118.483 + * ^ ^ ^
118.484 + * | | |
118.485 + * less k great
118.486 + *
118.487 + * Invariants:
118.488 + *
118.489 + * all in (left, less) < pivot
118.490 + * all in [less, k) == pivot
118.491 + * all in (great, right) > pivot
118.492 + *
118.493 + * Pointer k is the first index of ?-part
118.494 + */
118.495 + outer:
118.496 + for (int k = less; k <= great; k++) {
118.497 + long ak = a[k];
118.498 + if (ak == pivot1) {
118.499 + continue;
118.500 + }
118.501 + if (ak < pivot1) {
118.502 + if (k > less) {
118.503 + a[k] = a[less];
118.504 + a[less] = ak;
118.505 + }
118.506 + less++;
118.507 + } else { // a[k] > pivot
118.508 + while (a[great] > pivot1) {
118.509 + if (k == great--) {
118.510 + break outer;
118.511 + }
118.512 + }
118.513 + a[k] = a[great];
118.514 + a[great--] = ak;
118.515 +
118.516 + if ((ak = a[k]) < pivot1) {
118.517 + a[k] = a[less];
118.518 + a[less++] = ak;
118.519 + }
118.520 + }
118.521 + }
118.522 + }
118.523 +
118.524 + // Swap pivots into their final positions
118.525 + a[left] = a[less - 1]; a[less - 1] = pivot1;
118.526 + a[right] = a[great + 1]; a[great + 1] = pivot2;
118.527 +
118.528 + // Sort left and right parts recursively, excluding known pivot values
118.529 + doSort(a, left, less - 2);
118.530 + doSort(a, great + 2, right);
118.531 +
118.532 + /*
118.533 + * If pivot1 == pivot2, all elements from center
118.534 + * part are equal and, therefore, already sorted
118.535 + */
118.536 + if (!pivotsDiffer) {
118.537 + return;
118.538 + }
118.539 +
118.540 + /*
118.541 + * If center part is too large (comprises > 5/6 of
118.542 + * the array), swap internal pivot values to ends
118.543 + */
118.544 + if (less < e1 && e5 < great) {
118.545 + while (a[less] == pivot1) {
118.546 + less++;
118.547 + }
118.548 + while (a[great] == pivot2) {
118.549 + great--;
118.550 + }
118.551 + for (int k = less + 1; k <= great; ) {
118.552 + long ak = a[k];
118.553 + if (ak == pivot1) {
118.554 + a[k++] = a[less];
118.555 + a[less++] = pivot1;
118.556 + } else if (ak == pivot2) {
118.557 + a[k] = a[great];
118.558 + a[great--] = pivot2;
118.559 + } else {
118.560 + k++;
118.561 + }
118.562 + }
118.563 + }
118.564 +
118.565 + // Sort center part recursively, excluding known pivot values
118.566 + doSort(a, less, great);
118.567 + }
118.568 +
118.569 + /**
118.570 + * Sorts the specified array into ascending numerical order.
118.571 + *
118.572 + * @param a the array to be sorted
118.573 + */
118.574 + public static void sort(short[] a) {
118.575 + doSort(a, 0, a.length - 1);
118.576 + }
118.577 +
118.578 + /**
118.579 + * Sorts the specified range of the array into ascending order. The range
118.580 + * to be sorted extends from the index {@code fromIndex}, inclusive, to
118.581 + * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
118.582 + * the range to be sorted is empty.
118.583 + *
118.584 + * @param a the array to be sorted
118.585 + * @param fromIndex the index of the first element, inclusive, to be sorted
118.586 + * @param toIndex the index of the last element, exclusive, to be sorted
118.587 + * @throws IllegalArgumentException if {@code fromIndex > toIndex}
118.588 + * @throws ArrayIndexOutOfBoundsException
118.589 + * if {@code fromIndex < 0} or {@code toIndex > a.length}
118.590 + */
118.591 + public static void sort(short[] a, int fromIndex, int toIndex) {
118.592 + rangeCheck(a.length, fromIndex, toIndex);
118.593 + doSort(a, fromIndex, toIndex - 1);
118.594 + }
118.595 +
118.596 + /** The number of distinct short values. */
118.597 + private static final int NUM_SHORT_VALUES = 1 << 16;
118.598 +
118.599 + /**
118.600 + * Sorts the specified range of the array into ascending order. This
118.601 + * method differs from the public {@code sort} method in that the
118.602 + * {@code right} index is inclusive, and it does no range checking on
118.603 + * {@code left} or {@code right}.
118.604 + *
118.605 + * @param a the array to be sorted
118.606 + * @param left the index of the first element, inclusive, to be sorted
118.607 + * @param right the index of the last element, inclusive, to be sorted
118.608 + */
118.609 + private static void doSort(short[] a, int left, int right) {
118.610 + // Use insertion sort on tiny arrays
118.611 + if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
118.612 + for (int k = left + 1; k <= right; k++) {
118.613 + short ak = a[k];
118.614 + int j;
118.615 + for (j = k - 1; j >= left && ak < a[j]; j--) {
118.616 + a[j + 1] = a[j];
118.617 + }
118.618 + a[j + 1] = ak;
118.619 + }
118.620 + } else if (right-left+1 > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
118.621 + // Use counting sort on huge arrays
118.622 + int[] count = new int[NUM_SHORT_VALUES];
118.623 +
118.624 + for (int i = left; i <= right; i++) {
118.625 + count[a[i] - Short.MIN_VALUE]++;
118.626 + }
118.627 + for (int i = 0, k = left; i < count.length && k <= right; i++) {
118.628 + short value = (short) (i + Short.MIN_VALUE);
118.629 +
118.630 + for (int s = count[i]; s > 0; s--) {
118.631 + a[k++] = value;
118.632 + }
118.633 + }
118.634 + } else { // Use Dual-Pivot Quicksort on large arrays
118.635 + dualPivotQuicksort(a, left, right);
118.636 + }
118.637 + }
118.638 +
118.639 + /**
118.640 + * Sorts the specified range of the array into ascending order by the
118.641 + * Dual-Pivot Quicksort algorithm.
118.642 + *
118.643 + * @param a the array to be sorted
118.644 + * @param left the index of the first element, inclusive, to be sorted
118.645 + * @param right the index of the last element, inclusive, to be sorted
118.646 + */
118.647 + private static void dualPivotQuicksort(short[] a, int left, int right) {
118.648 + // Compute indices of five evenly spaced elements
118.649 + int sixth = (right - left + 1) / 6;
118.650 + int e1 = left + sixth;
118.651 + int e5 = right - sixth;
118.652 + int e3 = (left + right) >>> 1; // The midpoint
118.653 + int e4 = e3 + sixth;
118.654 + int e2 = e3 - sixth;
118.655 +
118.656 + // Sort these elements using a 5-element sorting network
118.657 + short ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
118.658 +
118.659 + if (ae1 > ae2) { short t = ae1; ae1 = ae2; ae2 = t; }
118.660 + if (ae4 > ae5) { short t = ae4; ae4 = ae5; ae5 = t; }
118.661 + if (ae1 > ae3) { short t = ae1; ae1 = ae3; ae3 = t; }
118.662 + if (ae2 > ae3) { short t = ae2; ae2 = ae3; ae3 = t; }
118.663 + if (ae1 > ae4) { short t = ae1; ae1 = ae4; ae4 = t; }
118.664 + if (ae3 > ae4) { short t = ae3; ae3 = ae4; ae4 = t; }
118.665 + if (ae2 > ae5) { short t = ae2; ae2 = ae5; ae5 = t; }
118.666 + if (ae2 > ae3) { short t = ae2; ae2 = ae3; ae3 = t; }
118.667 + if (ae4 > ae5) { short t = ae4; ae4 = ae5; ae5 = t; }
118.668 +
118.669 + a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
118.670 +
118.671 + /*
118.672 + * Use the second and fourth of the five sorted elements as pivots.
118.673 + * These values are inexpensive approximations of the first and
118.674 + * second terciles of the array. Note that pivot1 <= pivot2.
118.675 + *
118.676 + * The pivots are stored in local variables, and the first and
118.677 + * the last of the sorted elements are moved to the locations
118.678 + * formerly occupied by the pivots. When partitioning is complete,
118.679 + * the pivots are swapped back into their final positions, and
118.680 + * excluded from subsequent sorting.
118.681 + */
118.682 + short pivot1 = ae2; a[e2] = a[left];
118.683 + short pivot2 = ae4; a[e4] = a[right];
118.684 +
118.685 + /*
118.686 + * Partitioning
118.687 + *
118.688 + * left part center part right part
118.689 + * ------------------------------------------------------------
118.690 + * [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
118.691 + * ------------------------------------------------------------
118.692 + * ^ ^ ^
118.693 + * | | |
118.694 + * less k great
118.695 + */
118.696 +
118.697 + // Pointers
118.698 + int less = left + 1; // The index of first element of center part
118.699 + int great = right - 1; // The index before first element of right part
118.700 +
118.701 + boolean pivotsDiffer = pivot1 != pivot2;
118.702 +
118.703 + if (pivotsDiffer) {
118.704 + /*
118.705 + * Invariants:
118.706 + * all in (left, less) < pivot1
118.707 + * pivot1 <= all in [less, k) <= pivot2
118.708 + * all in (great, right) > pivot2
118.709 + *
118.710 + * Pointer k is the first index of ?-part
118.711 + */
118.712 + outer:
118.713 + for (int k = less; k <= great; k++) {
118.714 + short ak = a[k];
118.715 + if (ak < pivot1) {
118.716 + if (k > less) {
118.717 + a[k] = a[less];
118.718 + a[less] = ak;
118.719 + }
118.720 + less++;
118.721 + } else if (ak > pivot2) {
118.722 + while (a[great] > pivot2) {
118.723 + if (k == great--) {
118.724 + break outer;
118.725 + }
118.726 + }
118.727 + a[k] = a[great];
118.728 + a[great--] = ak;
118.729 +
118.730 + if ((ak = a[k]) < pivot1) {
118.731 + a[k] = a[less];
118.732 + a[less++] = ak;
118.733 + }
118.734 + }
118.735 + }
118.736 + } else { // Pivots are equal
118.737 + /*
118.738 + * Partition degenerates to the traditional 3-way
118.739 + * (or "Dutch National Flag") partition:
118.740 + *
118.741 + * left part center part right part
118.742 + * -------------------------------------------------
118.743 + * [ < pivot | == pivot | ? | > pivot ]
118.744 + * -------------------------------------------------
118.745 + *
118.746 + * ^ ^ ^
118.747 + * | | |
118.748 + * less k great
118.749 + *
118.750 + * Invariants:
118.751 + *
118.752 + * all in (left, less) < pivot
118.753 + * all in [less, k) == pivot
118.754 + * all in (great, right) > pivot
118.755 + *
118.756 + * Pointer k is the first index of ?-part
118.757 + */
118.758 + outer:
118.759 + for (int k = less; k <= great; k++) {
118.760 + short ak = a[k];
118.761 + if (ak == pivot1) {
118.762 + continue;
118.763 + }
118.764 + if (ak < pivot1) {
118.765 + if (k > less) {
118.766 + a[k] = a[less];
118.767 + a[less] = ak;
118.768 + }
118.769 + less++;
118.770 + } else { // a[k] > pivot
118.771 + while (a[great] > pivot1) {
118.772 + if (k == great--) {
118.773 + break outer;
118.774 + }
118.775 + }
118.776 + a[k] = a[great];
118.777 + a[great--] = ak;
118.778 +
118.779 + if ((ak = a[k]) < pivot1) {
118.780 + a[k] = a[less];
118.781 + a[less++] = ak;
118.782 + }
118.783 + }
118.784 + }
118.785 + }
118.786 +
118.787 + // Swap pivots into their final positions
118.788 + a[left] = a[less - 1]; a[less - 1] = pivot1;
118.789 + a[right] = a[great + 1]; a[great + 1] = pivot2;
118.790 +
118.791 + // Sort left and right parts recursively, excluding known pivot values
118.792 + doSort(a, left, less - 2);
118.793 + doSort(a, great + 2, right);
118.794 +
118.795 + /*
118.796 + * If pivot1 == pivot2, all elements from center
118.797 + * part are equal and, therefore, already sorted
118.798 + */
118.799 + if (!pivotsDiffer) {
118.800 + return;
118.801 + }
118.802 +
118.803 + /*
118.804 + * If center part is too large (comprises > 5/6 of
118.805 + * the array), swap internal pivot values to ends
118.806 + */
118.807 + if (less < e1 && e5 < great) {
118.808 + while (a[less] == pivot1) {
118.809 + less++;
118.810 + }
118.811 + while (a[great] == pivot2) {
118.812 + great--;
118.813 + }
118.814 + for (int k = less + 1; k <= great; ) {
118.815 + short ak = a[k];
118.816 + if (ak == pivot1) {
118.817 + a[k++] = a[less];
118.818 + a[less++] = pivot1;
118.819 + } else if (ak == pivot2) {
118.820 + a[k] = a[great];
118.821 + a[great--] = pivot2;
118.822 + } else {
118.823 + k++;
118.824 + }
118.825 + }
118.826 + }
118.827 +
118.828 + // Sort center part recursively, excluding known pivot values
118.829 + doSort(a, less, great);
118.830 + }
118.831 +
118.832 + /**
118.833 + * Sorts the specified array into ascending numerical order.
118.834 + *
118.835 + * @param a the array to be sorted
118.836 + */
118.837 + public static void sort(char[] a) {
118.838 + doSort(a, 0, a.length - 1);
118.839 + }
118.840 +
118.841 + /**
118.842 + * Sorts the specified range of the array into ascending order. The range
118.843 + * to be sorted extends from the index {@code fromIndex}, inclusive, to
118.844 + * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
118.845 + * the range to be sorted is empty.
118.846 + *
118.847 + * @param a the array to be sorted
118.848 + * @param fromIndex the index of the first element, inclusive, to be sorted
118.849 + * @param toIndex the index of the last element, exclusive, to be sorted
118.850 + * @throws IllegalArgumentException if {@code fromIndex > toIndex}
118.851 + * @throws ArrayIndexOutOfBoundsException
118.852 + * if {@code fromIndex < 0} or {@code toIndex > a.length}
118.853 + */
118.854 + public static void sort(char[] a, int fromIndex, int toIndex) {
118.855 + rangeCheck(a.length, fromIndex, toIndex);
118.856 + doSort(a, fromIndex, toIndex - 1);
118.857 + }
118.858 +
118.859 + /** The number of distinct char values. */
118.860 + private static final int NUM_CHAR_VALUES = 1 << 16;
118.861 +
118.862 + /**
118.863 + * Sorts the specified range of the array into ascending order. This
118.864 + * method differs from the public {@code sort} method in that the
118.865 + * {@code right} index is inclusive, and it does no range checking on
118.866 + * {@code left} or {@code right}.
118.867 + *
118.868 + * @param a the array to be sorted
118.869 + * @param left the index of the first element, inclusive, to be sorted
118.870 + * @param right the index of the last element, inclusive, to be sorted
118.871 + */
118.872 + private static void doSort(char[] a, int left, int right) {
118.873 + // Use insertion sort on tiny arrays
118.874 + if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
118.875 + for (int k = left + 1; k <= right; k++) {
118.876 + char ak = a[k];
118.877 + int j;
118.878 + for (j = k - 1; j >= left && ak < a[j]; j--) {
118.879 + a[j + 1] = a[j];
118.880 + }
118.881 + a[j + 1] = ak;
118.882 + }
118.883 + } else if (right-left+1 > COUNTING_SORT_THRESHOLD_FOR_SHORT_OR_CHAR) {
118.884 + // Use counting sort on huge arrays
118.885 + int[] count = new int[NUM_CHAR_VALUES];
118.886 +
118.887 + for (int i = left; i <= right; i++) {
118.888 + count[a[i]]++;
118.889 + }
118.890 + for (int i = 0, k = left; i < count.length && k <= right; i++) {
118.891 + for (int s = count[i]; s > 0; s--) {
118.892 + a[k++] = (char) i;
118.893 + }
118.894 + }
118.895 + } else { // Use Dual-Pivot Quicksort on large arrays
118.896 + dualPivotQuicksort(a, left, right);
118.897 + }
118.898 + }
118.899 +
118.900 + /**
118.901 + * Sorts the specified range of the array into ascending order by the
118.902 + * Dual-Pivot Quicksort algorithm.
118.903 + *
118.904 + * @param a the array to be sorted
118.905 + * @param left the index of the first element, inclusive, to be sorted
118.906 + * @param right the index of the last element, inclusive, to be sorted
118.907 + */
118.908 + private static void dualPivotQuicksort(char[] a, int left, int right) {
118.909 + // Compute indices of five evenly spaced elements
118.910 + int sixth = (right - left + 1) / 6;
118.911 + int e1 = left + sixth;
118.912 + int e5 = right - sixth;
118.913 + int e3 = (left + right) >>> 1; // The midpoint
118.914 + int e4 = e3 + sixth;
118.915 + int e2 = e3 - sixth;
118.916 +
118.917 + // Sort these elements using a 5-element sorting network
118.918 + char ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
118.919 +
118.920 + if (ae1 > ae2) { char t = ae1; ae1 = ae2; ae2 = t; }
118.921 + if (ae4 > ae5) { char t = ae4; ae4 = ae5; ae5 = t; }
118.922 + if (ae1 > ae3) { char t = ae1; ae1 = ae3; ae3 = t; }
118.923 + if (ae2 > ae3) { char t = ae2; ae2 = ae3; ae3 = t; }
118.924 + if (ae1 > ae4) { char t = ae1; ae1 = ae4; ae4 = t; }
118.925 + if (ae3 > ae4) { char t = ae3; ae3 = ae4; ae4 = t; }
118.926 + if (ae2 > ae5) { char t = ae2; ae2 = ae5; ae5 = t; }
118.927 + if (ae2 > ae3) { char t = ae2; ae2 = ae3; ae3 = t; }
118.928 + if (ae4 > ae5) { char t = ae4; ae4 = ae5; ae5 = t; }
118.929 +
118.930 + a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
118.931 +
118.932 + /*
118.933 + * Use the second and fourth of the five sorted elements as pivots.
118.934 + * These values are inexpensive approximations of the first and
118.935 + * second terciles of the array. Note that pivot1 <= pivot2.
118.936 + *
118.937 + * The pivots are stored in local variables, and the first and
118.938 + * the last of the sorted elements are moved to the locations
118.939 + * formerly occupied by the pivots. When partitioning is complete,
118.940 + * the pivots are swapped back into their final positions, and
118.941 + * excluded from subsequent sorting.
118.942 + */
118.943 + char pivot1 = ae2; a[e2] = a[left];
118.944 + char pivot2 = ae4; a[e4] = a[right];
118.945 +
118.946 + /*
118.947 + * Partitioning
118.948 + *
118.949 + * left part center part right part
118.950 + * ------------------------------------------------------------
118.951 + * [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
118.952 + * ------------------------------------------------------------
118.953 + * ^ ^ ^
118.954 + * | | |
118.955 + * less k great
118.956 + */
118.957 +
118.958 + // Pointers
118.959 + int less = left + 1; // The index of first element of center part
118.960 + int great = right - 1; // The index before first element of right part
118.961 +
118.962 + boolean pivotsDiffer = pivot1 != pivot2;
118.963 +
118.964 + if (pivotsDiffer) {
118.965 + /*
118.966 + * Invariants:
118.967 + * all in (left, less) < pivot1
118.968 + * pivot1 <= all in [less, k) <= pivot2
118.969 + * all in (great, right) > pivot2
118.970 + *
118.971 + * Pointer k is the first index of ?-part
118.972 + */
118.973 + outer:
118.974 + for (int k = less; k <= great; k++) {
118.975 + char ak = a[k];
118.976 + if (ak < pivot1) {
118.977 + if (k > less) {
118.978 + a[k] = a[less];
118.979 + a[less] = ak;
118.980 + }
118.981 + less++;
118.982 + } else if (ak > pivot2) {
118.983 + while (a[great] > pivot2) {
118.984 + if (k == great--) {
118.985 + break outer;
118.986 + }
118.987 + }
118.988 + a[k] = a[great];
118.989 + a[great--] = ak;
118.990 +
118.991 + if ((ak = a[k]) < pivot1) {
118.992 + a[k] = a[less];
118.993 + a[less++] = ak;
118.994 + }
118.995 + }
118.996 + }
118.997 + } else { // Pivots are equal
118.998 + /*
118.999 + * Partition degenerates to the traditional 3-way
118.1000 + * (or "Dutch National Flag") partition:
118.1001 + *
118.1002 + * left part center part right part
118.1003 + * -------------------------------------------------
118.1004 + * [ < pivot | == pivot | ? | > pivot ]
118.1005 + * -------------------------------------------------
118.1006 + *
118.1007 + * ^ ^ ^
118.1008 + * | | |
118.1009 + * less k great
118.1010 + *
118.1011 + * Invariants:
118.1012 + *
118.1013 + * all in (left, less) < pivot
118.1014 + * all in [less, k) == pivot
118.1015 + * all in (great, right) > pivot
118.1016 + *
118.1017 + * Pointer k is the first index of ?-part
118.1018 + */
118.1019 + outer:
118.1020 + for (int k = less; k <= great; k++) {
118.1021 + char ak = a[k];
118.1022 + if (ak == pivot1) {
118.1023 + continue;
118.1024 + }
118.1025 + if (ak < pivot1) {
118.1026 + if (k > less) {
118.1027 + a[k] = a[less];
118.1028 + a[less] = ak;
118.1029 + }
118.1030 + less++;
118.1031 + } else { // a[k] > pivot
118.1032 + while (a[great] > pivot1) {
118.1033 + if (k == great--) {
118.1034 + break outer;
118.1035 + }
118.1036 + }
118.1037 + a[k] = a[great];
118.1038 + a[great--] = ak;
118.1039 +
118.1040 + if ((ak = a[k]) < pivot1) {
118.1041 + a[k] = a[less];
118.1042 + a[less++] = ak;
118.1043 + }
118.1044 + }
118.1045 + }
118.1046 + }
118.1047 +
118.1048 + // Swap pivots into their final positions
118.1049 + a[left] = a[less - 1]; a[less - 1] = pivot1;
118.1050 + a[right] = a[great + 1]; a[great + 1] = pivot2;
118.1051 +
118.1052 + // Sort left and right parts recursively, excluding known pivot values
118.1053 + doSort(a, left, less - 2);
118.1054 + doSort(a, great + 2, right);
118.1055 +
118.1056 + /*
118.1057 + * If pivot1 == pivot2, all elements from center
118.1058 + * part are equal and, therefore, already sorted
118.1059 + */
118.1060 + if (!pivotsDiffer) {
118.1061 + return;
118.1062 + }
118.1063 +
118.1064 + /*
118.1065 + * If center part is too large (comprises > 5/6 of
118.1066 + * the array), swap internal pivot values to ends
118.1067 + */
118.1068 + if (less < e1 && e5 < great) {
118.1069 + while (a[less] == pivot1) {
118.1070 + less++;
118.1071 + }
118.1072 + while (a[great] == pivot2) {
118.1073 + great--;
118.1074 + }
118.1075 + for (int k = less + 1; k <= great; ) {
118.1076 + char ak = a[k];
118.1077 + if (ak == pivot1) {
118.1078 + a[k++] = a[less];
118.1079 + a[less++] = pivot1;
118.1080 + } else if (ak == pivot2) {
118.1081 + a[k] = a[great];
118.1082 + a[great--] = pivot2;
118.1083 + } else {
118.1084 + k++;
118.1085 + }
118.1086 + }
118.1087 + }
118.1088 +
118.1089 + // Sort center part recursively, excluding known pivot values
118.1090 + doSort(a, less, great);
118.1091 + }
118.1092 +
118.1093 + /**
118.1094 + * Sorts the specified array into ascending numerical order.
118.1095 + *
118.1096 + * @param a the array to be sorted
118.1097 + */
118.1098 + public static void sort(byte[] a) {
118.1099 + doSort(a, 0, a.length - 1);
118.1100 + }
118.1101 +
118.1102 + /**
118.1103 + * Sorts the specified range of the array into ascending order. The range
118.1104 + * to be sorted extends from the index {@code fromIndex}, inclusive, to
118.1105 + * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
118.1106 + * the range to be sorted is empty.
118.1107 + *
118.1108 + * @param a the array to be sorted
118.1109 + * @param fromIndex the index of the first element, inclusive, to be sorted
118.1110 + * @param toIndex the index of the last element, exclusive, to be sorted
118.1111 + * @throws IllegalArgumentException if {@code fromIndex > toIndex}
118.1112 + * @throws ArrayIndexOutOfBoundsException
118.1113 + * if {@code fromIndex < 0} or {@code toIndex > a.length}
118.1114 + */
118.1115 + public static void sort(byte[] a, int fromIndex, int toIndex) {
118.1116 + rangeCheck(a.length, fromIndex, toIndex);
118.1117 + doSort(a, fromIndex, toIndex - 1);
118.1118 + }
118.1119 +
118.1120 + /** The number of distinct byte values. */
118.1121 + private static final int NUM_BYTE_VALUES = 1 << 8;
118.1122 +
118.1123 + /**
118.1124 + * Sorts the specified range of the array into ascending order. This
118.1125 + * method differs from the public {@code sort} method in that the
118.1126 + * {@code right} index is inclusive, and it does no range checking on
118.1127 + * {@code left} or {@code right}.
118.1128 + *
118.1129 + * @param a the array to be sorted
118.1130 + * @param left the index of the first element, inclusive, to be sorted
118.1131 + * @param right the index of the last element, inclusive, to be sorted
118.1132 + */
118.1133 + private static void doSort(byte[] a, int left, int right) {
118.1134 + // Use insertion sort on tiny arrays
118.1135 + if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
118.1136 + for (int k = left + 1; k <= right; k++) {
118.1137 + byte ak = a[k];
118.1138 + int j;
118.1139 + for (j = k - 1; j >= left && ak < a[j]; j--) {
118.1140 + a[j + 1] = a[j];
118.1141 + }
118.1142 + a[j + 1] = ak;
118.1143 + }
118.1144 + } else if (right - left + 1 > COUNTING_SORT_THRESHOLD_FOR_BYTE) {
118.1145 + // Use counting sort on huge arrays
118.1146 + int[] count = new int[NUM_BYTE_VALUES];
118.1147 +
118.1148 + for (int i = left; i <= right; i++) {
118.1149 + count[a[i] - Byte.MIN_VALUE]++;
118.1150 + }
118.1151 + for (int i = 0, k = left; i < count.length && k <= right; i++) {
118.1152 + byte value = (byte) (i + Byte.MIN_VALUE);
118.1153 +
118.1154 + for (int s = count[i]; s > 0; s--) {
118.1155 + a[k++] = value;
118.1156 + }
118.1157 + }
118.1158 + } else { // Use Dual-Pivot Quicksort on large arrays
118.1159 + dualPivotQuicksort(a, left, right);
118.1160 + }
118.1161 + }
118.1162 +
118.1163 + /**
118.1164 + * Sorts the specified range of the array into ascending order by the
118.1165 + * Dual-Pivot Quicksort algorithm.
118.1166 + *
118.1167 + * @param a the array to be sorted
118.1168 + * @param left the index of the first element, inclusive, to be sorted
118.1169 + * @param right the index of the last element, inclusive, to be sorted
118.1170 + */
118.1171 + private static void dualPivotQuicksort(byte[] a, int left, int right) {
118.1172 + // Compute indices of five evenly spaced elements
118.1173 + int sixth = (right - left + 1) / 6;
118.1174 + int e1 = left + sixth;
118.1175 + int e5 = right - sixth;
118.1176 + int e3 = (left + right) >>> 1; // The midpoint
118.1177 + int e4 = e3 + sixth;
118.1178 + int e2 = e3 - sixth;
118.1179 +
118.1180 + // Sort these elements using a 5-element sorting network
118.1181 + byte ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
118.1182 +
118.1183 + if (ae1 > ae2) { byte t = ae1; ae1 = ae2; ae2 = t; }
118.1184 + if (ae4 > ae5) { byte t = ae4; ae4 = ae5; ae5 = t; }
118.1185 + if (ae1 > ae3) { byte t = ae1; ae1 = ae3; ae3 = t; }
118.1186 + if (ae2 > ae3) { byte t = ae2; ae2 = ae3; ae3 = t; }
118.1187 + if (ae1 > ae4) { byte t = ae1; ae1 = ae4; ae4 = t; }
118.1188 + if (ae3 > ae4) { byte t = ae3; ae3 = ae4; ae4 = t; }
118.1189 + if (ae2 > ae5) { byte t = ae2; ae2 = ae5; ae5 = t; }
118.1190 + if (ae2 > ae3) { byte t = ae2; ae2 = ae3; ae3 = t; }
118.1191 + if (ae4 > ae5) { byte t = ae4; ae4 = ae5; ae5 = t; }
118.1192 +
118.1193 + a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
118.1194 +
118.1195 + /*
118.1196 + * Use the second and fourth of the five sorted elements as pivots.
118.1197 + * These values are inexpensive approximations of the first and
118.1198 + * second terciles of the array. Note that pivot1 <= pivot2.
118.1199 + *
118.1200 + * The pivots are stored in local variables, and the first and
118.1201 + * the last of the sorted elements are moved to the locations
118.1202 + * formerly occupied by the pivots. When partitioning is complete,
118.1203 + * the pivots are swapped back into their final positions, and
118.1204 + * excluded from subsequent sorting.
118.1205 + */
118.1206 + byte pivot1 = ae2; a[e2] = a[left];
118.1207 + byte pivot2 = ae4; a[e4] = a[right];
118.1208 +
118.1209 + /*
118.1210 + * Partitioning
118.1211 + *
118.1212 + * left part center part right part
118.1213 + * ------------------------------------------------------------
118.1214 + * [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
118.1215 + * ------------------------------------------------------------
118.1216 + * ^ ^ ^
118.1217 + * | | |
118.1218 + * less k great
118.1219 + */
118.1220 +
118.1221 + // Pointers
118.1222 + int less = left + 1; // The index of first element of center part
118.1223 + int great = right - 1; // The index before first element of right part
118.1224 +
118.1225 + boolean pivotsDiffer = pivot1 != pivot2;
118.1226 +
118.1227 + if (pivotsDiffer) {
118.1228 + /*
118.1229 + * Invariants:
118.1230 + * all in (left, less) < pivot1
118.1231 + * pivot1 <= all in [less, k) <= pivot2
118.1232 + * all in (great, right) > pivot2
118.1233 + *
118.1234 + * Pointer k is the first index of ?-part
118.1235 + */
118.1236 + outer:
118.1237 + for (int k = less; k <= great; k++) {
118.1238 + byte ak = a[k];
118.1239 + if (ak < pivot1) {
118.1240 + if (k > less) {
118.1241 + a[k] = a[less];
118.1242 + a[less] = ak;
118.1243 + }
118.1244 + less++;
118.1245 + } else if (ak > pivot2) {
118.1246 + while (a[great] > pivot2) {
118.1247 + if (k == great--) {
118.1248 + break outer;
118.1249 + }
118.1250 + }
118.1251 + a[k] = a[great];
118.1252 + a[great--] = ak;
118.1253 +
118.1254 + if ((ak = a[k]) < pivot1) {
118.1255 + a[k] = a[less];
118.1256 + a[less++] = ak;
118.1257 + }
118.1258 + }
118.1259 + }
118.1260 + } else { // Pivots are equal
118.1261 + /*
118.1262 + * Partition degenerates to the traditional 3-way
118.1263 + * (or "Dutch National Flag") partition:
118.1264 + *
118.1265 + * left part center part right part
118.1266 + * -------------------------------------------------
118.1267 + * [ < pivot | == pivot | ? | > pivot ]
118.1268 + * -------------------------------------------------
118.1269 + *
118.1270 + * ^ ^ ^
118.1271 + * | | |
118.1272 + * less k great
118.1273 + *
118.1274 + * Invariants:
118.1275 + *
118.1276 + * all in (left, less) < pivot
118.1277 + * all in [less, k) == pivot
118.1278 + * all in (great, right) > pivot
118.1279 + *
118.1280 + * Pointer k is the first index of ?-part
118.1281 + */
118.1282 + outer:
118.1283 + for (int k = less; k <= great; k++) {
118.1284 + byte ak = a[k];
118.1285 + if (ak == pivot1) {
118.1286 + continue;
118.1287 + }
118.1288 + if (ak < pivot1) {
118.1289 + if (k > less) {
118.1290 + a[k] = a[less];
118.1291 + a[less] = ak;
118.1292 + }
118.1293 + less++;
118.1294 + } else { // a[k] > pivot
118.1295 + while (a[great] > pivot1) {
118.1296 + if (k == great--) {
118.1297 + break outer;
118.1298 + }
118.1299 + }
118.1300 + a[k] = a[great];
118.1301 + a[great--] = ak;
118.1302 +
118.1303 + if ((ak = a[k]) < pivot1) {
118.1304 + a[k] = a[less];
118.1305 + a[less++] = ak;
118.1306 + }
118.1307 + }
118.1308 + }
118.1309 + }
118.1310 +
118.1311 + // Swap pivots into their final positions
118.1312 + a[left] = a[less - 1]; a[less - 1] = pivot1;
118.1313 + a[right] = a[great + 1]; a[great + 1] = pivot2;
118.1314 +
118.1315 + // Sort left and right parts recursively, excluding known pivot values
118.1316 + doSort(a, left, less - 2);
118.1317 + doSort(a, great + 2, right);
118.1318 +
118.1319 + /*
118.1320 + * If pivot1 == pivot2, all elements from center
118.1321 + * part are equal and, therefore, already sorted
118.1322 + */
118.1323 + if (!pivotsDiffer) {
118.1324 + return;
118.1325 + }
118.1326 +
118.1327 + /*
118.1328 + * If center part is too large (comprises > 5/6 of
118.1329 + * the array), swap internal pivot values to ends
118.1330 + */
118.1331 + if (less < e1 && e5 < great) {
118.1332 + while (a[less] == pivot1) {
118.1333 + less++;
118.1334 + }
118.1335 + while (a[great] == pivot2) {
118.1336 + great--;
118.1337 + }
118.1338 + for (int k = less + 1; k <= great; ) {
118.1339 + byte ak = a[k];
118.1340 + if (ak == pivot1) {
118.1341 + a[k++] = a[less];
118.1342 + a[less++] = pivot1;
118.1343 + } else if (ak == pivot2) {
118.1344 + a[k] = a[great];
118.1345 + a[great--] = pivot2;
118.1346 + } else {
118.1347 + k++;
118.1348 + }
118.1349 + }
118.1350 + }
118.1351 +
118.1352 + // Sort center part recursively, excluding known pivot values
118.1353 + doSort(a, less, great);
118.1354 + }
118.1355 +
118.1356 + /**
118.1357 + * Sorts the specified array into ascending numerical order.
118.1358 + *
118.1359 + * <p>The {@code <} relation does not provide a total order on all float
118.1360 + * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
118.1361 + * value compares neither less than, greater than, nor equal to any value,
118.1362 + * even itself. This method uses the total order imposed by the method
118.1363 + * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
118.1364 + * {@code 0.0f} and {@code Float.NaN} is considered greater than any
118.1365 + * other value and all {@code Float.NaN} values are considered equal.
118.1366 + *
118.1367 + * @param a the array to be sorted
118.1368 + */
118.1369 + public static void sort(float[] a) {
118.1370 + sortNegZeroAndNaN(a, 0, a.length - 1);
118.1371 + }
118.1372 +
118.1373 + /**
118.1374 + * Sorts the specified range of the array into ascending order. The range
118.1375 + * to be sorted extends from the index {@code fromIndex}, inclusive, to
118.1376 + * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
118.1377 + * the range to be sorted is empty.
118.1378 + *
118.1379 + * <p>The {@code <} relation does not provide a total order on all float
118.1380 + * values: {@code -0.0f == 0.0f} is {@code true} and a {@code Float.NaN}
118.1381 + * value compares neither less than, greater than, nor equal to any value,
118.1382 + * even itself. This method uses the total order imposed by the method
118.1383 + * {@link Float#compareTo}: {@code -0.0f} is treated as less than value
118.1384 + * {@code 0.0f} and {@code Float.NaN} is considered greater than any
118.1385 + * other value and all {@code Float.NaN} values are considered equal.
118.1386 + *
118.1387 + * @param a the array to be sorted
118.1388 + * @param fromIndex the index of the first element, inclusive, to be sorted
118.1389 + * @param toIndex the index of the last element, exclusive, to be sorted
118.1390 + * @throws IllegalArgumentException if {@code fromIndex > toIndex}
118.1391 + * @throws ArrayIndexOutOfBoundsException
118.1392 + * if {@code fromIndex < 0} or {@code toIndex > a.length}
118.1393 + */
118.1394 + public static void sort(float[] a, int fromIndex, int toIndex) {
118.1395 + rangeCheck(a.length, fromIndex, toIndex);
118.1396 + sortNegZeroAndNaN(a, fromIndex, toIndex - 1);
118.1397 + }
118.1398 +
118.1399 + /**
118.1400 + * Sorts the specified range of the array into ascending order. The
118.1401 + * sort is done in three phases to avoid expensive comparisons in the
118.1402 + * inner loop. The comparisons would be expensive due to anomalies
118.1403 + * associated with negative zero {@code -0.0f} and {@code Float.NaN}.
118.1404 + *
118.1405 + * @param a the array to be sorted
118.1406 + * @param left the index of the first element, inclusive, to be sorted
118.1407 + * @param right the index of the last element, inclusive, to be sorted
118.1408 + */
118.1409 + private static void sortNegZeroAndNaN(float[] a, int left, int right) {
118.1410 + /*
118.1411 + * Phase 1: Count negative zeros and move NaNs to end of array
118.1412 + */
118.1413 + final int NEGATIVE_ZERO = Float.floatToIntBits(-0.0f);
118.1414 + int numNegativeZeros = 0;
118.1415 + int n = right;
118.1416 +
118.1417 + for (int k = left; k <= n; k++) {
118.1418 + float ak = a[k];
118.1419 + if (ak == 0.0f && NEGATIVE_ZERO == Float.floatToIntBits(ak)) {
118.1420 + a[k] = 0.0f;
118.1421 + numNegativeZeros++;
118.1422 + } else if (ak != ak) { // i.e., ak is NaN
118.1423 + a[k--] = a[n];
118.1424 + a[n--] = Float.NaN;
118.1425 + }
118.1426 + }
118.1427 +
118.1428 + /*
118.1429 + * Phase 2: Sort everything except NaNs (which are already in place)
118.1430 + */
118.1431 + doSort(a, left, n);
118.1432 +
118.1433 + /*
118.1434 + * Phase 3: Turn positive zeros back into negative zeros as appropriate
118.1435 + */
118.1436 + if (numNegativeZeros == 0) {
118.1437 + return;
118.1438 + }
118.1439 +
118.1440 + // Find first zero element
118.1441 + int zeroIndex = findAnyZero(a, left, n);
118.1442 +
118.1443 + for (int i = zeroIndex - 1; i >= left && a[i] == 0.0f; i--) {
118.1444 + zeroIndex = i;
118.1445 + }
118.1446 +
118.1447 + // Turn the right number of positive zeros back into negative zeros
118.1448 + for (int i = zeroIndex, m = zeroIndex + numNegativeZeros; i < m; i++) {
118.1449 + a[i] = -0.0f;
118.1450 + }
118.1451 + }
118.1452 +
118.1453 + /**
118.1454 + * Returns the index of some zero element in the specified range via
118.1455 + * binary search. The range is assumed to be sorted, and must contain
118.1456 + * at least one zero.
118.1457 + *
118.1458 + * @param a the array to be searched
118.1459 + * @param low the index of the first element, inclusive, to be searched
118.1460 + * @param high the index of the last element, inclusive, to be searched
118.1461 + */
118.1462 + private static int findAnyZero(float[] a, int low, int high) {
118.1463 + while (true) {
118.1464 + int middle = (low + high) >>> 1;
118.1465 + float middleValue = a[middle];
118.1466 +
118.1467 + if (middleValue < 0.0f) {
118.1468 + low = middle + 1;
118.1469 + } else if (middleValue > 0.0f) {
118.1470 + high = middle - 1;
118.1471 + } else { // middleValue == 0.0f
118.1472 + return middle;
118.1473 + }
118.1474 + }
118.1475 + }
118.1476 +
118.1477 + /**
118.1478 + * Sorts the specified range of the array into ascending order. This
118.1479 + * method differs from the public {@code sort} method in three ways:
118.1480 + * {@code right} index is inclusive, it does no range checking on
118.1481 + * {@code left} or {@code right}, and it does not handle negative
118.1482 + * zeros or NaNs in the array.
118.1483 + *
118.1484 + * @param a the array to be sorted, which must not contain -0.0f or NaN
118.1485 + * @param left the index of the first element, inclusive, to be sorted
118.1486 + * @param right the index of the last element, inclusive, to be sorted
118.1487 + */
118.1488 + private static void doSort(float[] a, int left, int right) {
118.1489 + // Use insertion sort on tiny arrays
118.1490 + if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
118.1491 + for (int k = left + 1; k <= right; k++) {
118.1492 + float ak = a[k];
118.1493 + int j;
118.1494 + for (j = k - 1; j >= left && ak < a[j]; j--) {
118.1495 + a[j + 1] = a[j];
118.1496 + }
118.1497 + a[j + 1] = ak;
118.1498 + }
118.1499 + } else { // Use Dual-Pivot Quicksort on large arrays
118.1500 + dualPivotQuicksort(a, left, right);
118.1501 + }
118.1502 + }
118.1503 +
118.1504 + /**
118.1505 + * Sorts the specified range of the array into ascending order by the
118.1506 + * Dual-Pivot Quicksort algorithm.
118.1507 + *
118.1508 + * @param a the array to be sorted
118.1509 + * @param left the index of the first element, inclusive, to be sorted
118.1510 + * @param right the index of the last element, inclusive, to be sorted
118.1511 + */
118.1512 + private static void dualPivotQuicksort(float[] a, int left, int right) {
118.1513 + // Compute indices of five evenly spaced elements
118.1514 + int sixth = (right - left + 1) / 6;
118.1515 + int e1 = left + sixth;
118.1516 + int e5 = right - sixth;
118.1517 + int e3 = (left + right) >>> 1; // The midpoint
118.1518 + int e4 = e3 + sixth;
118.1519 + int e2 = e3 - sixth;
118.1520 +
118.1521 + // Sort these elements using a 5-element sorting network
118.1522 + float ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
118.1523 +
118.1524 + if (ae1 > ae2) { float t = ae1; ae1 = ae2; ae2 = t; }
118.1525 + if (ae4 > ae5) { float t = ae4; ae4 = ae5; ae5 = t; }
118.1526 + if (ae1 > ae3) { float t = ae1; ae1 = ae3; ae3 = t; }
118.1527 + if (ae2 > ae3) { float t = ae2; ae2 = ae3; ae3 = t; }
118.1528 + if (ae1 > ae4) { float t = ae1; ae1 = ae4; ae4 = t; }
118.1529 + if (ae3 > ae4) { float t = ae3; ae3 = ae4; ae4 = t; }
118.1530 + if (ae2 > ae5) { float t = ae2; ae2 = ae5; ae5 = t; }
118.1531 + if (ae2 > ae3) { float t = ae2; ae2 = ae3; ae3 = t; }
118.1532 + if (ae4 > ae5) { float t = ae4; ae4 = ae5; ae5 = t; }
118.1533 +
118.1534 + a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
118.1535 +
118.1536 + /*
118.1537 + * Use the second and fourth of the five sorted elements as pivots.
118.1538 + * These values are inexpensive approximations of the first and
118.1539 + * second terciles of the array. Note that pivot1 <= pivot2.
118.1540 + *
118.1541 + * The pivots are stored in local variables, and the first and
118.1542 + * the last of the sorted elements are moved to the locations
118.1543 + * formerly occupied by the pivots. When partitioning is complete,
118.1544 + * the pivots are swapped back into their final positions, and
118.1545 + * excluded from subsequent sorting.
118.1546 + */
118.1547 + float pivot1 = ae2; a[e2] = a[left];
118.1548 + float pivot2 = ae4; a[e4] = a[right];
118.1549 +
118.1550 + /*
118.1551 + * Partitioning
118.1552 + *
118.1553 + * left part center part right part
118.1554 + * ------------------------------------------------------------
118.1555 + * [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
118.1556 + * ------------------------------------------------------------
118.1557 + * ^ ^ ^
118.1558 + * | | |
118.1559 + * less k great
118.1560 + */
118.1561 +
118.1562 + // Pointers
118.1563 + int less = left + 1; // The index of first element of center part
118.1564 + int great = right - 1; // The index before first element of right part
118.1565 +
118.1566 + boolean pivotsDiffer = pivot1 != pivot2;
118.1567 +
118.1568 + if (pivotsDiffer) {
118.1569 + /*
118.1570 + * Invariants:
118.1571 + * all in (left, less) < pivot1
118.1572 + * pivot1 <= all in [less, k) <= pivot2
118.1573 + * all in (great, right) > pivot2
118.1574 + *
118.1575 + * Pointer k is the first index of ?-part
118.1576 + */
118.1577 + outer:
118.1578 + for (int k = less; k <= great; k++) {
118.1579 + float ak = a[k];
118.1580 + if (ak < pivot1) {
118.1581 + if (k > less) {
118.1582 + a[k] = a[less];
118.1583 + a[less] = ak;
118.1584 + }
118.1585 + less++;
118.1586 + } else if (ak > pivot2) {
118.1587 + while (a[great] > pivot2) {
118.1588 + if (k == great--) {
118.1589 + break outer;
118.1590 + }
118.1591 + }
118.1592 + a[k] = a[great];
118.1593 + a[great--] = ak;
118.1594 +
118.1595 + if ((ak = a[k]) < pivot1) {
118.1596 + a[k] = a[less];
118.1597 + a[less++] = ak;
118.1598 + }
118.1599 + }
118.1600 + }
118.1601 + } else { // Pivots are equal
118.1602 + /*
118.1603 + * Partition degenerates to the traditional 3-way
118.1604 + * (or "Dutch National Flag") partition:
118.1605 + *
118.1606 + * left part center part right part
118.1607 + * -------------------------------------------------
118.1608 + * [ < pivot | == pivot | ? | > pivot ]
118.1609 + * -------------------------------------------------
118.1610 + *
118.1611 + * ^ ^ ^
118.1612 + * | | |
118.1613 + * less k great
118.1614 + *
118.1615 + * Invariants:
118.1616 + *
118.1617 + * all in (left, less) < pivot
118.1618 + * all in [less, k) == pivot
118.1619 + * all in (great, right) > pivot
118.1620 + *
118.1621 + * Pointer k is the first index of ?-part
118.1622 + */
118.1623 + outer:
118.1624 + for (int k = less; k <= great; k++) {
118.1625 + float ak = a[k];
118.1626 + if (ak == pivot1) {
118.1627 + continue;
118.1628 + }
118.1629 + if (ak < pivot1) {
118.1630 + if (k > less) {
118.1631 + a[k] = a[less];
118.1632 + a[less] = ak;
118.1633 + }
118.1634 + less++;
118.1635 + } else { // a[k] > pivot
118.1636 + while (a[great] > pivot1) {
118.1637 + if (k == great--) {
118.1638 + break outer;
118.1639 + }
118.1640 + }
118.1641 + a[k] = a[great];
118.1642 + a[great--] = ak;
118.1643 +
118.1644 + if ((ak = a[k]) < pivot1) {
118.1645 + a[k] = a[less];
118.1646 + a[less++] = ak;
118.1647 + }
118.1648 + }
118.1649 + }
118.1650 + }
118.1651 +
118.1652 + // Swap pivots into their final positions
118.1653 + a[left] = a[less - 1]; a[less - 1] = pivot1;
118.1654 + a[right] = a[great + 1]; a[great + 1] = pivot2;
118.1655 +
118.1656 + // Sort left and right parts recursively, excluding known pivot values
118.1657 + doSort(a, left, less - 2);
118.1658 + doSort(a, great + 2, right);
118.1659 +
118.1660 + /*
118.1661 + * If pivot1 == pivot2, all elements from center
118.1662 + * part are equal and, therefore, already sorted
118.1663 + */
118.1664 + if (!pivotsDiffer) {
118.1665 + return;
118.1666 + }
118.1667 +
118.1668 + /*
118.1669 + * If center part is too large (comprises > 5/6 of
118.1670 + * the array), swap internal pivot values to ends
118.1671 + */
118.1672 + if (less < e1 && e5 < great) {
118.1673 + while (a[less] == pivot1) {
118.1674 + less++;
118.1675 + }
118.1676 + while (a[great] == pivot2) {
118.1677 + great--;
118.1678 + }
118.1679 + for (int k = less + 1; k <= great; ) {
118.1680 + float ak = a[k];
118.1681 + if (ak == pivot1) {
118.1682 + a[k++] = a[less];
118.1683 + a[less++] = pivot1;
118.1684 + } else if (ak == pivot2) {
118.1685 + a[k] = a[great];
118.1686 + a[great--] = pivot2;
118.1687 + } else {
118.1688 + k++;
118.1689 + }
118.1690 + }
118.1691 + }
118.1692 +
118.1693 + // Sort center part recursively, excluding known pivot values
118.1694 + doSort(a, less, great);
118.1695 + }
118.1696 +
118.1697 + /**
118.1698 + * Sorts the specified array into ascending numerical order.
118.1699 + *
118.1700 + * <p>The {@code <} relation does not provide a total order on all double
118.1701 + * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
118.1702 + * value compares neither less than, greater than, nor equal to any value,
118.1703 + * even itself. This method uses the total order imposed by the method
118.1704 + * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
118.1705 + * {@code 0.0d} and {@code Double.NaN} is considered greater than any
118.1706 + * other value and all {@code Double.NaN} values are considered equal.
118.1707 + *
118.1708 + * @param a the array to be sorted
118.1709 + */
118.1710 + public static void sort(double[] a) {
118.1711 + sortNegZeroAndNaN(a, 0, a.length - 1);
118.1712 + }
118.1713 +
118.1714 + /**
118.1715 + * Sorts the specified range of the array into ascending order. The range
118.1716 + * to be sorted extends from the index {@code fromIndex}, inclusive, to
118.1717 + * the index {@code toIndex}, exclusive. If {@code fromIndex == toIndex},
118.1718 + * the range to be sorted is empty.
118.1719 + *
118.1720 + * <p>The {@code <} relation does not provide a total order on all double
118.1721 + * values: {@code -0.0d == 0.0d} is {@code true} and a {@code Double.NaN}
118.1722 + * value compares neither less than, greater than, nor equal to any value,
118.1723 + * even itself. This method uses the total order imposed by the method
118.1724 + * {@link Double#compareTo}: {@code -0.0d} is treated as less than value
118.1725 + * {@code 0.0d} and {@code Double.NaN} is considered greater than any
118.1726 + * other value and all {@code Double.NaN} values are considered equal.
118.1727 + *
118.1728 + * @param a the array to be sorted
118.1729 + * @param fromIndex the index of the first element, inclusive, to be sorted
118.1730 + * @param toIndex the index of the last element, exclusive, to be sorted
118.1731 + * @throws IllegalArgumentException if {@code fromIndex > toIndex}
118.1732 + * @throws ArrayIndexOutOfBoundsException
118.1733 + * if {@code fromIndex < 0} or {@code toIndex > a.length}
118.1734 + */
118.1735 + public static void sort(double[] a, int fromIndex, int toIndex) {
118.1736 + rangeCheck(a.length, fromIndex, toIndex);
118.1737 + sortNegZeroAndNaN(a, fromIndex, toIndex - 1);
118.1738 + }
118.1739 +
118.1740 + /**
118.1741 + * Sorts the specified range of the array into ascending order. The
118.1742 + * sort is done in three phases to avoid expensive comparisons in the
118.1743 + * inner loop. The comparisons would be expensive due to anomalies
118.1744 + * associated with negative zero {@code -0.0d} and {@code Double.NaN}.
118.1745 + *
118.1746 + * @param a the array to be sorted
118.1747 + * @param left the index of the first element, inclusive, to be sorted
118.1748 + * @param right the index of the last element, inclusive, to be sorted
118.1749 + */
118.1750 + private static void sortNegZeroAndNaN(double[] a, int left, int right) {
118.1751 + /*
118.1752 + * Phase 1: Count negative zeros and move NaNs to end of array
118.1753 + */
118.1754 + final long NEGATIVE_ZERO = Double.doubleToLongBits(-0.0d);
118.1755 + int numNegativeZeros = 0;
118.1756 + int n = right;
118.1757 +
118.1758 + for (int k = left; k <= n; k++) {
118.1759 + double ak = a[k];
118.1760 + if (ak == 0.0d && NEGATIVE_ZERO == Double.doubleToLongBits(ak)) {
118.1761 + a[k] = 0.0d;
118.1762 + numNegativeZeros++;
118.1763 + } else if (ak != ak) { // i.e., ak is NaN
118.1764 + a[k--] = a[n];
118.1765 + a[n--] = Double.NaN;
118.1766 + }
118.1767 + }
118.1768 +
118.1769 + /*
118.1770 + * Phase 2: Sort everything except NaNs (which are already in place)
118.1771 + */
118.1772 + doSort(a, left, n);
118.1773 +
118.1774 + /*
118.1775 + * Phase 3: Turn positive zeros back into negative zeros as appropriate
118.1776 + */
118.1777 + if (numNegativeZeros == 0) {
118.1778 + return;
118.1779 + }
118.1780 +
118.1781 + // Find first zero element
118.1782 + int zeroIndex = findAnyZero(a, left, n);
118.1783 +
118.1784 + for (int i = zeroIndex - 1; i >= left && a[i] == 0.0d; i--) {
118.1785 + zeroIndex = i;
118.1786 + }
118.1787 +
118.1788 + // Turn the right number of positive zeros back into negative zeros
118.1789 + for (int i = zeroIndex, m = zeroIndex + numNegativeZeros; i < m; i++) {
118.1790 + a[i] = -0.0d;
118.1791 + }
118.1792 + }
118.1793 +
118.1794 + /**
118.1795 + * Returns the index of some zero element in the specified range via
118.1796 + * binary search. The range is assumed to be sorted, and must contain
118.1797 + * at least one zero.
118.1798 + *
118.1799 + * @param a the array to be searched
118.1800 + * @param low the index of the first element, inclusive, to be searched
118.1801 + * @param high the index of the last element, inclusive, to be searched
118.1802 + */
118.1803 + private static int findAnyZero(double[] a, int low, int high) {
118.1804 + while (true) {
118.1805 + int middle = (low + high) >>> 1;
118.1806 + double middleValue = a[middle];
118.1807 +
118.1808 + if (middleValue < 0.0d) {
118.1809 + low = middle + 1;
118.1810 + } else if (middleValue > 0.0d) {
118.1811 + high = middle - 1;
118.1812 + } else { // middleValue == 0.0d
118.1813 + return middle;
118.1814 + }
118.1815 + }
118.1816 + }
118.1817 +
118.1818 + /**
118.1819 + * Sorts the specified range of the array into ascending order. This
118.1820 + * method differs from the public {@code sort} method in three ways:
118.1821 + * {@code right} index is inclusive, it does no range checking on
118.1822 + * {@code left} or {@code right}, and it does not handle negative
118.1823 + * zeros or NaNs in the array.
118.1824 + *
118.1825 + * @param a the array to be sorted, which must not contain -0.0d and NaN
118.1826 + * @param left the index of the first element, inclusive, to be sorted
118.1827 + * @param right the index of the last element, inclusive, to be sorted
118.1828 + */
118.1829 + private static void doSort(double[] a, int left, int right) {
118.1830 + // Use insertion sort on tiny arrays
118.1831 + if (right - left + 1 < INSERTION_SORT_THRESHOLD) {
118.1832 + for (int k = left + 1; k <= right; k++) {
118.1833 + double ak = a[k];
118.1834 + int j;
118.1835 + for (j = k - 1; j >= left && ak < a[j]; j--) {
118.1836 + a[j + 1] = a[j];
118.1837 + }
118.1838 + a[j + 1] = ak;
118.1839 + }
118.1840 + } else { // Use Dual-Pivot Quicksort on large arrays
118.1841 + dualPivotQuicksort(a, left, right);
118.1842 + }
118.1843 + }
118.1844 +
118.1845 + /**
118.1846 + * Sorts the specified range of the array into ascending order by the
118.1847 + * Dual-Pivot Quicksort algorithm.
118.1848 + *
118.1849 + * @param a the array to be sorted
118.1850 + * @param left the index of the first element, inclusive, to be sorted
118.1851 + * @param right the index of the last element, inclusive, to be sorted
118.1852 + */
118.1853 + private static void dualPivotQuicksort(double[] a, int left, int right) {
118.1854 + // Compute indices of five evenly spaced elements
118.1855 + int sixth = (right - left + 1) / 6;
118.1856 + int e1 = left + sixth;
118.1857 + int e5 = right - sixth;
118.1858 + int e3 = (left + right) >>> 1; // The midpoint
118.1859 + int e4 = e3 + sixth;
118.1860 + int e2 = e3 - sixth;
118.1861 +
118.1862 + // Sort these elements using a 5-element sorting network
118.1863 + double ae1 = a[e1], ae2 = a[e2], ae3 = a[e3], ae4 = a[e4], ae5 = a[e5];
118.1864 +
118.1865 + if (ae1 > ae2) { double t = ae1; ae1 = ae2; ae2 = t; }
118.1866 + if (ae4 > ae5) { double t = ae4; ae4 = ae5; ae5 = t; }
118.1867 + if (ae1 > ae3) { double t = ae1; ae1 = ae3; ae3 = t; }
118.1868 + if (ae2 > ae3) { double t = ae2; ae2 = ae3; ae3 = t; }
118.1869 + if (ae1 > ae4) { double t = ae1; ae1 = ae4; ae4 = t; }
118.1870 + if (ae3 > ae4) { double t = ae3; ae3 = ae4; ae4 = t; }
118.1871 + if (ae2 > ae5) { double t = ae2; ae2 = ae5; ae5 = t; }
118.1872 + if (ae2 > ae3) { double t = ae2; ae2 = ae3; ae3 = t; }
118.1873 + if (ae4 > ae5) { double t = ae4; ae4 = ae5; ae5 = t; }
118.1874 +
118.1875 + a[e1] = ae1; a[e3] = ae3; a[e5] = ae5;
118.1876 +
118.1877 + /*
118.1878 + * Use the second and fourth of the five sorted elements as pivots.
118.1879 + * These values are inexpensive approximations of the first and
118.1880 + * second terciles of the array. Note that pivot1 <= pivot2.
118.1881 + *
118.1882 + * The pivots are stored in local variables, and the first and
118.1883 + * the last of the sorted elements are moved to the locations
118.1884 + * formerly occupied by the pivots. When partitioning is complete,
118.1885 + * the pivots are swapped back into their final positions, and
118.1886 + * excluded from subsequent sorting.
118.1887 + */
118.1888 + double pivot1 = ae2; a[e2] = a[left];
118.1889 + double pivot2 = ae4; a[e4] = a[right];
118.1890 +
118.1891 + /*
118.1892 + * Partitioning
118.1893 + *
118.1894 + * left part center part right part
118.1895 + * ------------------------------------------------------------
118.1896 + * [ < pivot1 | pivot1 <= && <= pivot2 | ? | > pivot2 ]
118.1897 + * ------------------------------------------------------------
118.1898 + * ^ ^ ^
118.1899 + * | | |
118.1900 + * less k great
118.1901 + */
118.1902 +
118.1903 + // Pointers
118.1904 + int less = left + 1; // The index of first element of center part
118.1905 + int great = right - 1; // The index before first element of right part
118.1906 +
118.1907 + boolean pivotsDiffer = pivot1 != pivot2;
118.1908 +
118.1909 + if (pivotsDiffer) {
118.1910 + /*
118.1911 + * Invariants:
118.1912 + * all in (left, less) < pivot1
118.1913 + * pivot1 <= all in [less, k) <= pivot2
118.1914 + * all in (great, right) > pivot2
118.1915 + *
118.1916 + * Pointer k is the first index of ?-part
118.1917 + */
118.1918 + outer:
118.1919 + for (int k = less; k <= great; k++) {
118.1920 + double ak = a[k];
118.1921 + if (ak < pivot1) {
118.1922 + if (k > less) {
118.1923 + a[k] = a[less];
118.1924 + a[less] = ak;
118.1925 + }
118.1926 + less++;
118.1927 + } else if (ak > pivot2) {
118.1928 + while (a[great] > pivot2) {
118.1929 + if (k == great--) {
118.1930 + break outer;
118.1931 + }
118.1932 + }
118.1933 + a[k] = a[great];
118.1934 + a[great--] = ak;
118.1935 +
118.1936 + if ((ak = a[k]) < pivot1) {
118.1937 + a[k] = a[less];
118.1938 + a[less++] = ak;
118.1939 + }
118.1940 + }
118.1941 + }
118.1942 + } else { // Pivots are equal
118.1943 + /*
118.1944 + * Partition degenerates to the traditional 3-way
118.1945 + * (or "Dutch National Flag") partition:
118.1946 + *
118.1947 + * left part center part right part
118.1948 + * -------------------------------------------------
118.1949 + * [ < pivot | == pivot | ? | > pivot ]
118.1950 + * -------------------------------------------------
118.1951 + *
118.1952 + * ^ ^ ^
118.1953 + * | | |
118.1954 + * less k great
118.1955 + *
118.1956 + * Invariants:
118.1957 + *
118.1958 + * all in (left, less) < pivot
118.1959 + * all in [less, k) == pivot
118.1960 + * all in (great, right) > pivot
118.1961 + *
118.1962 + * Pointer k is the first index of ?-part
118.1963 + */
118.1964 + outer:
118.1965 + for (int k = less; k <= great; k++) {
118.1966 + double ak = a[k];
118.1967 + if (ak == pivot1) {
118.1968 + continue;
118.1969 + }
118.1970 + if (ak < pivot1) {
118.1971 + if (k > less) {
118.1972 + a[k] = a[less];
118.1973 + a[less] = ak;
118.1974 + }
118.1975 + less++;
118.1976 + } else { // a[k] > pivot
118.1977 + while (a[great] > pivot1) {
118.1978 + if (k == great--) {
118.1979 + break outer;
118.1980 + }
118.1981 + }
118.1982 + a[k] = a[great];
118.1983 + a[great--] = ak;
118.1984 +
118.1985 + if ((ak = a[k]) < pivot1) {
118.1986 + a[k] = a[less];
118.1987 + a[less++] = ak;
118.1988 + }
118.1989 + }
118.1990 + }
118.1991 + }
118.1992 +
118.1993 + // Swap pivots into their final positions
118.1994 + a[left] = a[less - 1]; a[less - 1] = pivot1;
118.1995 + a[right] = a[great + 1]; a[great + 1] = pivot2;
118.1996 +
118.1997 + // Sort left and right parts recursively, excluding known pivot values
118.1998 + doSort(a, left, less - 2);
118.1999 + doSort(a, great + 2, right);
118.2000 +
118.2001 + /*
118.2002 + * If pivot1 == pivot2, all elements from center
118.2003 + * part are equal and, therefore, already sorted
118.2004 + */
118.2005 + if (!pivotsDiffer) {
118.2006 + return;
118.2007 + }
118.2008 +
118.2009 + /*
118.2010 + * If center part is too large (comprises > 5/6 of
118.2011 + * the array), swap internal pivot values to ends
118.2012 + */
118.2013 + if (less < e1 && e5 < great) {
118.2014 + while (a[less] == pivot1) {
118.2015 + less++;
118.2016 + }
118.2017 + while (a[great] == pivot2) {
118.2018 + great--;
118.2019 + }
118.2020 + for (int k = less + 1; k <= great; ) {
118.2021 + double ak = a[k];
118.2022 + if (ak == pivot1) {
118.2023 + a[k++] = a[less];
118.2024 + a[less++] = pivot1;
118.2025 + } else if (ak == pivot2) {
118.2026 + a[k] = a[great];
118.2027 + a[great--] = pivot2;
118.2028 + } else {
118.2029 + k++;
118.2030 + }
118.2031 + }
118.2032 + }
118.2033 +
118.2034 + // Sort center part recursively, excluding known pivot values
118.2035 + doSort(a, less, great);
118.2036 + }
118.2037 +
118.2038 + /**
118.2039 + * Checks that {@code fromIndex} and {@code toIndex} are in
118.2040 + * the range and throws an appropriate exception, if they aren't.
118.2041 + */
118.2042 + private static void rangeCheck(int length, int fromIndex, int toIndex) {
118.2043 + if (fromIndex > toIndex) {
118.2044 + throw new IllegalArgumentException(
118.2045 + "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")");
118.2046 + }
118.2047 + if (fromIndex < 0) {
118.2048 + throw new ArrayIndexOutOfBoundsException(fromIndex);
118.2049 + }
118.2050 + if (toIndex > length) {
118.2051 + throw new ArrayIndexOutOfBoundsException(toIndex);
118.2052 + }
118.2053 + }
118.2054 +}
119.1 --- a/src/share/classes/java/util/Formatter.java Mon Nov 23 10:04:47 2009 +0000
119.2 +++ b/src/share/classes/java/util/Formatter.java Wed Nov 25 11:08:25 2009 -0800
119.3 @@ -2485,55 +2485,45 @@
119.4
119.5 private static Pattern fsPattern = Pattern.compile(formatSpecifier);
119.6
119.7 - // Look for format specifiers in the format string.
119.8 + /**
119.9 + * Finds format specifiers in the format string.
119.10 + */
119.11 private FormatString[] parse(String s) {
119.12 - ArrayList al = new ArrayList();
119.13 + ArrayList<FormatString> al = new ArrayList<FormatString>();
119.14 Matcher m = fsPattern.matcher(s);
119.15 - int i = 0;
119.16 - while (i < s.length()) {
119.17 + for (int i = 0, len = s.length(); i < len; ) {
119.18 if (m.find(i)) {
119.19 // Anything between the start of the string and the beginning
119.20 // of the format specifier is either fixed text or contains
119.21 // an invalid format string.
119.22 if (m.start() != i) {
119.23 // Make sure we didn't miss any invalid format specifiers
119.24 - checkText(s.substring(i, m.start()));
119.25 + checkText(s, i, m.start());
119.26 // Assume previous characters were fixed text
119.27 al.add(new FixedString(s.substring(i, m.start())));
119.28 }
119.29
119.30 - // Expect 6 groups in regular expression
119.31 - String[] sa = new String[6];
119.32 - for (int j = 0; j < m.groupCount(); j++)
119.33 - {
119.34 - sa[j] = m.group(j + 1);
119.35 -// System.out.print(sa[j] + " ");
119.36 - }
119.37 -// System.out.println();
119.38 - al.add(new FormatSpecifier(this, sa));
119.39 + al.add(new FormatSpecifier(m));
119.40 i = m.end();
119.41 } else {
119.42 // No more valid format specifiers. Check for possible invalid
119.43 // format specifiers.
119.44 - checkText(s.substring(i));
119.45 + checkText(s, i, len);
119.46 // The rest of the string is fixed text
119.47 al.add(new FixedString(s.substring(i)));
119.48 break;
119.49 }
119.50 }
119.51 -// FormatString[] fs = new FormatString[al.size()];
119.52 -// for (int j = 0; j < al.size(); j++)
119.53 -// System.out.println(((FormatString) al.get(j)).toString());
119.54 - return (FormatString[]) al.toArray(new FormatString[0]);
119.55 + return al.toArray(new FormatString[al.size()]);
119.56 }
119.57
119.58 - private void checkText(String s) {
119.59 - int idx;
119.60 - // If there are any '%' in the given string, we got a bad format
119.61 - // specifier.
119.62 - if ((idx = s.indexOf('%')) != -1) {
119.63 - char c = (idx > s.length() - 2 ? '%' : s.charAt(idx + 1));
119.64 - throw new UnknownFormatConversionException(String.valueOf(c));
119.65 + private static void checkText(String s, int start, int end) {
119.66 + for (int i = start; i < end; i++) {
119.67 + // Any '%' found in the region starts an invalid format specifier.
119.68 + if (s.charAt(i) == '%') {
119.69 + char c = (i == end - 1) ? '%' : s.charAt(i + 1);
119.70 + throw new UnknownFormatConversionException(String.valueOf(c));
119.71 + }
119.72 }
119.73 }
119.74
119.75 @@ -2562,8 +2552,6 @@
119.76 private boolean dt = false;
119.77 private char c;
119.78
119.79 - private Formatter formatter;
119.80 -
119.81 // cache the line separator
119.82 private String ls;
119.83
119.84 @@ -2650,21 +2638,22 @@
119.85 return c;
119.86 }
119.87
119.88 - FormatSpecifier(Formatter formatter, String[] sa) {
119.89 - this.formatter = formatter;
119.90 - int idx = 0;
119.91 -
119.92 - index(sa[idx++]);
119.93 - flags(sa[idx++]);
119.94 - width(sa[idx++]);
119.95 - precision(sa[idx++]);
119.96 -
119.97 - if (sa[idx] != null) {
119.98 + FormatSpecifier(Matcher m) {
119.99 + int idx = 1;
119.100 +
119.101 + index(m.group(idx++));
119.102 + flags(m.group(idx++));
119.103 + width(m.group(idx++));
119.104 + precision(m.group(idx++));
119.105 +
119.106 + String tT = m.group(idx++);
119.107 + if (tT != null) {
119.108 dt = true;
119.109 - if (sa[idx].equals("T"))
119.110 + if (tT.equals("T"))
119.111 f.add(Flags.UPPERCASE);
119.112 }
119.113 - conversion(sa[++idx]);
119.114 +
119.115 + conversion(m.group(idx));
119.116
119.117 if (dt)
119.118 checkDateTime();
119.119 @@ -2819,9 +2808,9 @@
119.120
119.121 private void printString(Object arg, Locale l) throws IOException {
119.122 if (arg instanceof Formattable) {
119.123 - Formatter fmt = formatter;
119.124 - if (formatter.locale() != l)
119.125 - fmt = new Formatter(formatter.out(), l);
119.126 + Formatter fmt = Formatter.this;
119.127 + if (fmt.locale() != l)
119.128 + fmt = new Formatter(fmt.out(), l);
119.129 ((Formattable)arg).formatTo(fmt, f.valueOf(), width, precision);
119.130 } else {
119.131 if (f.contains(Flags.ALTERNATE))
120.1 --- a/src/share/classes/java/util/LinkedList.java Mon Nov 23 10:04:47 2009 +0000
120.2 +++ b/src/share/classes/java/util/LinkedList.java Wed Nov 25 11:08:25 2009 -0800
120.3 @@ -26,22 +26,22 @@
120.4 package java.util;
120.5
120.6 /**
120.7 - * Linked list implementation of the <tt>List</tt> interface. Implements all
120.8 + * Linked list implementation of the {@code List} interface. Implements all
120.9 * optional list operations, and permits all elements (including
120.10 - * <tt>null</tt>). In addition to implementing the <tt>List</tt> interface,
120.11 - * the <tt>LinkedList</tt> class provides uniformly named methods to
120.12 - * <tt>get</tt>, <tt>remove</tt> and <tt>insert</tt> an element at the
120.13 + * {@code null}). In addition to implementing the {@code List} interface,
120.14 + * the {@code LinkedList} class provides uniformly named methods to
120.15 + * {@code get}, {@code remove} and {@code insert} an element at the
120.16 * beginning and end of the list. These operations allow linked lists to be
120.17 * used as a stack, {@linkplain Queue queue}, or {@linkplain Deque
120.18 - * double-ended queue}. <p>
120.19 + * double-ended queue}.
120.20 *
120.21 - * The class implements the <tt>Deque</tt> interface, providing
120.22 - * first-in-first-out queue operations for <tt>add</tt>,
120.23 - * <tt>poll</tt>, along with other stack and deque operations.<p>
120.24 + * <p>The class implements the {@code Deque} interface, providing
120.25 + * first-in-first-out queue operations for {@code add},
120.26 + * {@code poll}, along with other stack and deque operations.
120.27 *
120.28 - * All of the operations perform as could be expected for a doubly-linked
120.29 + * <p>All of the operations perform as could be expected for a doubly-linked
120.30 * list. Operations that index into the list will traverse the list from
120.31 - * the beginning or the end, whichever is closer to the specified index.<p>
120.32 + * the beginning or the end, whichever is closer to the specified index.
120.33 *
120.34 * <p><strong>Note that this implementation is not synchronized.</strong>
120.35 * If multiple threads access a linked list concurrently, and at least
120.36 @@ -58,11 +58,11 @@
120.37 * unsynchronized access to the list:<pre>
120.38 * List list = Collections.synchronizedList(new LinkedList(...));</pre>
120.39 *
120.40 - * <p>The iterators returned by this class's <tt>iterator</tt> and
120.41 - * <tt>listIterator</tt> methods are <i>fail-fast</i>: if the list is
120.42 + * <p>The iterators returned by this class's {@code iterator} and
120.43 + * {@code listIterator} methods are <i>fail-fast</i>: if the list is
120.44 * structurally modified at any time after the iterator is created, in
120.45 - * any way except through the Iterator's own <tt>remove</tt> or
120.46 - * <tt>add</tt> methods, the iterator will throw a {@link
120.47 + * any way except through the Iterator's own {@code remove} or
120.48 + * {@code add} methods, the iterator will throw a {@link
120.49 * ConcurrentModificationException}. Thus, in the face of concurrent
120.50 * modification, the iterator fails quickly and cleanly, rather than
120.51 * risking arbitrary, non-deterministic behavior at an undetermined
120.52 @@ -71,7 +71,7 @@
120.53 * <p>Note that the fail-fast behavior of an iterator cannot be guaranteed
120.54 * as it is, generally speaking, impossible to make any hard guarantees in the
120.55 * presence of unsynchronized concurrent modification. Fail-fast iterators
120.56 - * throw <tt>ConcurrentModificationException</tt> on a best-effort basis.
120.57 + * throw {@code ConcurrentModificationException} on a best-effort basis.
120.58 * Therefore, it would be wrong to write a program that depended on this
120.59 * exception for its correctness: <i>the fail-fast behavior of iterators
120.60 * should be used only to detect bugs.</i>
120.61 @@ -83,7 +83,6 @@
120.62 * @author Josh Bloch
120.63 * @see List
120.64 * @see ArrayList
120.65 - * @see Vector
120.66 * @since 1.2
120.67 * @param <E> the type of elements held in this collection
120.68 */
120.69 @@ -92,14 +91,26 @@
120.70 extends AbstractSequentialList<E>
120.71 implements List<E>, Deque<E>, Cloneable, java.io.Serializable
120.72 {
120.73 - private transient Entry<E> header = new Entry<E>(null, null, null);
120.74 - private transient int size = 0;
120.75 + transient int size = 0;
120.76 +
120.77 + /**
120.78 + * Pointer to first node.
120.79 + * Invariant: (first == null && last == null) ||
120.80 + * (first.prev == null && first.item != null)
120.81 + */
120.82 + transient Node<E> first;
120.83 +
120.84 + /**
120.85 + * Pointer to last node.
120.86 + * Invariant: (first == null && last == null) ||
120.87 + * (last.next == null && last.item != null)
120.88 + */
120.89 + transient Node<E> last;
120.90
120.91 /**
120.92 * Constructs an empty list.
120.93 */
120.94 public LinkedList() {
120.95 - header.next = header.previous = header;
120.96 }
120.97
120.98 /**
120.99 @@ -116,16 +127,129 @@
120.100 }
120.101
120.102 /**
120.103 + * Links e as first element.
120.104 + */
120.105 + private void linkFirst(E e) {
120.106 + final Node<E> f = first;
120.107 + final Node<E> newNode = new Node<E>(null, e, f);
120.108 + first = newNode;
120.109 + if (f == null)
120.110 + last = newNode;
120.111 + else
120.112 + f.prev = newNode;
120.113 + size++;
120.114 + modCount++;
120.115 + }
120.116 +
120.117 + /**
120.118 + * Links e as last element.
120.119 + */
120.120 + void linkLast(E e) {
120.121 + final Node<E> l = last;
120.122 + final Node<E> newNode = new Node<E>(l, e, null);
120.123 + last = newNode;
120.124 + if (l == null)
120.125 + first = newNode;
120.126 + else
120.127 + l.next = newNode;
120.128 + size++;
120.129 + modCount++;
120.130 + }
120.131 +
120.132 + /**
120.133 + * Inserts element e before non-null Node succ.
120.134 + */
120.135 + void linkBefore(E e, Node<E> succ) {
120.136 + // assert succ != null;
120.137 + final Node<E> pred = succ.prev;
120.138 + final Node<E> newNode = new Node<E>(pred, e, succ);
120.139 + succ.prev = newNode;
120.140 + if (pred == null)
120.141 + first = newNode;
120.142 + else
120.143 + pred.next = newNode;
120.144 + size++;
120.145 + modCount++;
120.146 + }
120.147 +
120.148 + /**
120.149 + * Unlinks non-null first node f.
120.150 + */
120.151 + private E unlinkFirst(Node<E> f) {
120.152 + // assert f == first && f != null;
120.153 + final E element = f.item;
120.154 + final Node<E> next = f.next;
120.155 + f.item = null;
120.156 + f.next = null; // help GC
120.157 + first = next;
120.158 + if (next == null)
120.159 + last = null;
120.160 + else
120.161 + next.prev = null;
120.162 + size--;
120.163 + modCount++;
120.164 + return element;
120.165 + }
120.166 +
120.167 + /**
120.168 + * Unlinks non-null last node l.
120.169 + */
120.170 + private E unlinkLast(Node<E> l) {
120.171 + // assert l == last && l != null;
120.172 + final E element = l.item;
120.173 + final Node<E> prev = l.prev;
120.174 + l.item = null;
120.175 + l.prev = null; // help GC
120.176 + last = prev;
120.177 + if (prev == null)
120.178 + first = null;
120.179 + else
120.180 + prev.next = null;
120.181 + size--;
120.182 + modCount++;
120.183 + return element;
120.184 + }
120.185 +
120.186 + /**
120.187 + * Unlinks non-null node x.
120.188 + */
120.189 + E unlink(Node<E> x) {
120.190 + // assert x != null;
120.191 + final E element = x.item;
120.192 + final Node<E> next = x.next;
120.193 + final Node<E> prev = x.prev;
120.194 +
120.195 + if (prev == null) {
120.196 + first = next;
120.197 + } else {
120.198 + prev.next = next;
120.199 + x.prev = null;
120.200 + }
120.201 +
120.202 + if (next == null) {
120.203 + last = prev;
120.204 + } else {
120.205 + next.prev = prev;
120.206 + x.next = null;
120.207 + }
120.208 +
120.209 + x.item = null;
120.210 + size--;
120.211 + modCount++;
120.212 + return element;
120.213 + }
120.214 +
120.215 + /**
120.216 * Returns the first element in this list.
120.217 *
120.218 * @return the first element in this list
120.219 * @throws NoSuchElementException if this list is empty
120.220 */
120.221 public E getFirst() {
120.222 - if (size==0)
120.223 + final Node<E> f = first;
120.224 + if (f == null)
120.225 throw new NoSuchElementException();
120.226 -
120.227 - return header.next.element;
120.228 + return f.item;
120.229 }
120.230
120.231 /**
120.232 @@ -135,10 +259,10 @@
120.233 * @throws NoSuchElementException if this list is empty
120.234 */
120.235 public E getLast() {
120.236 - if (size==0)
120.237 + final Node<E> l = last;
120.238 + if (l == null)
120.239 throw new NoSuchElementException();
120.240 -
120.241 - return header.previous.element;
120.242 + return l.item;
120.243 }
120.244
120.245 /**
120.246 @@ -148,7 +272,10 @@
120.247 * @throws NoSuchElementException if this list is empty
120.248 */
120.249 public E removeFirst() {
120.250 - return remove(header.next);
120.251 + final Node<E> f = first;
120.252 + if (f == null)
120.253 + throw new NoSuchElementException();
120.254 + return unlinkFirst(f);
120.255 }
120.256
120.257 /**
120.258 @@ -158,7 +285,10 @@
120.259 * @throws NoSuchElementException if this list is empty
120.260 */
120.261 public E removeLast() {
120.262 - return remove(header.previous);
120.263 + final Node<E> l = last;
120.264 + if (l == null)
120.265 + throw new NoSuchElementException();
120.266 + return unlinkLast(l);
120.267 }
120.268
120.269 /**
120.270 @@ -167,7 +297,7 @@
120.271 * @param e the element to add
120.272 */
120.273 public void addFirst(E e) {
120.274 - addBefore(e, header.next);
120.275 + linkFirst(e);
120.276 }
120.277
120.278 /**
120.279 @@ -178,17 +308,17 @@
120.280 * @param e the element to add
120.281 */
120.282 public void addLast(E e) {
120.283 - addBefore(e, header);
120.284 + linkLast(e);
120.285 }
120.286
120.287 /**
120.288 - * Returns <tt>true</tt> if this list contains the specified element.
120.289 - * More formally, returns <tt>true</tt> if and only if this list contains
120.290 - * at least one element <tt>e</tt> such that
120.291 + * Returns {@code true} if this list contains the specified element.
120.292 + * More formally, returns {@code true} if and only if this list contains
120.293 + * at least one element {@code e} such that
120.294 * <tt>(o==null ? e==null : o.equals(e))</tt>.
120.295 *
120.296 * @param o element whose presence in this list is to be tested
120.297 - * @return <tt>true</tt> if this list contains the specified element
120.298 + * @return {@code true} if this list contains the specified element
120.299 */
120.300 public boolean contains(Object o) {
120.301 return indexOf(o) != -1;
120.302 @@ -209,10 +339,10 @@
120.303 * <p>This method is equivalent to {@link #addLast}.
120.304 *
120.305 * @param e element to be appended to this list
120.306 - * @return <tt>true</tt> (as specified by {@link Collection#add})
120.307 + * @return {@code true} (as specified by {@link Collection#add})
120.308 */
120.309 public boolean add(E e) {
120.310 - addBefore(e, header);
120.311 + linkLast(e);
120.312 return true;
120.313 }
120.314
120.315 @@ -220,27 +350,27 @@
120.316 * Removes the first occurrence of the specified element from this list,
120.317 * if it is present. If this list does not contain the element, it is
120.318 * unchanged. More formally, removes the element with the lowest index
120.319 - * <tt>i</tt> such that
120.320 + * {@code i} such that
120.321 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>
120.322 - * (if such an element exists). Returns <tt>true</tt> if this list
120.323 + * (if such an element exists). Returns {@code true} if this list
120.324 * contained the specified element (or equivalently, if this list
120.325 * changed as a result of the call).
120.326 *
120.327 * @param o element to be removed from this list, if present
120.328 - * @return <tt>true</tt> if this list contained the specified element
120.329 + * @return {@code true} if this list contained the specified element
120.330 */
120.331 public boolean remove(Object o) {
120.332 - if (o==null) {
120.333 - for (Entry<E> e = header.next; e != header; e = e.next) {
120.334 - if (e.element==null) {
120.335 - remove(e);
120.336 + if (o == null) {
120.337 + for (Node<E> x = first; x != null; x = x.next) {
120.338 + if (x.item == null) {
120.339 + unlink(x);
120.340 return true;
120.341 }
120.342 }
120.343 } else {
120.344 - for (Entry<E> e = header.next; e != header; e = e.next) {
120.345 - if (o.equals(e.element)) {
120.346 - remove(e);
120.347 + for (Node<E> x = first; x != null; x = x.next) {
120.348 + if (o.equals(x.item)) {
120.349 + unlink(x);
120.350 return true;
120.351 }
120.352 }
120.353 @@ -257,7 +387,7 @@
120.354 * this list, and it's nonempty.)
120.355 *
120.356 * @param c collection containing elements to be added to this list
120.357 - * @return <tt>true</tt> if this list changed as a result of the call
120.358 + * @return {@code true} if this list changed as a result of the call
120.359 * @throws NullPointerException if the specified collection is null
120.360 */
120.361 public boolean addAll(Collection<? extends E> c) {
120.362 @@ -275,45 +405,66 @@
120.363 * @param index index at which to insert the first element
120.364 * from the specified collection
120.365 * @param c collection containing elements to be added to this list
120.366 - * @return <tt>true</tt> if this list changed as a result of the call
120.367 + * @return {@code true} if this list changed as a result of the call
120.368 * @throws IndexOutOfBoundsException {@inheritDoc}
120.369 * @throws NullPointerException if the specified collection is null
120.370 */
120.371 public boolean addAll(int index, Collection<? extends E> c) {
120.372 - if (index < 0 || index > size)
120.373 - throw new IndexOutOfBoundsException("Index: "+index+
120.374 - ", Size: "+size);
120.375 + checkPositionIndex(index);
120.376 +
120.377 Object[] a = c.toArray();
120.378 int numNew = a.length;
120.379 - if (numNew==0)
120.380 + if (numNew == 0)
120.381 return false;
120.382 - modCount++;
120.383
120.384 - Entry<E> successor = (index==size ? header : entry(index));
120.385 - Entry<E> predecessor = successor.previous;
120.386 - for (int i=0; i<numNew; i++) {
120.387 - Entry<E> e = new Entry<E>((E)a[i], successor, predecessor);
120.388 - predecessor.next = e;
120.389 - predecessor = e;
120.390 + Node<E> pred, succ;
120.391 + if (index == size) {
120.392 + succ = null;
120.393 + pred = last;
120.394 + } else {
120.395 + succ = node(index);
120.396 + pred = succ.prev;
120.397 }
120.398 - successor.previous = predecessor;
120.399 +
120.400 + for (Object o : a) {
120.401 + @SuppressWarnings("unchecked") E e = (E) o;
120.402 + Node<E> newNode = new Node<E>(pred, e, null);
120.403 + if (pred == null)
120.404 + first = newNode;
120.405 + else
120.406 + pred.next = newNode;
120.407 + pred = newNode;
120.408 + }
120.409 +
120.410 + if (succ == null) {
120.411 + last = pred;
120.412 + } else {
120.413 + pred.next = succ;
120.414 + succ.prev = pred;
120.415 + }
120.416
120.417 size += numNew;
120.418 + modCount++;
120.419 return true;
120.420 }
120.421
120.422 /**
120.423 * Removes all of the elements from this list.
120.424 + * The list will be empty after this call returns.
120.425 */
120.426 public void clear() {
120.427 - Entry<E> e = header.next;
120.428 - while (e != header) {
120.429 - Entry<E> next = e.next;
120.430 - e.next = e.previous = null;
120.431 - e.element = null;
120.432 - e = next;
120.433 + // Clearing all of the links between nodes is "unnecessary", but:
120.434 + // - helps a generational GC if the discarded nodes inhabit
120.435 + // more than one generation
120.436 + // - is sure to free memory even if there is a reachable Iterator
120.437 + for (Node<E> x = first; x != null; ) {
120.438 + Node<E> next = x.next;
120.439 + x.item = null;
120.440 + x.next = null;
120.441 + x.prev = null;
120.442 + x = next;
120.443 }
120.444 - header.next = header.previous = header;
120.445 + first = last = null;
120.446 size = 0;
120.447 modCount++;
120.448 }
120.449 @@ -329,7 +480,8 @@
120.450 * @throws IndexOutOfBoundsException {@inheritDoc}
120.451 */
120.452 public E get(int index) {
120.453 - return entry(index).element;
120.454 + checkElementIndex(index);
120.455 + return node(index).item;
120.456 }
120.457
120.458 /**
120.459 @@ -342,9 +494,10 @@
120.460 * @throws IndexOutOfBoundsException {@inheritDoc}
120.461 */
120.462 public E set(int index, E element) {
120.463 - Entry<E> e = entry(index);
120.464 - E oldVal = e.element;
120.465 - e.element = element;
120.466 + checkElementIndex(index);
120.467 + Node<E> x = node(index);
120.468 + E oldVal = x.item;
120.469 + x.item = element;
120.470 return oldVal;
120.471 }
120.472
120.473 @@ -358,7 +511,12 @@
120.474 * @throws IndexOutOfBoundsException {@inheritDoc}
120.475 */
120.476 public void add(int index, E element) {
120.477 - addBefore(element, (index==size ? header : entry(index)));
120.478 + checkPositionIndex(index);
120.479 +
120.480 + if (index == size)
120.481 + linkLast(element);
120.482 + else
120.483 + linkBefore(element, node(index));
120.484 }
120.485
120.486 /**
120.487 @@ -371,34 +529,69 @@
120.488 * @throws IndexOutOfBoundsException {@inheritDoc}
120.489 */
120.490 public E remove(int index) {
120.491 - return remove(entry(index));
120.492 + checkElementIndex(index);
120.493 + return unlink(node(index));
120.494 }
120.495
120.496 /**
120.497 - * Returns the indexed entry.
120.498 + * Tells if the argument is the index of an existing element.
120.499 */
120.500 - private Entry<E> entry(int index) {
120.501 - if (index < 0 || index >= size)
120.502 - throw new IndexOutOfBoundsException("Index: "+index+
120.503 - ", Size: "+size);
120.504 - Entry<E> e = header;
120.505 - if (index < (size >> 1)) {
120.506 - for (int i = 0; i <= index; i++)
120.507 - e = e.next;
120.508 - } else {
120.509 - for (int i = size; i > index; i--)
120.510 - e = e.previous;
120.511 - }
120.512 - return e;
120.513 + private boolean isElementIndex(int index) {
120.514 + return index >= 0 && index < size;
120.515 }
120.516
120.517 + /**
120.518 + * Tells if the argument is the index of a valid position for an
120.519 + * iterator or an add operation.
120.520 + */
120.521 + private boolean isPositionIndex(int index) {
120.522 + return index >= 0 && index <= size;
120.523 + }
120.524 +
120.525 + /**
120.526 + * Constructs an IndexOutOfBoundsException detail message.
120.527 + * Of the many possible refactorings of the error handling code,
120.528 + * this "outlining" performs best with both server and client VMs.
120.529 + */
120.530 + private String outOfBoundsMsg(int index) {
120.531 + return "Index: "+index+", Size: "+size;
120.532 + }
120.533 +
120.534 + private void checkElementIndex(int index) {
120.535 + if (!isElementIndex(index))
120.536 + throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
120.537 + }
120.538 +
120.539 + private void checkPositionIndex(int index) {
120.540 + if (!isPositionIndex(index))
120.541 + throw new IndexOutOfBoundsException(outOfBoundsMsg(index));
120.542 + }
120.543 +
120.544 + /**
120.545 + * Returns the (non-null) Node at the specified element index.
120.546 + */
120.547 + Node<E> node(int index) {
120.548 + // assert isElementIndex(index);
120.549 +
120.550 + if (index < (size >> 1)) {
120.551 + Node<E> x = first;
120.552 + for (int i = 0; i < index; i++)
120.553 + x = x.next;
120.554 + return x;
120.555 + } else {
120.556 + Node<E> x = last;
120.557 + for (int i = size - 1; i > index; i--)
120.558 + x = x.prev;
120.559 + return x;
120.560 + }
120.561 + }
120.562
120.563 // Search Operations
120.564
120.565 /**
120.566 * Returns the index of the first occurrence of the specified element
120.567 * in this list, or -1 if this list does not contain the element.
120.568 - * More formally, returns the lowest index <tt>i</tt> such that
120.569 + * More formally, returns the lowest index {@code i} such that
120.570 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
120.571 * or -1 if there is no such index.
120.572 *
120.573 @@ -408,15 +601,15 @@
120.574 */
120.575 public int indexOf(Object o) {
120.576 int index = 0;
120.577 - if (o==null) {
120.578 - for (Entry e = header.next; e != header; e = e.next) {
120.579 - if (e.element==null)
120.580 + if (o == null) {
120.581 + for (Node<E> x = first; x != null; x = x.next) {
120.582 + if (x.item == null)
120.583 return index;
120.584 index++;
120.585 }
120.586 } else {
120.587 - for (Entry e = header.next; e != header; e = e.next) {
120.588 - if (o.equals(e.element))
120.589 + for (Node<E> x = first; x != null; x = x.next) {
120.590 + if (o.equals(x.item))
120.591 return index;
120.592 index++;
120.593 }
120.594 @@ -427,7 +620,7 @@
120.595 /**
120.596 * Returns the index of the last occurrence of the specified element
120.597 * in this list, or -1 if this list does not contain the element.
120.598 - * More formally, returns the highest index <tt>i</tt> such that
120.599 + * More formally, returns the highest index {@code i} such that
120.600 * <tt>(o==null ? get(i)==null : o.equals(get(i)))</tt>,
120.601 * or -1 if there is no such index.
120.602 *
120.603 @@ -437,16 +630,16 @@
120.604 */
120.605 public int lastIndexOf(Object o) {
120.606 int index = size;
120.607 - if (o==null) {
120.608 - for (Entry e = header.previous; e != header; e = e.previous) {
120.609 + if (o == null) {
120.610 + for (Node<E> x = last; x != null; x = x.prev) {
120.611 index--;
120.612 - if (e.element==null)
120.613 + if (x.item == null)
120.614 return index;
120.615 }
120.616 } else {
120.617 - for (Entry e = header.previous; e != header; e = e.previous) {
120.618 + for (Node<E> x = last; x != null; x = x.prev) {
120.619 index--;
120.620 - if (o.equals(e.element))
120.621 + if (o.equals(x.item))
120.622 return index;
120.623 }
120.624 }
120.625 @@ -457,17 +650,18 @@
120.626
120.627 /**
120.628 * Retrieves, but does not remove, the head (first element) of this list.
120.629 - * @return the head of this list, or <tt>null</tt> if this list is empty
120.630 + *
120.631 + * @return the head of this list, or {@code null} if this list is empty
120.632 * @since 1.5
120.633 */
120.634 public E peek() {
120.635 - if (size==0)
120.636 - return null;
120.637 - return getFirst();
120.638 + final Node<E> f = first;
120.639 + return (f == null) ? null : f.item;
120.640 }
120.641
120.642 /**
120.643 * Retrieves, but does not remove, the head (first element) of this list.
120.644 + *
120.645 * @return the head of this list
120.646 * @throws NoSuchElementException if this list is empty
120.647 * @since 1.5
120.648 @@ -477,14 +671,14 @@
120.649 }
120.650
120.651 /**
120.652 - * Retrieves and removes the head (first element) of this list
120.653 - * @return the head of this list, or <tt>null</tt> if this list is empty
120.654 + * Retrieves and removes the head (first element) of this list.
120.655 + *
120.656 + * @return the head of this list, or {@code null} if this list is empty
120.657 * @since 1.5
120.658 */
120.659 public E poll() {
120.660 - if (size==0)
120.661 - return null;
120.662 - return removeFirst();
120.663 + final Node<E> f = first;
120.664 + return (f == null) ? null : unlinkFirst(f);
120.665 }
120.666
120.667 /**
120.668 @@ -502,7 +696,7 @@
120.669 * Adds the specified element as the tail (last element) of this list.
120.670 *
120.671 * @param e the element to add
120.672 - * @return <tt>true</tt> (as specified by {@link Queue#offer})
120.673 + * @return {@code true} (as specified by {@link Queue#offer})
120.674 * @since 1.5
120.675 */
120.676 public boolean offer(E e) {
120.677 @@ -514,7 +708,7 @@
120.678 * Inserts the specified element at the front of this list.
120.679 *
120.680 * @param e the element to insert
120.681 - * @return <tt>true</tt> (as specified by {@link Deque#offerFirst})
120.682 + * @return {@code true} (as specified by {@link Deque#offerFirst})
120.683 * @since 1.6
120.684 */
120.685 public boolean offerFirst(E e) {
120.686 @@ -526,7 +720,7 @@
120.687 * Inserts the specified element at the end of this list.
120.688 *
120.689 * @param e the element to insert
120.690 - * @return <tt>true</tt> (as specified by {@link Deque#offerLast})
120.691 + * @return {@code true} (as specified by {@link Deque#offerLast})
120.692 * @since 1.6
120.693 */
120.694 public boolean offerLast(E e) {
120.695 @@ -536,58 +730,54 @@
120.696
120.697 /**
120.698 * Retrieves, but does not remove, the first element of this list,
120.699 - * or returns <tt>null</tt> if this list is empty.
120.700 + * or returns {@code null} if this list is empty.
120.701 *
120.702 - * @return the first element of this list, or <tt>null</tt>
120.703 + * @return the first element of this list, or {@code null}
120.704 * if this list is empty
120.705 * @since 1.6
120.706 */
120.707 public E peekFirst() {
120.708 - if (size==0)
120.709 - return null;
120.710 - return getFirst();
120.711 - }
120.712 + final Node<E> f = first;
120.713 + return (f == null) ? null : f.item;
120.714 + }
120.715
120.716 /**
120.717 * Retrieves, but does not remove, the last element of this list,
120.718 - * or returns <tt>null</tt> if this list is empty.
120.719 + * or returns {@code null} if this list is empty.
120.720 *
120.721 - * @return the last element of this list, or <tt>null</tt>
120.722 + * @return the last element of this list, or {@code null}
120.723 * if this list is empty
120.724 * @since 1.6
120.725 */
120.726 public E peekLast() {
120.727 - if (size==0)
120.728 - return null;
120.729 - return getLast();
120.730 + final Node<E> l = last;
120.731 + return (l == null) ? null : l.item;
120.732 }
120.733
120.734 /**
120.735 * Retrieves and removes the first element of this list,
120.736 - * or returns <tt>null</tt> if this list is empty.
120.737 + * or returns {@code null} if this list is empty.
120.738 *
120.739 - * @return the first element of this list, or <tt>null</tt> if
120.740 + * @return the first element of this list, or {@code null} if
120.741 * this list is empty
120.742 * @since 1.6
120.743 */
120.744 public E pollFirst() {
120.745 - if (size==0)
120.746 - return null;
120.747 - return removeFirst();
120.748 + final Node<E> f = first;
120.749 + return (f == null) ? null : unlinkFirst(f);
120.750 }
120.751
120.752 /**
120.753 * Retrieves and removes the last element of this list,
120.754 - * or returns <tt>null</tt> if this list is empty.
120.755 + * or returns {@code null} if this list is empty.
120.756 *
120.757 - * @return the last element of this list, or <tt>null</tt> if
120.758 + * @return the last element of this list, or {@code null} if
120.759 * this list is empty
120.760 * @since 1.6
120.761 */
120.762 public E pollLast() {
120.763 - if (size==0)
120.764 - return null;
120.765 - return removeLast();
120.766 + final Node<E> l = last;
120.767 + return (l == null) ? null : unlinkLast(l);
120.768 }
120.769
120.770 /**
120.771 @@ -624,7 +814,7 @@
120.772 * does not contain the element, it is unchanged.
120.773 *
120.774 * @param o element to be removed from this list, if present
120.775 - * @return <tt>true</tt> if the list contained the specified element
120.776 + * @return {@code true} if the list contained the specified element
120.777 * @since 1.6
120.778 */
120.779 public boolean removeFirstOccurrence(Object o) {
120.780 @@ -637,21 +827,21 @@
120.781 * does not contain the element, it is unchanged.
120.782 *
120.783 * @param o element to be removed from this list, if present
120.784 - * @return <tt>true</tt> if the list contained the specified element
120.785 + * @return {@code true} if the list contained the specified element
120.786 * @since 1.6
120.787 */
120.788 public boolean removeLastOccurrence(Object o) {
120.789 - if (o==null) {
120.790 - for (Entry<E> e = header.previous; e != header; e = e.previous) {
120.791 - if (e.element==null) {
120.792 - remove(e);
120.793 + if (o == null) {
120.794 + for (Node<E> x = last; x != null; x = x.prev) {
120.795 + if (x.item == null) {
120.796 + unlink(x);
120.797 return true;
120.798 }
120.799 }
120.800 } else {
120.801 - for (Entry<E> e = header.previous; e != header; e = e.previous) {
120.802 - if (o.equals(e.element)) {
120.803 - remove(e);
120.804 + for (Node<E> x = last; x != null; x = x.prev) {
120.805 + if (o.equals(x.item)) {
120.806 + unlink(x);
120.807 return true;
120.808 }
120.809 }
120.810 @@ -662,76 +852,68 @@
120.811 /**
120.812 * Returns a list-iterator of the elements in this list (in proper
120.813 * sequence), starting at the specified position in the list.
120.814 - * Obeys the general contract of <tt>List.listIterator(int)</tt>.<p>
120.815 + * Obeys the general contract of {@code List.listIterator(int)}.<p>
120.816 *
120.817 * The list-iterator is <i>fail-fast</i>: if the list is structurally
120.818 * modified at any time after the Iterator is created, in any way except
120.819 - * through the list-iterator's own <tt>remove</tt> or <tt>add</tt>
120.820 + * through the list-iterator's own {@code remove} or {@code add}
120.821 * methods, the list-iterator will throw a
120.822 - * <tt>ConcurrentModificationException</tt>. Thus, in the face of
120.823 + * {@code ConcurrentModificationException}. Thus, in the face of
120.824 * concurrent modification, the iterator fails quickly and cleanly, rather
120.825 * than risking arbitrary, non-deterministic behavior at an undetermined
120.826 * time in the future.
120.827 *
120.828 * @param index index of the first element to be returned from the
120.829 - * list-iterator (by a call to <tt>next</tt>)
120.830 + * list-iterator (by a call to {@code next})
120.831 * @return a ListIterator of the elements in this list (in proper
120.832 * sequence), starting at the specified position in the list
120.833 * @throws IndexOutOfBoundsException {@inheritDoc}
120.834 * @see List#listIterator(int)
120.835 */
120.836 public ListIterator<E> listIterator(int index) {
120.837 + checkPositionIndex(index);
120.838 return new ListItr(index);
120.839 }
120.840
120.841 private class ListItr implements ListIterator<E> {
120.842 - private Entry<E> lastReturned = header;
120.843 - private Entry<E> next;
120.844 + private Node<E> lastReturned = null;
120.845 + private Node<E> next;
120.846 private int nextIndex;
120.847 private int expectedModCount = modCount;
120.848
120.849 ListItr(int index) {
120.850 - if (index < 0 || index > size)
120.851 - throw new IndexOutOfBoundsException("Index: "+index+
120.852 - ", Size: "+size);
120.853 - if (index < (size >> 1)) {
120.854 - next = header.next;
120.855 - for (nextIndex=0; nextIndex<index; nextIndex++)
120.856 - next = next.next;
120.857 - } else {
120.858 - next = header;
120.859 - for (nextIndex=size; nextIndex>index; nextIndex--)
120.860 - next = next.previous;
120.861 - }
120.862 + // assert isPositionIndex(index);
120.863 + next = (index == size) ? null : node(index);
120.864 + nextIndex = index;
120.865 }
120.866
120.867 public boolean hasNext() {
120.868 - return nextIndex != size;
120.869 + return nextIndex < size;
120.870 }
120.871
120.872 public E next() {
120.873 checkForComodification();
120.874 - if (nextIndex == size)
120.875 + if (!hasNext())
120.876 throw new NoSuchElementException();
120.877
120.878 lastReturned = next;
120.879 next = next.next;
120.880 nextIndex++;
120.881 - return lastReturned.element;
120.882 + return lastReturned.item;
120.883 }
120.884
120.885 public boolean hasPrevious() {
120.886 - return nextIndex != 0;
120.887 + return nextIndex > 0;
120.888 }
120.889
120.890 public E previous() {
120.891 - if (nextIndex == 0)
120.892 + checkForComodification();
120.893 + if (!hasPrevious())
120.894 throw new NoSuchElementException();
120.895
120.896 - lastReturned = next = next.previous;
120.897 + lastReturned = next = (next == null) ? last : next.prev;
120.898 nextIndex--;
120.899 - checkForComodification();
120.900 - return lastReturned.element;
120.901 + return lastReturned.item;
120.902 }
120.903
120.904 public int nextIndex() {
120.905 @@ -739,36 +921,38 @@
120.906 }
120.907
120.908 public int previousIndex() {
120.909 - return nextIndex-1;
120.910 + return nextIndex - 1;
120.911 }
120.912
120.913 public void remove() {
120.914 checkForComodification();
120.915 - Entry<E> lastNext = lastReturned.next;
120.916 - try {
120.917 - LinkedList.this.remove(lastReturned);
120.918 - } catch (NoSuchElementException e) {
120.919 + if (lastReturned == null)
120.920 throw new IllegalStateException();
120.921 - }
120.922 - if (next==lastReturned)
120.923 +
120.924 + Node<E> lastNext = lastReturned.next;
120.925 + unlink(lastReturned);
120.926 + if (next == lastReturned)
120.927 next = lastNext;
120.928 else
120.929 nextIndex--;
120.930 - lastReturned = header;
120.931 + lastReturned = null;
120.932 expectedModCount++;
120.933 }
120.934
120.935 public void set(E e) {
120.936 - if (lastReturned == header)
120.937 + if (lastReturned == null)
120.938 throw new IllegalStateException();
120.939 checkForComodification();
120.940 - lastReturned.element = e;
120.941 + lastReturned.item = e;
120.942 }
120.943
120.944 public void add(E e) {
120.945 checkForComodification();
120.946 - lastReturned = header;
120.947 - addBefore(e, next);
120.948 + lastReturned = null;
120.949 + if (next == null)
120.950 + linkLast(e);
120.951 + else
120.952 + linkBefore(e, next);
120.953 nextIndex++;
120.954 expectedModCount++;
120.955 }
120.956 @@ -779,41 +963,18 @@
120.957 }
120.958 }
120.959
120.960 - private static class Entry<E> {
120.961 - E element;
120.962 - Entry<E> next;
120.963 - Entry<E> previous;
120.964 + private static class Node<E> {
120.965 + E item;
120.966 + Node<E> next;
120.967 + Node<E> prev;
120.968
120.969 - Entry(E element, Entry<E> next, Entry<E> previous) {
120.970 - this.element = element;
120.971 + Node(Node<E> prev, E element, Node<E> next) {
120.972 + this.item = element;
120.973 this.next = next;
120.974 - this.previous = previous;
120.975 + this.prev = prev;
120.976 }
120.977 }
120.978
120.979 - private Entry<E> addBefore(E e, Entry<E> entry) {
120.980 - Entry<E> newEntry = new Entry<E>(e, entry, entry.previous);
120.981 - newEntry.previous.next = newEntry;
120.982 - newEntry.next.previous = newEntry;
120.983 - size++;
120.984 - modCount++;
120.985 - return newEntry;
120.986 - }
120.987 -
120.988 - private E remove(Entry<E> e) {
120.989 - if (e == header)
120.990 - throw new NoSuchElementException();
120.991 -
120.992 - E result = e.element;
120.993 - e.previous.next = e.next;
120.994 - e.next.previous = e.previous;
120.995 - e.next = e.previous = null;
120.996 - e.element = null;
120.997 - size--;
120.998 - modCount++;
120.999 - return result;
120.1000 - }
120.1001 -
120.1002 /**
120.1003 * @since 1.6
120.1004 */
120.1005 @@ -821,9 +982,11 @@
120.1006 return new DescendingIterator();
120.1007 }
120.1008
120.1009 - /** Adapter to provide descending iterators via ListItr.previous */
120.1010 - private class DescendingIterator implements Iterator {
120.1011 - final ListItr itr = new ListItr(size());
120.1012 + /**
120.1013 + * Adapter to provide descending iterators via ListItr.previous
120.1014 + */
120.1015 + private class DescendingIterator implements Iterator<E> {
120.1016 + private final ListItr itr = new ListItr(size());
120.1017 public boolean hasNext() {
120.1018 return itr.hasPrevious();
120.1019 }
120.1020 @@ -835,29 +998,32 @@
120.1021 }
120.1022 }
120.1023
120.1024 - /**
120.1025 - * Returns a shallow copy of this <tt>LinkedList</tt>. (The elements
120.1026 - * themselves are not cloned.)
120.1027 - *
120.1028 - * @return a shallow copy of this <tt>LinkedList</tt> instance
120.1029 - */
120.1030 - public Object clone() {
120.1031 - LinkedList<E> clone = null;
120.1032 + @SuppressWarnings("unchecked")
120.1033 + private LinkedList<E> superClone() {
120.1034 try {
120.1035 - clone = (LinkedList<E>) super.clone();
120.1036 + return (LinkedList<E>) super.clone();
120.1037 } catch (CloneNotSupportedException e) {
120.1038 throw new InternalError();
120.1039 }
120.1040 + }
120.1041 +
120.1042 + /**
120.1043 + * Returns a shallow copy of this {@code LinkedList}. (The elements
120.1044 + * themselves are not cloned.)
120.1045 + *
120.1046 + * @return a shallow copy of this {@code LinkedList} instance
120.1047 + */
120.1048 + public Object clone() {
120.1049 + LinkedList<E> clone = superClone();
120.1050
120.1051 // Put clone into "virgin" state
120.1052 - clone.header = new Entry<E>(null, null, null);
120.1053 - clone.header.next = clone.header.previous = clone.header;
120.1054 + clone.first = clone.last = null;
120.1055 clone.size = 0;
120.1056 clone.modCount = 0;
120.1057
120.1058 // Initialize clone with our elements
120.1059 - for (Entry<E> e = header.next; e != header; e = e.next)
120.1060 - clone.add(e.element);
120.1061 + for (Node<E> x = first; x != null; x = x.next)
120.1062 + clone.add(x.item);
120.1063
120.1064 return clone;
120.1065 }
120.1066 @@ -879,8 +1045,8 @@
120.1067 public Object[] toArray() {
120.1068 Object[] result = new Object[size];
120.1069 int i = 0;
120.1070 - for (Entry<E> e = header.next; e != header; e = e.next)
120.1071 - result[i++] = e.element;
120.1072 + for (Node<E> x = first; x != null; x = x.next)
120.1073 + result[i++] = x.item;
120.1074 return result;
120.1075 }
120.1076
120.1077 @@ -894,7 +1060,7 @@
120.1078 *
120.1079 * <p>If the list fits in the specified array with room to spare (i.e.,
120.1080 * the array has more elements than the list), the element in the array
120.1081 - * immediately following the end of the list is set to <tt>null</tt>.
120.1082 + * immediately following the end of the list is set to {@code null}.
120.1083 * (This is useful in determining the length of the list <i>only</i> if
120.1084 * the caller knows that the list does not contain any null elements.)
120.1085 *
120.1086 @@ -903,15 +1069,15 @@
120.1087 * precise control over the runtime type of the output array, and may,
120.1088 * under certain circumstances, be used to save allocation costs.
120.1089 *
120.1090 - * <p>Suppose <tt>x</tt> is a list known to contain only strings.
120.1091 + * <p>Suppose {@code x} is a list known to contain only strings.
120.1092 * The following code can be used to dump the list into a newly
120.1093 - * allocated array of <tt>String</tt>:
120.1094 + * allocated array of {@code String}:
120.1095 *
120.1096 * <pre>
120.1097 * String[] y = x.toArray(new String[0]);</pre>
120.1098 *
120.1099 - * Note that <tt>toArray(new Object[0])</tt> is identical in function to
120.1100 - * <tt>toArray()</tt>.
120.1101 + * Note that {@code toArray(new Object[0])} is identical in function to
120.1102 + * {@code toArray()}.
120.1103 *
120.1104 * @param a the array into which the elements of the list are to
120.1105 * be stored, if it is big enough; otherwise, a new array of the
120.1106 @@ -922,14 +1088,15 @@
120.1107 * this list
120.1108 * @throws NullPointerException if the specified array is null
120.1109 */
120.1110 + @SuppressWarnings("unchecked")
120.1111 public <T> T[] toArray(T[] a) {
120.1112 if (a.length < size)
120.1113 a = (T[])java.lang.reflect.Array.newInstance(
120.1114 a.getClass().getComponentType(), size);
120.1115 int i = 0;
120.1116 Object[] result = a;
120.1117 - for (Entry<E> e = header.next; e != header; e = e.next)
120.1118 - result[i++] = e.element;
120.1119 + for (Node<E> x = first; x != null; x = x.next)
120.1120 + result[i++] = x.item;
120.1121
120.1122 if (a.length > size)
120.1123 a[size] = null;
120.1124 @@ -940,8 +1107,8 @@
120.1125 private static final long serialVersionUID = 876323262645176354L;
120.1126
120.1127 /**
120.1128 - * Save the state of this <tt>LinkedList</tt> instance to a stream (that
120.1129 - * is, serialize it).
120.1130 + * Saves the state of this {@code LinkedList} instance to a stream
120.1131 + * (that is, serializes it).
120.1132 *
120.1133 * @serialData The size of the list (the number of elements it
120.1134 * contains) is emitted (int), followed by all of its
120.1135 @@ -956,14 +1123,15 @@
120.1136 s.writeInt(size);
120.1137
120.1138 // Write out all elements in the proper order.
120.1139 - for (Entry e = header.next; e != header; e = e.next)
120.1140 - s.writeObject(e.element);
120.1141 + for (Node<E> x = first; x != null; x = x.next)
120.1142 + s.writeObject(x.item);
120.1143 }
120.1144
120.1145 /**
120.1146 - * Reconstitute this <tt>LinkedList</tt> instance from a stream (that is
120.1147 - * deserialize it).
120.1148 + * Reconstitutes this {@code LinkedList} instance from a stream
120.1149 + * (that is, deserializes it).
120.1150 */
120.1151 + @SuppressWarnings("unchecked")
120.1152 private void readObject(java.io.ObjectInputStream s)
120.1153 throws java.io.IOException, ClassNotFoundException {
120.1154 // Read in any hidden serialization magic
120.1155 @@ -972,12 +1140,8 @@
120.1156 // Read in size
120.1157 int size = s.readInt();
120.1158
120.1159 - // Initialize header
120.1160 - header = new Entry<E>(null, null, null);
120.1161 - header.next = header.previous = header;
120.1162 -
120.1163 // Read in all elements in the proper order.
120.1164 - for (int i=0; i<size; i++)
120.1165 - addBefore((E)s.readObject(), header);
120.1166 + for (int i = 0; i < size; i++)
120.1167 + linkLast((E)s.readObject());
120.1168 }
120.1169 }
121.1 --- a/src/share/classes/java/util/Objects.java Mon Nov 23 10:04:47 2009 +0000
121.2 +++ b/src/share/classes/java/util/Objects.java Wed Nov 25 11:08:25 2009 -0800
121.3 @@ -33,7 +33,7 @@
121.4 *
121.5 * @since 1.7
121.6 */
121.7 -public class Objects {
121.8 +public final class Objects {
121.9 private Objects() {
121.10 throw new AssertionError("No java.util.Objects instances for you!");
121.11 }
121.12 @@ -57,6 +57,32 @@
121.13 return (a == b) || (a != null && a.equals(b));
121.14 }
121.15
121.16 + /**
121.17 + * Returns {@code true} if the arguments are deeply equal to each other
121.18 + * and {@code false} otherwise.
121.19 + *
121.20 + * Two {@code null} values are deeply equal. If both arguments are
121.21 + * arrays, the algorithm in {@link Arrays#deepEquals(Object[],
121.22 + * Object[]) Arrays.deepEquals} is used to determine equality.
121.23 + * Otherwise, equality is determined by using the {@link
121.24 + * Object#equals equals} method of the first argument.
121.25 + *
121.26 + * @param a an object
121.27 + * @param b an object to be compared with {@code a} for deep equality
121.28 + * @return {@code true} if the arguments are deeply equal to each other
121.29 + * and {@code false} otherwise
121.30 + * @see Arrays#deepEquals(Object[], Object[])
121.31 + * @see Objects#equals(Object, Object)
121.32 + */
121.33 + public static boolean deepEquals(Object a, Object b) {
121.34 + if (a == b)
121.35 + return true;
121.36 + else if (a == null || b == null)
121.37 + return false;
121.38 + else
121.39 + return Arrays.deepEquals0(a, b);
121.40 + }
121.41 +
121.42 /**
121.43 * Returns the hash code of a non-{@code null} argument and 0 for
121.44 * a {@code null} argument.
121.45 @@ -70,6 +96,36 @@
121.46 return o != null ? o.hashCode() : 0;
121.47 }
121.48
121.49 + /**
121.50 + * Generates a hash code for a sequence of input values. The hash
121.51 + * code is generated as if all the input values were placed into an
121.52 + * array, and that array were hashed by calling {@link
121.53 + * Arrays#hashCode(Object[])}.
121.54 + *
121.55 + * <p>This method is useful for implementing {@link
121.56 + * Object#hashCode()} on objects containing multiple fields. For
121.57 + * example, if an object that has three fields, {@code x}, {@code
121.58 + * y}, and {@code z}, one could write:
121.59 + *
121.60 + * <blockquote><pre>
121.61 + * @Override public int hashCode() {
121.62 + * return Objects.hash(x, y, z);
121.63 + * }
121.64 + * </pre></blockquote>
121.65 + *
121.66 + * <b>Warning: When a single object reference is supplied, the returned
121.67 + * value does not equal the hash code of that object reference.</b> This
121.68 + * value can be computed by calling {@link #hashCode(Object)}.
121.69 + *
121.70 + * @param values the values to be hashed
121.71 + * @return a hash value of the sequence of input values
121.72 + * @see Arrays#hashCode
121.73 + * @see List#hashCode
121.74 + */
121.75 + public static int hash(Object... values) {
121.76 + return Arrays.hashCode(values);
121.77 + }
121.78 +
121.79 /**
121.80 * Returns the result of calling {@code toString} for a non-{@code
121.81 * null} argument and {@code "null"} for a {@code null} argument.
121.82 @@ -85,6 +141,23 @@
121.83 }
121.84
121.85 /**
121.86 + * Returns the result of calling {@code toString} on the first
121.87 + * argument if the first argument is not {@code null} and returns
121.88 + * the second argument otherwise.
121.89 + *
121.90 + * @param o an object
121.91 + * @param nullDefault string to return if the first argument is
121.92 + * {@code null}
121.93 + * @return the result of calling {@code toString} on the first
121.94 + * argument if it is not {@code null} and the second argument
121.95 + * otherwise.
121.96 + * @see Objects#toString(Object)
121.97 + */
121.98 + public static String toString(Object o, String nullDefault) {
121.99 + return (o != null) ? o.toString() : nullDefault;
121.100 + }
121.101 +
121.102 + /**
121.103 * Returns 0 if the arguments are identical and {@code
121.104 * c.compare(a, b)} otherwise.
121.105 * Consequently, if both arguments are {@code null} 0
122.1 --- a/src/share/classes/java/util/jar/JarFile.java Mon Nov 23 10:04:47 2009 +0000
122.2 +++ b/src/share/classes/java/util/jar/JarFile.java Wed Nov 25 11:08:25 2009 -0800
122.3 @@ -1,5 +1,5 @@
122.4 /*
122.5 - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
122.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
122.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
122.8 *
122.9 * This code is free software; you can redistribute it and/or modify it
122.10 @@ -297,6 +297,7 @@
122.11 String name = names[i].toUpperCase(Locale.ENGLISH);
122.12 if (name.endsWith(".DSA") ||
122.13 name.endsWith(".RSA") ||
122.14 + name.endsWith(".EC") ||
122.15 name.endsWith(".SF")) {
122.16 // Assume since we found a signature-related file
122.17 // that the jar is signed and that we therefore
123.1 --- a/src/share/classes/java/util/jar/JarVerifier.java Mon Nov 23 10:04:47 2009 +0000
123.2 +++ b/src/share/classes/java/util/jar/JarVerifier.java Wed Nov 25 11:08:25 2009 -0800
123.3 @@ -1,5 +1,5 @@
123.4 /*
123.5 - * Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
123.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
123.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
123.8 *
123.9 * This code is free software; you can redistribute it and/or modify it
123.10 @@ -50,7 +50,7 @@
123.11 private Hashtable verifiedSigners;
123.12
123.13 /* a table mapping names to code signers, for jar entries that have
123.14 - passed the .SF/.DSA -> MANIFEST check */
123.15 + passed the .SF/.DSA/.EC -> MANIFEST check */
123.16 private Hashtable sigFileSigners;
123.17
123.18 /* a hash table to hold .SF bytes */
123.19 @@ -111,7 +111,7 @@
123.20 /*
123.21 * Assumptions:
123.22 * 1. The manifest should be the first entry in the META-INF directory.
123.23 - * 2. The .SF/.DSA files follow the manifest, before any normal entries
123.24 + * 2. The .SF/.DSA/.EC files follow the manifest, before any normal entries
123.25 * 3. Any of the following will throw a SecurityException:
123.26 * a. digest mismatch between a manifest section and
123.27 * the SF section.
123.28 @@ -129,7 +129,7 @@
123.29 }
123.30
123.31 if (SignatureFileVerifier.isBlockOrSF(uname)) {
123.32 - /* We parse only DSA or RSA PKCS7 blocks. */
123.33 + /* We parse only DSA, RSA or EC PKCS7 blocks. */
123.34 parsingBlockOrSF = true;
123.35 baos.reset();
123.36 mev.setEntry(null, je);
124.1 --- a/src/share/classes/java/util/logging/LogManager.java Mon Nov 23 10:04:47 2009 +0000
124.2 +++ b/src/share/classes/java/util/logging/LogManager.java Wed Nov 25 11:08:25 2009 -0800
124.3 @@ -1039,12 +1039,16 @@
124.4
124.5 /**
124.6 * Returns <tt>LoggingMXBean</tt> for managing loggers.
124.7 - * The <tt>LoggingMXBean</tt> can also obtained from the
124.8 - * {@link java.lang.management.ManagementFactory#getPlatformMBeanServer
124.9 - * platform <tt>MBeanServer</tt>} method.
124.10 + * An alternative way to manage loggers is using
124.11 + * the {@link java.lang.management.ManagementFactory#getPlatformMXBeans(Class)
124.12 + * ManagementFactory.getPlatformMXBeans} method as follows:
124.13 + * <pre>
124.14 + * List<{@link PlatformLoggingMXBean}> result = ManagementFactory.getPlatformMXBeans(PlatformLoggingMXBean.class);
124.15 + * </pre>
124.16 *
124.17 * @return a {@link LoggingMXBean} object.
124.18 *
124.19 + * @see PlatformLoggingMXBean
124.20 * @see java.lang.management.ManagementFactory
124.21 * @since 1.5
124.22 */
125.1 --- a/src/share/classes/java/util/logging/Logging.java Mon Nov 23 10:04:47 2009 +0000
125.2 +++ b/src/share/classes/java/util/logging/Logging.java Wed Nov 25 11:08:25 2009 -0800
125.3 @@ -29,8 +29,6 @@
125.4 import java.util.List;
125.5 import java.util.ArrayList;
125.6
125.7 -import javax.management.ObjectName;
125.8 -
125.9 /**
125.10 * Logging is the implementation class of LoggingMXBean.
125.11 *
125.12 @@ -116,8 +114,4 @@
125.13 return p.getName();
125.14 }
125.15 }
125.16 -
125.17 - public ObjectName getObjectName() {
125.18 - return ObjectName.valueOf(LogManager.LOGGING_MXBEAN_NAME);
125.19 - }
125.20 }
126.1 --- a/src/share/classes/java/util/logging/LoggingMXBean.java Mon Nov 23 10:04:47 2009 +0000
126.2 +++ b/src/share/classes/java/util/logging/LoggingMXBean.java Wed Nov 25 11:08:25 2009 -0800
126.3 @@ -25,7 +25,6 @@
126.4
126.5 package java.util.logging;
126.6
126.7 -import java.lang.management.PlatformManagedObject;
126.8
126.9 /**
126.10 * The management interface for the logging facility.
126.11 @@ -35,27 +34,26 @@
126.12 * <a href="../../lang/management/ManagementFactory.html#MXBean">MXBean</a>
126.13 * can be obtained by calling
126.14 * the {@link LogManager#getLoggingMXBean} method or from the
126.15 - * {@link java.lang.management.ManagementFactory#getPlatformMBeanServer
126.16 - * platform <tt>MBeanServer</tt>} method.
126.17 + * {@linkplain java.lang.management.ManagementFactory#getPlatformMBeanServer
126.18 + * platform <tt>MBeanServer</tt>}.
126.19 *
126.20 - * <p>The {@link javax.management.ObjectName ObjectName} for uniquely
126.21 + * The {@link javax.management.ObjectName ObjectName} for uniquely
126.22 * identifying the <tt>LoggingMXBean</tt> within an MBeanServer is:
126.23 * <blockquote>
126.24 * {@link LogManager#LOGGING_MXBEAN_NAME
126.25 * <tt>java.util.logging:type=Logging</tt>}
126.26 * </blockquote>
126.27 *
126.28 - * It can be obtained by calling the
126.29 - * {@link PlatformManagedObject#getObjectName} method.
126.30 - *
126.31 - * @see java.lang.management.ManagementFactory#getPlatformMXBeans(Class)
126.32 + * The instance registered in the platform <tt>MBeanServer</tt> with
126.33 + * this {@code ObjectName} is also a {@link PlatformLoggingMXBean}.
126.34 *
126.35 * @author Ron Mann
126.36 * @author Mandy Chung
126.37 * @since 1.5
126.38 *
126.39 + * @see PlatformLoggingMXBean
126.40 */
126.41 -public interface LoggingMXBean extends PlatformManagedObject {
126.42 +public interface LoggingMXBean {
126.43
126.44 /**
126.45 * Returns the list of currently registered loggers. This method
127.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
127.2 +++ b/src/share/classes/java/util/logging/LoggingProxyImpl.java Wed Nov 25 11:08:25 2009 -0800
127.3 @@ -0,0 +1,102 @@
127.4 +/*
127.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
127.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
127.7 + *
127.8 + * This code is free software; you can redistribute it and/or modify it
127.9 + * under the terms of the GNU General Public License version 2 only, as
127.10 + * published by the Free Software Foundation. Sun designates this
127.11 + * particular file as subject to the "Classpath" exception as provided
127.12 + * by Sun in the LICENSE file that accompanied this code.
127.13 + *
127.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
127.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
127.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
127.17 + * version 2 for more details (a copy is included in the LICENSE file that
127.18 + * accompanied this code).
127.19 + *
127.20 + * You should have received a copy of the GNU General Public License version
127.21 + * 2 along with this work; if not, write to the Free Software Foundation,
127.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
127.23 + *
127.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
127.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
127.26 + * have any questions.
127.27 + */
127.28 +
127.29 +package java.util.logging;
127.30 +
127.31 +import sun.util.logging.LoggingProxy;
127.32 +
127.33 +/**
127.34 + * Implementation of LoggingProxy when java.util.logging classes exist.
127.35 + */
127.36 +class LoggingProxyImpl implements LoggingProxy {
127.37 + static final LoggingProxy INSTANCE = new LoggingProxyImpl();
127.38 +
127.39 + private LoggingProxyImpl() { }
127.40 +
127.41 + @Override
127.42 + public Object getLogger(String name) {
127.43 + return Logger.getLogger(name);
127.44 + }
127.45 +
127.46 + @Override
127.47 + public Object getLevel(Object logger) {
127.48 + return ((Logger) logger).getLevel();
127.49 + }
127.50 +
127.51 + @Override
127.52 + public void setLevel(Object logger, Object newLevel) {
127.53 + ((Logger) logger).setLevel((Level) newLevel);
127.54 + }
127.55 +
127.56 + @Override
127.57 + public boolean isLoggable(Object logger, Object level) {
127.58 + return ((Logger) logger).isLoggable((Level) level);
127.59 + }
127.60 +
127.61 + @Override
127.62 + public void log(Object logger, Object level, String msg) {
127.63 + ((Logger) logger).log((Level) level, msg);
127.64 + }
127.65 +
127.66 + @Override
127.67 + public void log(Object logger, Object level, String msg, Throwable t) {
127.68 + ((Logger) logger).log((Level) level, msg, t);
127.69 + }
127.70 +
127.71 + @Override
127.72 + public void log(Object logger, Object level, String msg, Object... params) {
127.73 + ((Logger) logger).log((Level) level, msg, params);
127.74 + }
127.75 +
127.76 + @Override
127.77 + public java.util.List<String> getLoggerNames() {
127.78 + return LogManager.getLoggingMXBean().getLoggerNames();
127.79 + }
127.80 +
127.81 + @Override
127.82 + public String getLoggerLevel(String loggerName) {
127.83 + return LogManager.getLoggingMXBean().getLoggerLevel(loggerName);
127.84 + }
127.85 +
127.86 + @Override
127.87 + public void setLoggerLevel(String loggerName, String levelName) {
127.88 + LogManager.getLoggingMXBean().setLoggerLevel(loggerName, levelName);
127.89 + }
127.90 +
127.91 + @Override
127.92 + public String getParentLoggerName(String loggerName) {
127.93 + return LogManager.getLoggingMXBean().getParentLoggerName(loggerName);
127.94 + }
127.95 +
127.96 + @Override
127.97 + public Object parseLevel(String levelName) {
127.98 + return Level.parse(levelName);
127.99 + }
127.100 +
127.101 + @Override
127.102 + public String getLevelName(Object level) {
127.103 + return ((Level) level).getName();
127.104 + }
127.105 +}
128.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
128.2 +++ b/src/share/classes/java/util/logging/PlatformLoggingMXBean.java Wed Nov 25 11:08:25 2009 -0800
128.3 @@ -0,0 +1,60 @@
128.4 +/*
128.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
128.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
128.7 + *
128.8 + * This code is free software; you can redistribute it and/or modify it
128.9 + * under the terms of the GNU General Public License version 2 only, as
128.10 + * published by the Free Software Foundation. Sun designates this
128.11 + * particular file as subject to the "Classpath" exception as provided
128.12 + * by Sun in the LICENSE file that accompanied this code.
128.13 + *
128.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
128.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
128.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
128.17 + * version 2 for more details (a copy is included in the LICENSE file that
128.18 + * accompanied this code).
128.19 + *
128.20 + * You should have received a copy of the GNU General Public License version
128.21 + * 2 along with this work; if not, write to the Free Software Foundation,
128.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
128.23 + *
128.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
128.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
128.26 + * have any questions.
128.27 + */
128.28 +
128.29 +package java.util.logging;
128.30 +
128.31 +import java.lang.management.PlatformManagedObject;
128.32 +
128.33 +/**
128.34 + * The {@linkplain PlatformManagedObject platform managed object} for the
128.35 + * logging facility. This interface simply unifies {@link LoggingMXBean}
128.36 + * {@link PlatformManagedObject};
128.37 + * and it does not specify any new operations.
128.38 + *
128.39 + * <p>The {@link java.lang.management.ManagementFactory#getPlatformMXBeans(Class)
128.40 + * ManagementFactory.getPlatformMXBeans} method can be used to obtain
128.41 + * the {@code PlatformLoggingMXBean} object as follows:
128.42 + * <pre>
128.43 + * ManagementFactory.getPlatformMXBeans(PlatformLoggingMXBean.class);
128.44 + * </pre>
128.45 + * or from the {@linkplain java.lang.management.ManagementFactory#getPlatformMBeanServer
128.46 + * platform <tt>MBeanServer</tt>}.
128.47 + *
128.48 + * The {@link javax.management.ObjectName ObjectName} for uniquely
128.49 + * identifying the <tt>LoggingMXBean</tt> within an MBeanServer is:
128.50 + * <blockquote>
128.51 + * <tt>java.util.logging:type=Logging</tt>
128.52 + * </blockquote>
128.53 + *
128.54 + * The {@link PlatformManagedObject#getObjectName} method
128.55 + * can be used to obtain its {@code ObjectName}.
128.56 + *
128.57 + * @See java.lang.management.PlatformManagedObject
128.58 + *
128.59 + * @author Mandy Chung
128.60 + * @since 1.7
128.61 + */
128.62 +public interface PlatformLoggingMXBean extends LoggingMXBean, PlatformManagedObject {
128.63 +}
129.1 --- a/src/share/classes/java/util/regex/Matcher.java Mon Nov 23 10:04:47 2009 +0000
129.2 +++ b/src/share/classes/java/util/regex/Matcher.java Wed Nov 25 11:08:25 2009 -0800
129.3 @@ -688,7 +688,7 @@
129.4 *
129.5 * <p> The replacement string may contain references to subsequences
129.6 * captured during the previous match: Each occurrence of
129.7 - * <tt>$</tt><<i>name</i>> or <tt>$</tt><i>g</i>
129.8 + * <tt>${</tt><i>name</i><tt>}</tt> or <tt>$</tt><i>g</i>
129.9 * will be replaced by the result of evaluating the corresponding
129.10 * {@link #group(String) group(name)} or {@link #group(int) group(g)</tt>}
129.11 * respectively. For <tt>$</tt><i>g</i><tt></tt>,
129.12 @@ -770,7 +770,7 @@
129.13 // more appropriate.
129.14 nextChar = replacement.charAt(cursor);
129.15 int refNum = -1;
129.16 - if (nextChar == '<') {
129.17 + if (nextChar == '{') {
129.18 cursor++;
129.19 StringBuilder gsb = new StringBuilder();
129.20 while (cursor < replacement.length()) {
129.21 @@ -787,13 +787,17 @@
129.22 if (gsb.length() == 0)
129.23 throw new IllegalArgumentException(
129.24 "named capturing group has 0 length name");
129.25 - if (nextChar != '>')
129.26 + if (nextChar != '}')
129.27 throw new IllegalArgumentException(
129.28 - "named capturing group is missing trailing '>'");
129.29 + "named capturing group is missing trailing '}'");
129.30 String gname = gsb.toString();
129.31 + if (ASCII.isDigit(gname.charAt(0)))
129.32 + throw new IllegalArgumentException(
129.33 + "capturing group name {" + gname +
129.34 + "} starts with digit character");
129.35 if (!parentPattern.namedGroups().containsKey(gname))
129.36 throw new IllegalArgumentException(
129.37 - "No group with name <" + gname + ">");
129.38 + "No group with name {" + gname + "}");
129.39 refNum = parentPattern.namedGroups().get(gname);
129.40 cursor++;
129.41 } else {
130.1 --- a/src/share/classes/java/util/regex/Pattern.java Mon Nov 23 10:04:47 2009 +0000
130.2 +++ b/src/share/classes/java/util/regex/Pattern.java Wed Nov 25 11:08:25 2009 -0800
130.3 @@ -484,7 +484,7 @@
130.4 * <h5> Group name </h5>
130.5 * <p>A capturing group can also be assigned a "name", a <tt>named-capturing group</tt>,
130.6 * and then be back-referenced later by the "name". Group names are composed of
130.7 - * the following characters:
130.8 + * the following characters. The first character must be a <tt>letter</tt>.
130.9 *
130.10 * <ul>
130.11 * <li> The uppercase letters <tt>'A'</tt> through <tt>'Z'</tt>
130.12 @@ -2567,7 +2567,7 @@
130.13 break;
130.14 case '<': // (?<xxx) look behind
130.15 ch = read();
130.16 - if (ASCII.isLower(ch) || ASCII.isUpper(ch) || ASCII.isDigit(ch)) {
130.17 + if (ASCII.isLower(ch) || ASCII.isUpper(ch)) {
130.18 // named captured group
130.19 String name = groupname(ch);
130.20 if (namedGroups().containsKey(name))
131.1 --- a/src/share/classes/java/util/zip/Deflater.java Mon Nov 23 10:04:47 2009 +0000
131.2 +++ b/src/share/classes/java/util/zip/Deflater.java Wed Nov 25 11:08:25 2009 -0800
131.3 @@ -122,6 +122,33 @@
131.4 */
131.5 public static final int DEFAULT_STRATEGY = 0;
131.6
131.7 + /**
131.8 + * Compression flush mode used to achieve best compression result.
131.9 + *
131.10 + * @see Deflater#deflate(byte[], int, int, int)
131.11 + * @since 1.7
131.12 + */
131.13 + public static final int NO_FLUSH = 0;
131.14 +
131.15 + /**
131.16 + * Compression flush mode used to flush out all pending output; may
131.17 + * degrade compression for some compression algorithms.
131.18 + *
131.19 + * @see Deflater#deflate(byte[], int, int, int)
131.20 + * @since 1.7
131.21 + */
131.22 + public static final int SYNC_FLUSH = 2;
131.23 +
131.24 + /**
131.25 + * Compression flush mode used to flush out all pending output and
131.26 + * reset the deflater. Using this mode too often can seriously degrade
131.27 + * compression.
131.28 + *
131.29 + * @see Deflater#deflate(byte[], int, int, int)
131.30 + * @since 1.7
131.31 + */
131.32 + public static final int FULL_FLUSH = 3;
131.33 +
131.34 static {
131.35 /* Zip library is loaded from System.initializeSystemClass */
131.36 initIDs();
131.37 @@ -289,35 +316,100 @@
131.38 }
131.39
131.40 /**
131.41 - * Fills specified buffer with compressed data. Returns actual number
131.42 - * of bytes of compressed data. A return value of 0 indicates that
131.43 - * needsInput() should be called in order to determine if more input
131.44 - * data is required.
131.45 + * Compresses the input data and fills specified buffer with compressed
131.46 + * data. Returns actual number of bytes of compressed data. A return value
131.47 + * of 0 indicates that {@link needsInput() needsInput} should be called
131.48 + * in order to determine if more input data is required.
131.49 + *
131.50 + * <p>This method uses {@link #NO_FLUSH} as its compression flush mode.
131.51 + * An invocation of this method of the form {@code deflater.deflate(b, off, len)}
131.52 + * yields the same result as the invocation of
131.53 + * {@code deflater.deflate(b, off, len, Deflater.NO_FLUSH)}.
131.54 + *
131.55 * @param b the buffer for the compressed data
131.56 * @param off the start offset of the data
131.57 * @param len the maximum number of bytes of compressed data
131.58 - * @return the actual number of bytes of compressed data
131.59 + * @return the actual number of bytes of compressed data written to the
131.60 + * output buffer
131.61 */
131.62 - public synchronized int deflate(byte[] b, int off, int len) {
131.63 + public int deflate(byte[] b, int off, int len) {
131.64 + return deflate(b, off, len, NO_FLUSH);
131.65 + }
131.66 +
131.67 + /**
131.68 + * Compresses the input data and fills specified buffer with compressed
131.69 + * data. Returns actual number of bytes of compressed data. A return value
131.70 + * of 0 indicates that {@link needsInput() needsInput} should be called
131.71 + * in order to determine if more input data is required.
131.72 + *
131.73 + * <p>This method uses {@link #NO_FLUSH} as its compression flush mode.
131.74 + * An invocation of this method of the form {@code deflater.deflate(b)}
131.75 + * yields the same result as the invocation of
131.76 + * {@code deflater.deflate(b, 0, b.length, Deflater.NO_FLUSH)}.
131.77 + *
131.78 + * @param b the buffer for the compressed data
131.79 + * @return the actual number of bytes of compressed data written to the
131.80 + * output buffer
131.81 + */
131.82 + public int deflate(byte[] b) {
131.83 + return deflate(b, 0, b.length, NO_FLUSH);
131.84 + }
131.85 +
131.86 + /**
131.87 + * Compresses the input data and fills the specified buffer with compressed
131.88 + * data. Returns actual number of bytes of data compressed.
131.89 + *
131.90 + * <p>Compression flush mode is one of the following three modes:
131.91 + *
131.92 + * <ul>
131.93 + * <li>{@link #NO_FLUSH}: allows the deflater to decide how much data
131.94 + * to accumulate, before producing output, in order to achieve the best
131.95 + * compression (should be used in normal use scenario). A return value
131.96 + * of 0 in this flush mode indicates that {@link #needsInput()} should
131.97 + * be called in order to determine if more input data is required.
131.98 + *
131.99 + * <li>{@link #SYNC_FLUSH}: all pending output in the deflater is flushed,
131.100 + * to the specified output buffer, so that an inflater that works on
131.101 + * compressed data can get all input data available so far (In particular
131.102 + * the {@link #needsInput()} returns {@code true} after this invocation
131.103 + * if enough output space is provided). Flushing with {@link #SYNC_FLUSH}
131.104 + * may degrade compression for some compression algorithms and so it
131.105 + * should be used only when necessary.
131.106 + *
131.107 + * <li>{@link #FULL_FLUSH}: all pending output is flushed out as with
131.108 + * {@link #SYNC_FLUSH}. The compression state is reset so that the inflater
131.109 + * that works on the compressed output data can restart from this point
131.110 + * if previous compressed data has been damaged or if random access is
131.111 + * desired. Using {@link #FULL_FLUSH} too often can seriously degrade
131.112 + * compression.
131.113 + * </ul>
131.114 + *
131.115 + * <p>In the case of {@link #FULL_FLUSH} or {@link #SYNC_FLUSH}, if
131.116 + * the return value is {@code len}, the space available in output
131.117 + * buffer {@code b}, this method should be invoked again with the same
131.118 + * {@code flush} parameter and more output space.
131.119 + *
131.120 + * @param b the buffer for the compressed data
131.121 + * @param off the start offset of the data
131.122 + * @param len the maximum number of bytes of compressed data
131.123 + * @param flush the compression flush mode
131.124 + * @return the actual number of bytes of compressed data written to
131.125 + * the output buffer
131.126 + *
131.127 + * @throws IllegalArgumentException if the flush mode is invalid
131.128 + * @since 1.7
131.129 + */
131.130 + public synchronized int deflate(byte[] b, int off, int len, int flush) {
131.131 if (b == null) {
131.132 throw new NullPointerException();
131.133 }
131.134 if (off < 0 || len < 0 || off > b.length - len) {
131.135 throw new ArrayIndexOutOfBoundsException();
131.136 }
131.137 - return deflateBytes(b, off, len);
131.138 - }
131.139 -
131.140 - /**
131.141 - * Fills specified buffer with compressed data. Returns actual number
131.142 - * of bytes of compressed data. A return value of 0 indicates that
131.143 - * needsInput() should be called in order to determine if more input
131.144 - * data is required.
131.145 - * @param b the buffer for the compressed data
131.146 - * @return the actual number of bytes of compressed data
131.147 - */
131.148 - public int deflate(byte[] b) {
131.149 - return deflate(b, 0, b.length);
131.150 + if (flush == NO_FLUSH || flush == SYNC_FLUSH ||
131.151 + flush == FULL_FLUSH)
131.152 + return deflateBytes(b, off, len, flush);
131.153 + throw new IllegalArgumentException();
131.154 }
131.155
131.156 /**
131.157 @@ -420,7 +512,7 @@
131.158 private native static long init(int level, int strategy, boolean nowrap);
131.159 private native static void setDictionary(long strm, byte[] b, int off,
131.160 int len);
131.161 - private native int deflateBytes(byte[] b, int off, int len);
131.162 + private native int deflateBytes(byte[] b, int off, int len, int flush);
131.163 private native static int getAdler(long strm);
131.164 private native static long getBytesRead(long strm);
131.165 private native static long getBytesWritten(long strm);
132.1 --- a/src/share/classes/java/util/zip/DeflaterOutputStream.java Mon Nov 23 10:04:47 2009 +0000
132.2 +++ b/src/share/classes/java/util/zip/DeflaterOutputStream.java Wed Nov 25 11:08:25 2009 -0800
132.3 @@ -1,5 +1,5 @@
132.4 /*
132.5 - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
132.6 + * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
132.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
132.8 *
132.9 * This code is free software; you can redistribute it and/or modify it
132.10 @@ -56,15 +56,29 @@
132.11
132.12 private boolean closed = false;
132.13
132.14 + private final boolean syncFlush;
132.15 +
132.16 /**
132.17 - * Creates a new output stream with the specified compressor and
132.18 - * buffer size.
132.19 + * Creates a new output stream with the specified compressor,
132.20 + * buffer size and flush mode.
132.21 +
132.22 * @param out the output stream
132.23 * @param def the compressor ("deflater")
132.24 * @param size the output buffer size
132.25 - * @exception IllegalArgumentException if size is <= 0
132.26 + * @param syncFlush
132.27 + * if {@code true} the {@link flush()} method of this
132.28 + * instance flushes the compressor with flush mode
132.29 + * {@link Deflater#SYNC_FLUSH} before flushing the output
132.30 + * stream, otherwise only flushes the output stream
132.31 + *
132.32 + * @throws IllegalArgumentException if size is <= 0
132.33 + *
132.34 + * @since 1.7
132.35 */
132.36 - public DeflaterOutputStream(OutputStream out, Deflater def, int size) {
132.37 + public DeflaterOutputStream(OutputStream out,
132.38 + Deflater def,
132.39 + int size,
132.40 + boolean syncFlush) {
132.41 super(out);
132.42 if (out == null || def == null) {
132.43 throw new NullPointerException();
132.44 @@ -72,27 +86,93 @@
132.45 throw new IllegalArgumentException("buffer size <= 0");
132.46 }
132.47 this.def = def;
132.48 - buf = new byte[size];
132.49 + this.buf = new byte[size];
132.50 + this.syncFlush = syncFlush;
132.51 }
132.52
132.53 +
132.54 + /**
132.55 + * Creates a new output stream with the specified compressor and
132.56 + * buffer size.
132.57 + *
132.58 + * <p>The new output stream instance is created as if by invoking
132.59 + * the 4-argument constructor DeflaterOutputStream(out, def, size, false).
132.60 + *
132.61 + * @param out the output stream
132.62 + * @param def the compressor ("deflater")
132.63 + * @param size the output buffer size
132.64 + * @exception IllegalArgumentException if size is <= 0
132.65 + */
132.66 + public DeflaterOutputStream(OutputStream out, Deflater def, int size) {
132.67 + this(out, def, size, false);
132.68 + }
132.69 +
132.70 + /**
132.71 + * Creates a new output stream with the specified compressor, flush
132.72 + * mode and a default buffer size.
132.73 + *
132.74 + * @param out the output stream
132.75 + * @param def the compressor ("deflater")
132.76 + * @param syncFlush
132.77 + * if {@code true} the {@link flush()} method of this
132.78 + * instance flushes the compressor with flush mode
132.79 + * {@link Deflater#SYNC_FLUSH} before flushing the output
132.80 + * stream, otherwise only flushes the output stream
132.81 + *
132.82 + * @since 1.7
132.83 + */
132.84 + public DeflaterOutputStream(OutputStream out,
132.85 + Deflater def,
132.86 + boolean syncFlush) {
132.87 + this(out, def, 512, syncFlush);
132.88 + }
132.89 +
132.90 +
132.91 /**
132.92 * Creates a new output stream with the specified compressor and
132.93 * a default buffer size.
132.94 + *
132.95 + * <p>The new output stream instance is created as if by invoking
132.96 + * the 3-argument constructor DeflaterOutputStream(out, def, false).
132.97 + *
132.98 * @param out the output stream
132.99 * @param def the compressor ("deflater")
132.100 */
132.101 public DeflaterOutputStream(OutputStream out, Deflater def) {
132.102 - this(out, def, 512);
132.103 + this(out, def, 512, false);
132.104 }
132.105
132.106 boolean usesDefaultDeflater = false;
132.107
132.108 +
132.109 + /**
132.110 + * Creates a new output stream with a default compressor, a default
132.111 + * buffer size and the specified flush mode.
132.112 + *
132.113 + * @param out the output stream
132.114 + * @param syncFlush
132.115 + * if {@code true} the {@link flush()} method of this
132.116 + * instance flushes the compressor with flush mode
132.117 + * {@link Deflater#SYNC_FLUSH} before flushing the output
132.118 + * stream, otherwise only flushes the output stream
132.119 + *
132.120 + * @since 1.7
132.121 + */
132.122 + public DeflaterOutputStream(OutputStream out, boolean syncFlush) {
132.123 + this(out, new Deflater(), 512, syncFlush);
132.124 + usesDefaultDeflater = true;
132.125 + }
132.126 +
132.127 /**
132.128 * Creates a new output stream with a default compressor and buffer size.
132.129 + *
132.130 + * <p>The new output stream instance is created as if by invoking
132.131 + * the 2-argument constructor DeflaterOutputStream(out, false).
132.132 + *
132.133 * @param out the output stream
132.134 */
132.135 public DeflaterOutputStream(OutputStream out) {
132.136 - this(out, new Deflater());
132.137 + this(out, false);
132.138 usesDefaultDeflater = true;
132.139 }
132.140
132.141 @@ -178,4 +258,32 @@
132.142 out.write(buf, 0, len);
132.143 }
132.144 }
132.145 +
132.146 + /**
132.147 + * Flushes the compressed output stream.
132.148 + *
132.149 + * If {@link DeflaterOutputStream(OutputStream, Deflater, int, boolean)
132.150 + * syncFlush} is {@code true} when this compressed output stream is
132.151 + * constructed this method flushes the underlying {@code compressor}
132.152 + * first with the flush mode {@link Deflater#SYNC_FLUSH} to force
132.153 + * all pending data to be flushed out to the output stream and then
132.154 + * flushes the output stream. Otherwise this method only flushes the
132.155 + * output stream without flushing the {@code compressor}.
132.156 + *
132.157 + * @throws IOException if an I/O error has occurred
132.158 + *
132.159 + * @since 1.7
132.160 + */
132.161 + public void flush() throws IOException {
132.162 + if (syncFlush && !def.finished()) {
132.163 + int len = 0;
132.164 + while ((len = def.deflate(buf, 0, buf.length, Deflater.SYNC_FLUSH)) > 0)
132.165 + {
132.166 + out.write(buf, 0, len);
132.167 + if (len < buf.length)
132.168 + break;
132.169 + }
132.170 + }
132.171 + out.flush();
132.172 + }
132.173 }
133.1 --- a/src/share/classes/javax/management/AndQueryExp.java Mon Nov 23 10:04:47 2009 +0000
133.2 +++ b/src/share/classes/javax/management/AndQueryExp.java Wed Nov 25 11:08:25 2009 -0800
133.3 @@ -104,26 +104,4 @@
133.4 public String toString() {
133.5 return "(" + exp1 + ") and (" + exp2 + ")";
133.6 }
133.7 -
133.8 - @Override
133.9 - String toQueryString() {
133.10 - // Parentheses are only added if needed to disambiguate.
133.11 - return parens(exp1) + " and " + parens(exp2);
133.12 - }
133.13 -
133.14 - // Add parens if needed to disambiguate an expression such as
133.15 - // Query.and(Query.or(a, b), c). We need to return
133.16 - // (a or b) and c
133.17 - // in such a case, because
133.18 - // a or b and c
133.19 - // would mean
133.20 - // a or (b and c)
133.21 - private static String parens(QueryExp exp) {
133.22 - String s = Query.toString(exp);
133.23 - if (exp instanceof OrQueryExp)
133.24 - return "(" + s + ")";
133.25 - else
133.26 - return s;
133.27 - }
133.28 -
133.29 }
134.1 --- a/src/share/classes/javax/management/AttributeList.java Mon Nov 23 10:04:47 2009 +0000
134.2 +++ b/src/share/classes/javax/management/AttributeList.java Wed Nov 25 11:08:25 2009 -0800
134.3 @@ -138,56 +138,6 @@
134.4 }
134.5
134.6 /**
134.7 - * <p>Constructs an {@code AttributeList} containing the elements of
134.8 - * the {@code Map} specified, in the order in which they appear in the
134.9 - * {@code Map}'s {@link Map#entrySet entrySet}. For each <em>{@code
134.10 - * key}</em> and <em>{@code value}</em> in the {@code Map}, the constructed
134.11 - * {@code AttributeList} will contain {@link Attribute#Attribute
134.12 - * Attribute(<em>key</em>, <em>value</em>)}.</p>
134.13 - *
134.14 - * @param map the {@code Map} defining the elements of the new
134.15 - * {@code AttributeList}.
134.16 - */
134.17 - public AttributeList(Map<String, ?> map) {
134.18 - for (Map.Entry<String, ?> entry : map.entrySet())
134.19 - add(new Attribute(entry.getKey(), entry.getValue()));
134.20 - typeSafe = true;
134.21 - }
134.22 -
134.23 - /**
134.24 - * <p>Return a {@code Map} that is a snapshot of the values in this
134.25 - * {@code AttributeList}. Each key in the {@code Map} is the {@linkplain
134.26 - * Attribute#getName() name} of an {@code Attribute} in the list, and each
134.27 - * value is the corresponding {@linkplain Attribute#getValue() value} of
134.28 - * that {@code Attribute}. The {@code AttributeList} and the {@code Map}
134.29 - * are unrelated after the call, that is, changes to one do not affect the
134.30 - * other.</p>
134.31 - *
134.32 - * <p>If the {@code AttributeList} contains more than one {@code Attribute}
134.33 - * with the same name, then the {@code Map} will contain an entry
134.34 - * for that name where the value is that of the last of those {@code
134.35 - * Attribute}s.</p>
134.36 - *
134.37 - * @return the new {@code Map}.
134.38 - *
134.39 - * @throws IllegalArgumentException if this {@code AttributeList} contains
134.40 - * an element that is not an {@code Attribute}.
134.41 - */
134.42 - public Map<String, Object> toMap() {
134.43 - Map<String, Object> map = new LinkedHashMap<String, Object>();
134.44 -
134.45 - // We can't call adding(this) because we're not necessarily typeSafe
134.46 - if (tainted)
134.47 - throw new IllegalArgumentException("AttributeList contains non-Attribute");
134.48 -
134.49 - for (Object x : this) {
134.50 - Attribute a = (Attribute) x;
134.51 - map.put(a.getName(), a.getValue());
134.52 - }
134.53 - return map;
134.54 - }
134.55 -
134.56 - /**
134.57 * Return a view of this list as a {@code List<Attribute>}.
134.58 * Changes to the returned value are reflected by changes
134.59 * to the original {@code AttributeList} and vice versa.
135.1 --- a/src/share/classes/javax/management/AttributeValueExp.java Mon Nov 23 10:04:47 2009 +0000
135.2 +++ b/src/share/classes/javax/management/AttributeValueExp.java Wed Nov 25 11:08:25 2009 -0800
135.3 @@ -51,8 +51,6 @@
135.4 */
135.5 private String attr;
135.6
135.7 - private transient int dotIndex;
135.8 -
135.9 /**
135.10 * An <code>AttributeValueExp</code> with a null attribute.
135.11 * @deprecated An instance created with this constructor cannot be
135.12 @@ -71,18 +69,6 @@
135.13 */
135.14 public AttributeValueExp(String attr) {
135.15 this.attr = attr;
135.16 - setDotIndex();
135.17 - }
135.18 -
135.19 - private void setDotIndex() {
135.20 - if (attr != null)
135.21 - dotIndex = attr.indexOf('.');
135.22 - }
135.23 -
135.24 - private void readObject(ObjectInputStream in)
135.25 - throws ClassNotFoundException, IOException {
135.26 - in.defaultReadObject();
135.27 - setDotIndex();
135.28 }
135.29
135.30 /**
135.31 @@ -134,7 +120,7 @@
135.32 */
135.33 @Override
135.34 public String toString() {
135.35 - return QueryParser.quoteId(attr);
135.36 + return attr;
135.37 }
135.38
135.39
135.40 @@ -160,18 +146,6 @@
135.41 * If the attempt to access the attribute generates an exception,
135.42 * return null.</p>
135.43 *
135.44 - * <p>Let <em>n</em> be the {@linkplain #getAttributeName attribute
135.45 - * name}. Then this method proceeds as follows. First it calls
135.46 - * {@link MBeanServer#getAttribute getAttribute(name, <em>n</em>)}. If that
135.47 - * generates an {@link AttributeNotFoundException}, and if <em>n</em>
135.48 - * contains at least one dot ({@code .}), then the method calls {@code
135.49 - * getAttribute(name, }<em>n</em>{@code .substring(0, }<em>n</em>{@code
135.50 - * .indexOf('.')))}; in other words it calls {@code getAttribute}
135.51 - * with the substring of <em>n</em> before the first dot. Then it
135.52 - * extracts a component from the retrieved value, as described in the <a
135.53 - * href="monitor/package-summary.html#complex">documentation for the {@code
135.54 - * monitor} package</a>.</p>
135.55 - *
135.56 * <p>The MBean Server used is the one returned by {@link
135.57 * QueryEval#getMBeanServer()}.</p>
135.58 *
135.59 @@ -186,34 +160,9 @@
135.60
135.61 MBeanServer server = QueryEval.getMBeanServer();
135.62
135.63 - try {
135.64 return server.getAttribute(name, attr);
135.65 - } catch (AttributeNotFoundException e) {
135.66 - if (dotIndex < 0)
135.67 - throw e;
135.68 - }
135.69 -
135.70 - String toGet = attr.substring(0, dotIndex);
135.71 -
135.72 - Object value = server.getAttribute(name, toGet);
135.73 -
135.74 - return extractElement(value, attr.substring(dotIndex + 1));
135.75 } catch (Exception re) {
135.76 return null;
135.77 }
135.78 }
135.79 -
135.80 - private Object extractElement(Object value, String elementWithDots)
135.81 - throws AttributeNotFoundException {
135.82 - while (true) {
135.83 - int dot = elementWithDots.indexOf('.');
135.84 - String element = (dot < 0) ?
135.85 - elementWithDots : elementWithDots.substring(0, dot);
135.86 - value = Introspector.elementFromComplex(value, element);
135.87 - if (dot < 0)
135.88 - return value;
135.89 - elementWithDots = elementWithDots.substring(dot + 1);
135.90 - }
135.91 - }
135.92 -
135.93 }
136.1 --- a/src/share/classes/javax/management/BetweenQueryExp.java Mon Nov 23 10:04:47 2009 +0000
136.2 +++ b/src/share/classes/javax/management/BetweenQueryExp.java Wed Nov 25 11:08:25 2009 -0800
136.3 @@ -139,9 +139,4 @@
136.4 public String toString() {
136.5 return "(" + exp1 + ") between (" + exp2 + ") and (" + exp3 + ")";
136.6 }
136.7 -
136.8 - @Override
136.9 - String toQueryString() {
136.10 - return exp1 + " between " + exp2 + " and " + exp3;
136.11 - }
136.12 }
137.1 --- a/src/share/classes/javax/management/BinaryOpValueExp.java Mon Nov 23 10:04:47 2009 +0000
137.2 +++ b/src/share/classes/javax/management/BinaryOpValueExp.java Wed Nov 25 11:08:25 2009 -0800
137.3 @@ -253,7 +253,5 @@
137.4 @Deprecated
137.5 public void setMBeanServer(MBeanServer s) {
137.6 super.setMBeanServer(s);
137.7 + }
137.8 }
137.9 -
137.10 -
137.11 - }
138.1 --- a/src/share/classes/javax/management/BinaryRelQueryExp.java Mon Nov 23 10:04:47 2009 +0000
138.2 +++ b/src/share/classes/javax/management/BinaryRelQueryExp.java Wed Nov 25 11:08:25 2009 -0800
138.3 @@ -192,11 +192,6 @@
138.4 return "(" + exp1 + ") " + relOpString() + " (" + exp2 + ")";
138.5 }
138.6
138.7 - @Override
138.8 - String toQueryString() {
138.9 - return exp1 + " " + relOpString() + " " + exp2;
138.10 - }
138.11 -
138.12 private String relOpString() {
138.13 switch (relOp) {
138.14 case Query.GT:
139.1 --- a/src/share/classes/javax/management/ClientContext.java Mon Nov 23 10:04:47 2009 +0000
139.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
139.3 @@ -1,1091 +0,0 @@
139.4 -/*
139.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
139.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
139.7 - *
139.8 - * This code is free software; you can redistribute it and/or modify it
139.9 - * under the terms of the GNU General Public License version 2 only, as
139.10 - * published by the Free Software Foundation. Sun designates this
139.11 - * particular file as subject to the "Classpath" exception as provided
139.12 - * by Sun in the LICENSE file that accompanied this code.
139.13 - *
139.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
139.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
139.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
139.17 - * version 2 for more details (a copy is included in the LICENSE file that
139.18 - * accompanied this code).
139.19 - *
139.20 - * You should have received a copy of the GNU General Public License version
139.21 - * 2 along with this work; if not, write to the Free Software Foundation,
139.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
139.23 - *
139.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
139.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
139.26 - * have any questions.
139.27 - */
139.28 -
139.29 -package javax.management;
139.30 -
139.31 -import com.sun.jmx.interceptor.SingleMBeanForwarder;
139.32 -import com.sun.jmx.namespace.RoutingConnectionProxy;
139.33 -import com.sun.jmx.namespace.RoutingProxy;
139.34 -import com.sun.jmx.namespace.RoutingServerProxy;
139.35 -import java.io.UnsupportedEncodingException;
139.36 -import java.lang.reflect.InvocationHandler;
139.37 -import java.lang.reflect.InvocationTargetException;
139.38 -import java.lang.reflect.Method;
139.39 -import java.lang.reflect.Proxy;
139.40 -import java.net.URLDecoder;
139.41 -import java.net.URLEncoder;
139.42 -import java.util.Arrays;
139.43 -import java.util.Collections;
139.44 -import java.util.LinkedHashMap;
139.45 -import java.util.Locale;
139.46 -import java.util.Map;
139.47 -import java.util.Set;
139.48 -import java.util.StringTokenizer;
139.49 -import java.util.TreeMap;
139.50 -import java.util.concurrent.Callable;
139.51 -import java.util.logging.Level;
139.52 -import java.util.logging.Logger;
139.53 -import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR;
139.54 -import javax.management.namespace.JMXNamespaces;
139.55 -import javax.management.namespace.JMXNamespace;
139.56 -import javax.management.namespace.JMXNamespaceMBean;
139.57 -import javax.management.namespace.MBeanServerSupport;
139.58 -import javax.management.remote.IdentityMBeanServerForwarder;
139.59 -import javax.management.remote.MBeanServerForwarder;
139.60 -
139.61 -/**
139.62 - * <p>Methods to communicate a client context to MBeans. A context is
139.63 - * a {@literal Map<String, String>} that is provided by the client and
139.64 - * that an MBean can consult using the {@link #getContext()} method.
139.65 - * The context is set on a per-thread basis and can be consulted by any
139.66 - * code that the target MBean calls within the thread.</p>
139.67 - *
139.68 - * <p>One common usage of client context is to communicate the client's
139.69 - * {@link Locale} to MBeans. For example, if an MBean has a String attribute
139.70 - * {@code LastProblemDescription}, the value of that attribute could be
139.71 - * a description of the last problem encountered by the MBean, translated
139.72 - * into the client's locale. Different clients accessing this attribute
139.73 - * from different locales would each see the appropriate version for their
139.74 - * locale.</p>
139.75 - *
139.76 - * <p>The locale case is sufficiently important that it has a special
139.77 - * shorthand, the {@link #getLocale()} method. This method calls
139.78 - * <code>{@link #getContext()}.get({@link #LOCALE_KEY})</code> and converts the
139.79 - * resultant String into a Locale object.</p>
139.80 - *
139.81 - * <p>Here is what an MBean with a localized {@code LastProblemDescription}
139.82 - * attribute might look like:</p>
139.83 - *
139.84 - * <pre>
139.85 - * public class LocaleSensitive implements LocaleSensitiveMBean {
139.86 - * ...
139.87 - * public String getLastProblemDescription() {
139.88 - * Locale loc = {@link #getLocale() ClientContext.getLocale()};
139.89 - * ResourceBundle rb = ResourceBundle.getBundle("MyResources", loc);
139.90 - * String resourceKey = getLastProblemResourceKey();
139.91 - * return rb.getString(resourceKey);
139.92 - * }
139.93 - * ...
139.94 - * }
139.95 - * </pre>
139.96 - *
139.97 - * <p>Here is how a client can communicate its locale to the target
139.98 - * MBean:</p>
139.99 - *
139.100 - * <pre>
139.101 - * JMXConnector connector = JMXConnectorFactory.connect(url);
139.102 - * MBeanServerConnection connection = connector.getMBeanServerConnection();
139.103 - * <b>MBeanServerConnection localizedConnection =
139.104 - * {@link #withLocale(MBeanServerConnection, Locale)
139.105 - * ClientContext.withLocale}(connection, Locale.getDefault());</b>
139.106 - * String problem = localizedConnection.getAttribute(
139.107 - * objectName, "LastProblemDescription");
139.108 - * </pre>
139.109 - *
139.110 - * <p>In the more general case where the client wants to communicate context
139.111 - * other than the locale, it can use {@link #withContext(MBeanServerConnection,
139.112 - * String, String) withContext} instead of {@code withLocale}, and the target
139.113 - * MBean can retrieve the context using {@link #getContext()}.</p>
139.114 - *
139.115 - *
139.116 - * <h3 id="remote-use">Remote use of contexts</h3>
139.117 - *
139.118 - * <p>The various {@code with*} methods, for example {@link
139.119 - * #withLocale(javax.management.MBeanServer, java.util.Locale) withLocale},
139.120 - * transmit the context of each request by encoding it in the ObjectName of
139.121 - * the request. For example, if a client creates a connection in the
139.122 - * French locale like this...</p>
139.123 - *
139.124 - * <pre>
139.125 - * MBeanServerConnection mbsc = ...;
139.126 - * Locale french = new Locale("fr");
139.127 - * MBeanServerConnection localizedConnection = ClientContext.withLocale(mbsc, french);
139.128 - * </pre>
139.129 - *
139.130 - * <p>...or, equivalently, like this...</p>
139.131 - *
139.132 - * <pre>
139.133 - * MBeanServerConnection localizedConnection =
139.134 - * ClientContext.withContext(mbsc, {@link #LOCALE_KEY "jmx.locale"}, "fr");
139.135 - * </pre>
139.136 - *
139.137 - * <p>...then the context associates {@code "jmx.locale"} with {@code "fr"}
139.138 - * and a request such as<br>
139.139 - * {@code localizedConnection.getAttribute("java.lang:type=Runtime", "Name")}<br>
139.140 - * is translated into<br>
139.141 - * {@code mbsc.getAttribute("jmx.context//jmx.locale=fr//java.lang:Runtime", "Name")}.<br>
139.142 - * A special {@linkplain javax.management.namespace namespace} {@code jmx.context//}
139.143 - * extracts the context from the string {@code jmx.locale=fr} and establishes
139.144 - * it in the thread that will do<br>
139.145 - * {@code getAttribute("java.lang:Runtime", "Name")}.</p>
139.146 - *
139.147 - * <p>The details of how contexts are encoded into ObjectNames are explained
139.148 - * in the {@link #encode encode} method.</p>
139.149 - *
139.150 - * <p>The namespace {@code jmx.context//} just mentioned is only needed by
139.151 - * remote clients, since local clients can set the context directly using
139.152 - * {@link #doWithContext doWithContext}. Accordingly, this namespace is not
139.153 - * present by default in the {@code MBeanServer}. Instead, it is
139.154 - * <em>simulated</em> by the standard RMI connector using a special
139.155 - * {@link MBeanServerForwarder}. If you are using this connector, you do not
139.156 - * need to do anything special. Other connectors may or may not simulate this
139.157 - * namespace in the same way. If the connector server returns true from the
139.158 - * method {@link
139.159 - * javax.management.remote.JMXConnectorServer#supportsSystemMBeanServerForwarder()
139.160 - * supportsSystemMBeanServerForwarder} then it does simulate the namespace.
139.161 - * If you are using another connector, or if you want to be able to use the
139.162 - * {@code with*} methods locally, then you can install the {@code
139.163 - * MBeanServerForwarder} yourself as described in the method {@link
139.164 - * #newContextForwarder newContextForwarder}.</p>
139.165 - */
139.166 -public class ClientContext {
139.167 - /**
139.168 - * <p>The context key for the client locale. The string associated with
139.169 - * this key is an encoded locale such as {@code en_US} which could be
139.170 - * returned by {@link Locale#toString()}.</p>
139.171 - */
139.172 - public static final String LOCALE_KEY = "jmx.locale";
139.173 -
139.174 - private static final Logger LOG =
139.175 - Logger.getLogger("javax.management.context");
139.176 -
139.177 - /**
139.178 - * <p>The namespace that implements contexts, {@value}.</p>
139.179 - */
139.180 - public static final String
139.181 - NAMESPACE = "jmx.context";
139.182 - private static final String NAMESPACE_PLUS_SEP =
139.183 - NAMESPACE + NAMESPACE_SEPARATOR;
139.184 - static final ObjectName CLIENT_CONTEXT_NAMESPACE_HANDLER =
139.185 - ObjectName.valueOf(NAMESPACE_PLUS_SEP + ":" +
139.186 - JMXNamespace.TYPE_ASSIGNMENT);
139.187 - private static final ObjectName NAMESPACE_HANDLER_WITHOUT_NAMESPACE =
139.188 - ObjectName.valueOf(":" + JMXNamespace.TYPE_ASSIGNMENT);
139.189 -
139.190 - private static final ThreadLocal<Map<String, String>> contextThreadLocal =
139.191 - new InheritableThreadLocal<Map<String, String>>() {
139.192 - @Override
139.193 - protected Map<String, String> initialValue() {
139.194 - return Collections.emptyMap();
139.195 - }
139.196 - };
139.197 -
139.198 - /** There are no instances of this class. */
139.199 - private ClientContext() {
139.200 - }
139.201 -
139.202 - /**
139.203 - * <p>Get the client context associated with the current thread.
139.204 - *
139.205 - * @return the client context associated with the current thread.
139.206 - * This may be an empty Map, but it cannot be null. The returned
139.207 - * Map cannot be modified.
139.208 - */
139.209 - public static Map<String, String> getContext() {
139.210 - return Collections.unmodifiableMap(contextThreadLocal.get());
139.211 - }
139.212 -
139.213 - /**
139.214 - * <p>Get the client locale associated with the current thread.
139.215 - * If the client context includes the {@value #LOCALE_KEY} key
139.216 - * then the returned value is the Locale encoded in that key.
139.217 - * Otherwise the returned value is the {@linkplain Locale#getDefault()
139.218 - * default locale}.
139.219 - *
139.220 - * @return the client locale.
139.221 - */
139.222 - public static Locale getLocale() {
139.223 - String localeS = getContext().get(LOCALE_KEY);
139.224 - if (localeS == null)
139.225 - return Locale.getDefault();
139.226 - // Parse the locale string. Why isn't there a method in Locale for this?
139.227 - String language, country, variant;
139.228 - int ui = localeS.indexOf('_');
139.229 - if (ui < 0) {
139.230 - language = localeS;
139.231 - country = variant = "";
139.232 - } else {
139.233 - language = localeS.substring(0, ui);
139.234 - localeS = localeS.substring(ui + 1);
139.235 - ui = localeS.indexOf('_');
139.236 - if (ui < 0) {
139.237 - country = localeS;
139.238 - variant = "";
139.239 - } else {
139.240 - country = localeS.substring(0, ui);
139.241 - variant = localeS.substring(ui + 1);
139.242 - }
139.243 - }
139.244 - return new Locale(language, country, variant);
139.245 - }
139.246 -
139.247 - /**
139.248 - * <p>Execute the given {@code task} with the client context set to
139.249 - * the given Map. This Map will be the result of {@link #getContext()}
139.250 - * within the {@code task}.</p>
139.251 - *
139.252 - * <p>The {@code task} may include nested calls to {@code doWithContext}.
139.253 - * The value returned by {@link #getContext} at any point is the Map
139.254 - * provided to the most recent {@code doWithContext} (in the current thread)
139.255 - * that has not yet returned.</p>
139.256 - *
139.257 - * <p>The {@link #getContext()} method returns the same value immediately
139.258 - * after a call to this method as immediately before. In other words,
139.259 - * {@code doWithContext} only affects the context during the execution of
139.260 - * the {@code task}.</p>
139.261 - *
139.262 - * <p>As an example, suppose you want to get an attribute with whatever
139.263 - * context has already been set, plus the locale set to "fr". You could
139.264 - * write this:</p>
139.265 - *
139.266 - * <pre>
139.267 - * {@code Map<String, String>} context =
139.268 - * new {@code HashMap<String, String>}(ClientContext.getContext());
139.269 - * context.put(ClientContext.LOCALE_KEY, "fr");
139.270 - * String lastProblemDescription =
139.271 - * ClientContext.doWithContext(context, new {@code Callable<String>}() {
139.272 - * public String call() {
139.273 - * return (String) mbeanServer.getAttribute(mbean, "LastProblemDescription");
139.274 - * }
139.275 - * });
139.276 - * </pre>
139.277 - *
139.278 - * @param <T> the type of value that the task will return. This type
139.279 - * parameter is usually inferred from the type of the {@code task}
139.280 - * parameter. For example, if {@code task} is a {@code Callable<String>}
139.281 - * then {@code T} is {@code String}. If the task does not return a value,
139.282 - * use a {@code Callable<Void>} and return null from its
139.283 - * {@link Callable#call call} method.
139.284 - * @param context the context to use while executing {@code task}.
139.285 - * @param task the task to run with the {@code key}={@code value}
139.286 - * binding.
139.287 - * @return the result of {@link Callable#call() task.call()}.
139.288 - * @throws IllegalArgumentException if either parameter is null, or
139.289 - * if any key in {@code context} is null or empty, or if any value
139.290 - * in {@code context} is null.
139.291 - * @throws Exception If {@link Callable#call() task.call()} throws an
139.292 - * exception, {@code doWithContext} throws the same exception.
139.293 - */
139.294 - public static <T> T doWithContext(Map<String, String> context, Callable<T> task)
139.295 - throws Exception {
139.296 - if (context == null || task == null)
139.297 - throw new IllegalArgumentException("Null parameter");
139.298 - Map<String, String> contextCopy = new TreeMap<String, String>(context);
139.299 - validateContext(contextCopy);
139.300 - Map<String, String> oldContextMap = contextThreadLocal.get();
139.301 - try {
139.302 - contextThreadLocal.set(contextCopy);
139.303 - return task.call();
139.304 - } finally {
139.305 - contextThreadLocal.set(oldContextMap);
139.306 - }
139.307 - }
139.308 -
139.309 - private static void validateContext(Map<String, String> context) {
139.310 - for (Map.Entry<String, String> entry : context.entrySet()) {
139.311 - // If the user passes a raw Map rather than a Map<String, String>,
139.312 - // entries could contain objects other than Strings. If so,
139.313 - // we'll get a ClassCastException here.
139.314 - String key = entry.getKey();
139.315 - String value = entry.getValue();
139.316 - if (key == null || value == null)
139.317 - throw new IllegalArgumentException("Null key or value in context");
139.318 - if (key.equals(""))
139.319 - throw new IllegalArgumentException("Empty key in context");
139.320 - }
139.321 - }
139.322 -
139.323 - /**
139.324 - * <p>Return an MBeanServer object that is equivalent to the given
139.325 - * MBeanServer object except that operations on MBeans run with
139.326 - * the given Locale in their {@linkplain #getContext() thread context}.
139.327 - * Note that this will only work if the given MBeanServer supports
139.328 - * contexts, as described <a href="#remote-use">above</a>.</p>
139.329 - *
139.330 - * <p>This method is equivalent to {@link #withContext(MBeanServer,
139.331 - * String, String) withContext}<code>(mbs, {@value LOCALE_KEY},
139.332 - * locale.toString())</code>.</p>
139.333 - *
139.334 - * @throws IllegalArgumentException if either parameter is null, or if
139.335 - * {@code mbs} does not support contexts. In the second case only,
139.336 - * the cause of the {@code IllegalArgumentException} will be an {@link
139.337 - * InstanceNotFoundException}.
139.338 - */
139.339 - public static MBeanServer withLocale(MBeanServer mbs, Locale locale) {
139.340 - return withLocale(mbs, MBeanServer.class, locale);
139.341 - }
139.342 -
139.343 - /**
139.344 - * <p>Return an MBeanServerConnection object that is equivalent to the given
139.345 - * MBeanServerConnection object except that operations on MBeans run with
139.346 - * the given Locale in their {@linkplain #getContext() thread context}.
139.347 - * Note that this will only work if the given MBeanServerConnection supports
139.348 - * contexts, as described <a href="#remote-use">above</a>.</p>
139.349 - *
139.350 - * <p>This method is equivalent to {@link #withContext(MBeanServerConnection,
139.351 - * String, String) withContext}<code>(mbs, {@value LOCALE_KEY},
139.352 - * locale.toString())</code>.</p>
139.353 - *
139.354 - * @throws IllegalArgumentException if either parameter is null, or if
139.355 - * the communication with {@code mbsc} fails, or if {@code mbsc} does not
139.356 - * support contexts. If the communication with {@code mbsc} fails, the
139.357 - * {@linkplain Throwable#getCause() cause} of this exception will be an
139.358 - * {@code IOException}. If {@code mbsc} does not support contexts, the
139.359 - * cause will be an {@link InstanceNotFoundException}.
139.360 - */
139.361 - public static MBeanServerConnection withLocale(
139.362 - MBeanServerConnection mbsc, Locale locale) {
139.363 - return withLocale(mbsc, MBeanServerConnection.class, locale);
139.364 - }
139.365 -
139.366 - private static <T extends MBeanServerConnection> T withLocale(
139.367 - T mbsc, Class<T> mbscClass, Locale locale) {
139.368 - if (locale == null)
139.369 - throw new IllegalArgumentException("Null locale");
139.370 - return withContext(mbsc, mbscClass, LOCALE_KEY, locale.toString());
139.371 - }
139.372 -
139.373 - /**
139.374 - * <p>Return an MBeanServer object that is equivalent to the given
139.375 - * MBeanServer object except that operations on MBeans run with
139.376 - * the given key bound to the given value in their {@linkplain
139.377 - * #getContext() thread context}.
139.378 - * Note that this will only work if the given MBeanServer supports
139.379 - * contexts, as described <a href="#remote-use">above</a>.</p>
139.380 - *
139.381 - * @param mbs the original MBeanServer.
139.382 - * @param key the key to bind in the context of MBean operations
139.383 - * in the returned MBeanServer object.
139.384 - * @param value the value to bind to the key in the context of MBean
139.385 - * operations in the returned MBeanServer object.
139.386 - * @throws IllegalArgumentException if any parameter is null, or
139.387 - * if {@code key} is the empty string, or if {@code mbs} does not support
139.388 - * contexts. In the last case only, the cause of the {@code
139.389 - * IllegalArgumentException} will be an {@link InstanceNotFoundException}.
139.390 - */
139.391 - public static MBeanServer withContext(
139.392 - MBeanServer mbs, String key, String value) {
139.393 - return withContext(mbs, MBeanServer.class, key, value);
139.394 - }
139.395 -
139.396 - /**
139.397 - * <p>Return an MBeanServerConnection object that is equivalent to the given
139.398 - * MBeanServerConnection object except that operations on MBeans run with
139.399 - * the given key bound to the given value in their {@linkplain
139.400 - * #getContext() thread context}.
139.401 - * Note that this will only work if the given MBeanServerConnection supports
139.402 - * contexts, as described <a href="#remote-use">above</a>.</p>
139.403 - *
139.404 - * @param mbsc the original MBeanServerConnection.
139.405 - * @param key the key to bind in the context of MBean operations
139.406 - * in the returned MBeanServerConnection object.
139.407 - * @param value the value to bind to the key in the context of MBean
139.408 - * operations in the returned MBeanServerConnection object.
139.409 - * @throws IllegalArgumentException if any parameter is null, or
139.410 - * if {@code key} is the empty string, or if the communication with {@code
139.411 - * mbsc} fails, or if {@code mbsc} does not support contexts. If
139.412 - * the communication with {@code mbsc} fails, the {@linkplain
139.413 - * Throwable#getCause() cause} of this exception will be an {@code
139.414 - * IOException}. If {@code mbsc} does not support contexts, the cause will
139.415 - * be an {@link InstanceNotFoundException}.
139.416 - */
139.417 - public static MBeanServerConnection withContext(
139.418 - MBeanServerConnection mbsc, String key, String value) {
139.419 - return withContext(mbsc, MBeanServerConnection.class, key, value);
139.420 - }
139.421 -
139.422 -
139.423 - /**
139.424 - * <p>Returns an MBeanServerConnection object that is equivalent to the
139.425 - * given MBeanServerConnection object except that remote operations on
139.426 - * MBeans run with the context that has been established by the client
139.427 - * using {@link #doWithContext doWithContext}. Note that this will
139.428 - * only work if the remote system supports contexts, as described <a
139.429 - * href="#remote-use">above</a>.</p>
139.430 - *
139.431 - * <p>For example, suppose the remote system does support contexts, and you
139.432 - * have created a {@code JMXConnector} like this:</p>
139.433 - *
139.434 - * <pre>
139.435 - * JMXServiceURL url = ...;
139.436 - * JMXConnector client = JMXConnectorFactory.connect(url);
139.437 - * MBeanServerConnection mbsc = client.getMBeanServerConnection();
139.438 - * <b>mbsc = ClientContext.withDynamicContext(mbsc);</b>
139.439 - * </pre>
139.440 - *
139.441 - * <p>Then if you do this...</p>
139.442 - *
139.443 - * <pre>
139.444 - * MBeanInfo mbi = ClientContext.doWithContext(
139.445 - * Collections.singletonMap(ClientContext.LOCALE_KEY, "fr"),
139.446 - * new {@code Callable<MBeanInfo>}() {
139.447 - * public MBeanInfo call() {
139.448 - * return mbsc.getMBeanInfo(objectName);
139.449 - * }
139.450 - * });
139.451 - * </pre>
139.452 - *
139.453 - * <p>...then the context with the locale set to "fr" will be in place
139.454 - * when the {@code getMBeanInfo} is executed on the remote MBean Server.</p>
139.455 - *
139.456 - * @param mbsc the original MBeanServerConnection.
139.457 - *
139.458 - * @throws IllegalArgumentException if the {@code mbsc} parameter is null,
139.459 - * or if the communication with {@code mbsc} fails, or if {@code mbsc}
139.460 - * does not support contexts. If the communication with {@code mbsc}
139.461 - * fails, the {@linkplain Throwable#getCause() cause} of this exception
139.462 - * will be an {@code IOException}. If {@code mbsc} does not support
139.463 - * contexts, the cause will be an {@link InstanceNotFoundException}.
139.464 - */
139.465 - public static MBeanServerConnection withDynamicContext(
139.466 - MBeanServerConnection mbsc) {
139.467 - // Probe mbsc to get the right exception if it's incommunicado or
139.468 - // doesn't support namespaces.
139.469 - JMXNamespaces.narrowToNamespace(mbsc, NAMESPACE);
139.470 - return (MBeanServerConnection) Proxy.newProxyInstance(
139.471 - MBeanServerConnection.class.getClassLoader(),
139.472 - new Class<?>[] {MBeanServerConnection.class},
139.473 - new DynamicContextIH(mbsc));
139.474 - }
139.475 -
139.476 - private static class DynamicContextIH implements InvocationHandler {
139.477 - private final MBeanServerConnection mbsc;
139.478 -
139.479 - public DynamicContextIH(MBeanServerConnection mbsc) {
139.480 - this.mbsc = mbsc;
139.481 - }
139.482 -
139.483 - public Object invoke(Object proxy, Method method, Object[] args)
139.484 - throws Throwable {
139.485 - MBeanServerConnection dynMBSC = withContext(
139.486 - mbsc, MBeanServerConnection.class, getContext(), false);
139.487 - try {
139.488 - return method.invoke(dynMBSC, args);
139.489 - } catch (InvocationTargetException e) {
139.490 - throw e.getCause();
139.491 - }
139.492 - }
139.493 - }
139.494 -
139.495 - private static <T extends MBeanServerConnection> T withContext(
139.496 - T mbsc, Class<T> mbscClass, String key, String value) {
139.497 - return withContext(
139.498 - mbsc, mbscClass, Collections.singletonMap(key, value), true);
139.499 - }
139.500 -
139.501 - private static <T extends MBeanServerConnection> T withContext(
139.502 - T mbsc, Class<T> mbscClass, Map<String, String> context,
139.503 - boolean probe) {
139.504 - if (mbsc == null || context == null)
139.505 - throw new IllegalArgumentException("Null parameter");
139.506 - if (context.isEmpty())
139.507 - return mbsc;
139.508 - validateContext(context);
139.509 - Map<String, String> contextMap = null;
139.510 - if (mbsc.getClass() == RoutingServerProxy.class ||
139.511 - mbsc.getClass() == RoutingProxy.class) {
139.512 - RoutingProxy<?> nsp = (RoutingProxy<?>) mbsc;
139.513 - String where = nsp.getSourceNamespace();
139.514 - if (where.startsWith(NAMESPACE_PLUS_SEP)) {
139.515 - /* Try to merge the existing context namespace with the
139.516 - * new one. If it doesn't work, we fall back to just
139.517 - * prefixing jmx.context//key=value, which
139.518 - * might lead to a name like jmx.c//k1=v1//jmx.c//k2=v2//d:k=v.
139.519 - */
139.520 - String encodedContext =
139.521 - where.substring(NAMESPACE_PLUS_SEP.length());
139.522 - if (encodedContext.indexOf(NAMESPACE_SEPARATOR) < 0) {
139.523 - contextMap = stringToMapOrNull(encodedContext);
139.524 - if (contextMap != null) {
139.525 - contextMap.putAll(context);
139.526 - mbsc = mbscClass.cast(nsp.source());
139.527 - }
139.528 - }
139.529 - }
139.530 - }
139.531 - if (contextMap == null)
139.532 - contextMap = context;
139.533 - String contextDir = NAMESPACE_PLUS_SEP + mapToString(contextMap);
139.534 - if (mbscClass == MBeanServer.class) {
139.535 - return mbscClass.cast(RoutingServerProxy.cd(
139.536 - (MBeanServer) mbsc, contextDir, probe));
139.537 - } else if (mbscClass == MBeanServerConnection.class) {
139.538 - return mbscClass.cast(RoutingConnectionProxy.cd(
139.539 - mbsc, contextDir, probe));
139.540 - } else
139.541 - throw new AssertionError("Bad MBSC: " + mbscClass);
139.542 - }
139.543 -
139.544 - /**
139.545 - * <p>Returns an encoded context prefix for ObjectNames.
139.546 - * If the given context is empty, {@code ""} is returned.
139.547 - * Otherwise, this method returns a string of the form
139.548 - * {@code "jmx.context//key=value;key=value;..."}.
139.549 - * For example, if the context has keys {@code "jmx.locale"}
139.550 - * and {@code "xid"} with respective values {@code "fr"}
139.551 - * and {@code "1234"}, this method will return
139.552 - * {@code "jmx.context//jmx.locale=fr;xid=1234"} or
139.553 - * {@code "jmx.context//xid=1234;jmx.locale=fr"}.</p>
139.554 - *
139.555 - * <p>Each key and each value in the encoded string is subject to
139.556 - * encoding as if by the method {@link URLEncoder#encode(String, String)}
139.557 - * with a character encoding of {@code "UTF-8"}, but with the additional
139.558 - * encoding of any {@code *} character as {@code "%2A"}. This ensures
139.559 - * that keys and values can contain any character. Without encoding,
139.560 - * characters such as {@code =} and {@code :} would pose problems.</p>
139.561 - *
139.562 - * @param context the context to encode.
139.563 - *
139.564 - * @return the context in encoded form.
139.565 - *
139.566 - * @throws IllegalArgumentException if the {@code context} parameter
139.567 - * is null or if it contains a null key or value.
139.568 - **/
139.569 - public static String encode(Map<String, String> context) {
139.570 - if (context == null)
139.571 - throw new IllegalArgumentException("Null context");
139.572 - if (context.isEmpty())
139.573 - return "";
139.574 - StringBuilder sb = new StringBuilder();
139.575 - for (Map.Entry<String, String> entry : context.entrySet()) {
139.576 - String key = entry.getKey();
139.577 - String value = entry.getValue();
139.578 - if (key == null || value == null)
139.579 - throw new IllegalArgumentException("Null key or value");
139.580 - if (sb.length() > 0)
139.581 - sb.append(";");
139.582 - sb.append(encode(key)).append("=").append(encode(value));
139.583 - }
139.584 - sb.insert(0, NAMESPACE_PLUS_SEP);
139.585 - return sb.toString();
139.586 - }
139.587 -
139.588 - /**
139.589 - * <p>Create a new {@link MBeanServerForwarder} that applies the context
139.590 - * received from a client to the current thread. A client using
139.591 - * one of the various {@code with*} methods (for example {@link
139.592 - * #withContext(MBeanServerConnection, String, String) withContext}) will
139.593 - * encode that context into the {@code ObjectName} of each
139.594 - * {@code MBeanServer} request. The object returned by this method
139.595 - * decodes the context from that {@code ObjectName} and applies it
139.596 - * as described for {@link #doWithContext doWithContext} while performing
139.597 - * the {@code MBeanServer} request using the {@code ObjectName} without
139.598 - * the encoded context.</p>
139.599 - *
139.600 - * <p>This forwarder can be used in a number of ways:</p>
139.601 - *
139.602 - * <ul>
139.603 - * <li>
139.604 - * <p>To add context decoding to a local {@code MBeanServer}, you can
139.605 - * write:</p>
139.606 - * <pre>
139.607 - * MBeanServer mbs = {@link
139.608 - * java.lang.management.ManagementFactory#getPlatformMBeanServer()
139.609 - * ManagementFactory.getPlatformMBeanServer()}; // for example
139.610 - * mbs = ClientContext.newContextForwarder(mbs, null);
139.611 - * </pre>
139.612 - *
139.613 - * <li>
139.614 - * <p>To add context decoding to a {@linkplain
139.615 - * javax.management.remote.JMXConnectorServer connector server}:</p>
139.616 - * <pre>
139.617 - * JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(...);
139.618 - * MBeanServer nextMBS = cs.getMBeanServer();
139.619 - * MBeanServerForwarder mbsf = ClientContext.newContextForwarder(nextMBS, null);
139.620 - * cs.{@link
139.621 - * javax.management.remote.JMXConnectorServer#setMBeanServerForwarder
139.622 - * setMBeanServerForwarder}(mbsf);
139.623 - * </pre>
139.624 - *
139.625 - * <li>
139.626 - * <p>For connectors, such as the standard RMI connector, that support
139.627 - * a {@linkplain
139.628 - * javax.management.remote.JMXConnectorServer#getSystemMBeanServerForwarder
139.629 - * system chain} of {@code MBeanServerForwarder}s, this forwarder will
139.630 - * be installed in that chain by default. See
139.631 - * {@link javax.management.remote.JMXConnectorServer#CONTEXT_FORWARDER
139.632 - * JMXConnectorServer.CONTEXT_FORWARDER}.
139.633 - * </p>
139.634 - *
139.635 - * </ul>
139.636 - *
139.637 - * @param nextMBS the next {@code MBeanServer} in the chain of
139.638 - * forwarders, which might be another {@code MBeanServerForwarder} or
139.639 - * a plain {@code MBeanServer}. This is the object to which {@code
139.640 - * MBeanServer} requests that do not include a context are sent. It
139.641 - * will be the value of {@link MBeanServerForwarder#getMBeanServer()
139.642 - * getMBeanServer()} on the returned object, and can be changed with {@link
139.643 - * MBeanServerForwarder#setMBeanServer setMBeanServer}. It can be null but
139.644 - * must be set to a non-null value before any {@code MBeanServer} requests
139.645 - * arrive.
139.646 - *
139.647 - * @param loopMBS the {@code MBeanServer} to which requests that contain
139.648 - * an encoded context should be sent once the context has been decoded.
139.649 - * For example, if the request is {@link MBeanServer#getAttribute
139.650 - * getAttribute}{@code ("jmx.context//jmx.locale=fr//java.lang:type=Runtime",
139.651 - * "Name")}, then the {@linkplain #getContext() context} of the thread
139.652 - * executing that request will have {@code "jmx.locale"} set to {@code "fr"}
139.653 - * while executing {@code loopMBS.getAttribute("java.lang:type=Runtime",
139.654 - * "Name")}. If this parameter is null, then these requests will be
139.655 - * sent to the newly-created {@code MBeanServerForwarder}. Usually
139.656 - * the parameter will either be null or will be the result of {@link
139.657 - * javax.management.remote.JMXConnectorServer#getSystemMBeanServerForwarder
139.658 - * getSystemMBeanServerForwarder()} for the connector server in which
139.659 - * this forwarder will be installed.
139.660 - *
139.661 - * @return a new {@code MBeanServerForwarder} that decodes client context
139.662 - * from {@code ObjectName}s.
139.663 - */
139.664 - /*
139.665 - * What we're building here is confusing enough to need a diagram.
139.666 - * The MBSF that we return is actually the composition of two forwarders:
139.667 - * the first one simulates the existence of the MBean
139.668 - * jmx.context//:type=JMXNamespace, and the second one simulates the
139.669 - * existence of the namespace jmx.context//. Furthermore, that namespace
139.670 - * loops back to the composed forwarder, so that something like
139.671 - * jmx.context//foo=bar//jmxcontext//baz=buh will work. And the loopback
139.672 - * goes through yet another forwarder, which simulates the existence of
139.673 - * (e.g.) jmx.context//foo=bar//:type=JMXNamespace, which is needed
139.674 - * notably so that narrowToNamespace will work.
139.675 - *
139.676 - * | +--------------------------------------------------+
139.677 - * v v |
139.678 - * +----------------+ |
139.679 - * | Handler MBSF |->accesses to jmx.context//:type=JMXNamespace |
139.680 - * +----------------+ (handled completely here) +-------------------+
139.681 - * | | 2nd Handler MBSF |
139.682 - * v +-------------------+
139.683 - * +----------------+ ^
139.684 - * | Namespace MBSF |->accesses to jmx.context//**-------------------+
139.685 - * +----------------+ (after attaching context to thread)
139.686 - * |
139.687 - * v accesses to anything else
139.688 - *
139.689 - * And finally, we need to ensure that from the outside the composed object
139.690 - * looks like a single forwarder, so that its get/setMBeanServer methods
139.691 - * will do the expected thing. That's what the anonymous subclass is for.
139.692 - */
139.693 - public static MBeanServerForwarder newContextForwarder(
139.694 - MBeanServer nextMBS, MBeanServer loopMBS) {
139.695 - final MBeanServerForwarder mbsWrapper =
139.696 - new IdentityMBeanServerForwarder(nextMBS);
139.697 - DynamicMBean handlerMBean = new StandardMBean(
139.698 - new JMXNamespace(mbsWrapper), JMXNamespaceMBean.class, false);
139.699 - SingleMBeanForwarder handlerForwarder = new SingleMBeanForwarder(
139.700 - CLIENT_CONTEXT_NAMESPACE_HANDLER, handlerMBean, true) {
139.701 - @Override
139.702 - public MBeanServer getMBeanServer() {
139.703 - return ((MBeanServerForwarder) super.getMBeanServer()).getMBeanServer();
139.704 - }
139.705 -
139.706 - @Override
139.707 - public void setMBeanServer(MBeanServer mbs1) {
139.708 - MBeanServerForwarder mbsf1 = (MBeanServerForwarder)
139.709 - super.getMBeanServer();
139.710 - if (mbsf1 != null)
139.711 - mbsf1.setMBeanServer(mbs1);
139.712 - else
139.713 - super.setMBeanServer(mbs1);
139.714 - mbsWrapper.setMBeanServer(mbs1);
139.715 - }
139.716 - };
139.717 - if (loopMBS == null)
139.718 - loopMBS = handlerForwarder;
139.719 - ContextInvocationHandler contextIH =
139.720 - new ContextInvocationHandler(nextMBS, loopMBS);
139.721 - MBeanServerForwarder contextForwarder = newForwarderProxy(contextIH);
139.722 - handlerForwarder.setMBeanServer(contextForwarder);
139.723 - return handlerForwarder;
139.724 - }
139.725 -
139.726 - /**
139.727 - * <p>Create a new {@link MBeanServerForwarder} that localizes
139.728 - * descriptions in {@code MBeanInfo} instances returned by
139.729 - * {@link MBeanServer#getMBeanInfo getMBeanInfo}. The {@code
139.730 - * MBeanServerForwarder} returned by this method passes all {@code
139.731 - * MBeanServer} methods through unchanged to the supplied object, {@code
139.732 - * mbs}, with the exception of {@code getMBeanInfo}. To handle {@code
139.733 - * getMBeanInfo(objectName)}, it calls {@code mbs.getMBeanInfo(objectName)}
139.734 - * to get an {@code MBeanInfo}, {@code mbi}; it calls {@link
139.735 - * MBeanServer#getClassLoaderFor mbs.getClassLoaderFor(objectName)} to
139.736 - * get a {@code ClassLoader}, {@code cl}; and it calls {@link
139.737 - * #getLocale} to get a {@code Locale}, {@code locale}. The order
139.738 - * of these three calls is not specified. Then the result is {@code
139.739 - * mbi.localizeDescriptions(locale, loader)}.</p>
139.740 - *
139.741 - * <p>This forwarder can be used in a number of ways:</p>
139.742 - *
139.743 - * <ul>
139.744 - * <li>
139.745 - * <p>To add description localization to a local {@code MBeanServer}, you
139.746 - * can write:</p>
139.747 - *
139.748 - * <pre>
139.749 - * MBeanServer mbs = {@link
139.750 - * java.lang.management.ManagementFactory#getPlatformMBeanServer()
139.751 - * ManagementFactory.getPlatformMBeanServer()}; // for example
139.752 - * mbs = ClientContext.newLocalizeMBeanInfoForwarder(mbs);
139.753 - * </pre>
139.754 - *
139.755 - * <li>
139.756 - * <p>To add description localization to a {@linkplain
139.757 - * javax.management.remote.JMXConnectorServer connector server}, you will
139.758 - * need to add both a {@linkplain #newContextForwarder context forwarder}
139.759 - * and a localization forwarder, for example like this:</p>
139.760 - *
139.761 - * <pre>
139.762 - * JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(...);
139.763 - * MBeanServer nextMBS = cs.getMBeanServer();
139.764 - * MBeanServerForwarder localizeMBSF =
139.765 - * ClientContext.newLocalizeMBeanInfoForwarder(nextMBS);
139.766 - * MBeanServerForwarder contextMBSF =
139.767 - * ClientContext.newContextForwarder(localizeMBSF, null);
139.768 - * cs.{@link
139.769 - * javax.management.remote.JMXConnectorServer#setMBeanServerForwarder
139.770 - * setMBeanServerForwarder}(contextMBSF);
139.771 - * </pre>
139.772 - *
139.773 - * <p>Notice that the context forwarder must run before the localization
139.774 - * forwarder, so that the locale is correctly established when the latter
139.775 - * runs. So the {@code nextMBS} parameter of the context forwarder must
139.776 - * be the localization forwarder, and not vice versa.</p>
139.777 - *
139.778 - * <li>
139.779 - * <p>For connectors, such as the standard RMI connector, that support
139.780 - * a {@linkplain
139.781 - * javax.management.remote.JMXConnectorServer#getSystemMBeanServerForwarder
139.782 - * system chain} of {@code MBeanServerForwarder}s, the context forwarder and
139.783 - * the localization forwarder will be installed in that chain, in the right
139.784 - * order, if you include
139.785 - * {@link
139.786 - * javax.management.remote.JMXConnectorServer#LOCALIZE_MBEAN_INFO_FORWARDER
139.787 - * LOCALIZE_MBEAN_INFO_FORWARDER} in the environment {@code Map} with
139.788 - * the value {@code "true"}, for example like this:</p>
139.789 - * </p>
139.790 - * <pre>
139.791 - * MBeanServer mbs = ...;
139.792 - * JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://...");
139.793 - * {@code Map<String, Object>} env = new {@code HashMap<String, Object>}();
139.794 - * env.put(JMXConnectorServer.LOCALIZE_MBEAN_INFO_FORWARDER, "true");
139.795 - * JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(
139.796 - * url, env, mbs);
139.797 - * </pre>
139.798 - *
139.799 - * </ul>
139.800 - *
139.801 - * @param mbs the next {@code MBeanServer} in the chain of
139.802 - * forwarders, which might be another {@code MBeanServerForwarder}
139.803 - * or a plain {@code MBeanServer}. It will be the value of
139.804 - * {@link MBeanServerForwarder#getMBeanServer() getMBeanServer()}
139.805 - * on the returned object, and can be changed with {@link
139.806 - * MBeanServerForwarder#setMBeanServer setMBeanServer}. It can be null but
139.807 - * must be set to a non-null value before any {@code MBeanServer} requests
139.808 - * arrive.
139.809 - *
139.810 - * @return a new {@code MBeanServerForwarder} that localizes descriptions
139.811 - * in the result of {@code getMBeanInfo}.
139.812 - */
139.813 - public static MBeanServerForwarder newLocalizeMBeanInfoForwarder(
139.814 - MBeanServer mbs) {
139.815 - return new IdentityMBeanServerForwarder(mbs) {
139.816 - @Override
139.817 - public MBeanInfo getMBeanInfo(ObjectName name)
139.818 - throws InstanceNotFoundException, IntrospectionException,
139.819 - ReflectionException {
139.820 - MBeanInfo mbi = super.getMBeanInfo(name);
139.821 - Locale locale = getLocale();
139.822 - ClassLoader loader = getClassLoaderFor(name);
139.823 - return mbi.localizeDescriptions(locale, loader);
139.824 - }
139.825 - };
139.826 - }
139.827 -
139.828 - private static MBeanServerForwarder newForwarderProxy(InvocationHandler ih) {
139.829 - return (MBeanServerForwarder) Proxy.newProxyInstance(
139.830 - MBeanServerForwarder.class.getClassLoader(),
139.831 - new Class<?>[] {MBeanServerForwarder.class},
139.832 - ih);
139.833 - }
139.834 -
139.835 - // A proxy connection that will strip the 'contextDir' at input (routing),
139.836 - // and put it back at output (createMBean / registerMBean / query* /
139.837 - // getObjectInstance). Usually RoutingProxy / RoutingServerProxy are used
139.838 - // the other way round (they are used for 'cd' - where they need to add
139.839 - // something at input and remove it at output).
139.840 - // For 'cd' operations we create RoutingProxys with a non empty sourceDir,
139.841 - // and a possibly non-empty targetDir. This is the only case where we use
139.842 - // RoutingProxies with an empty sourceDir (sourceDir is what we add at input
139.843 - // and remove at output, targetDir is what we remove at input and add at
139.844 - // output.
139.845 - //
139.846 - // Note that using a transient ContextRoutingConnection
139.847 - // is possible only because RoutingProxys don't rewrite
139.848 - // notifications sources - otherwise we would have to
139.849 - // keep the ContextRoutingConnection - just to preserve
139.850 - // the 'wrapping listeners'
139.851 - //
139.852 - private static final class ContextRoutingConnection
139.853 - extends RoutingServerProxy {
139.854 - public ContextRoutingConnection(MBeanServer source,
139.855 - String contextDir) {
139.856 - super(source, "", contextDir, false);
139.857 - }
139.858 -
139.859 - // Not really needed - but this is safer and more optimized.
139.860 - // See RoutingProxy for more details.
139.861 - //
139.862 - @Override
139.863 - public Integer getMBeanCount() {
139.864 - return source().getMBeanCount();
139.865 - }
139.866 -
139.867 - // Not really needed - but this is safer and more optimized.
139.868 - // See RoutingProxy for more details.
139.869 - //
139.870 - @Override
139.871 - public String[] getDomains() {
139.872 - return source().getDomains();
139.873 - }
139.874 -
139.875 - // Not really needed - but this is safer and more optimized.
139.876 - // See RoutingProxy for more details.
139.877 - //
139.878 - @Override
139.879 - public String getDefaultDomain() {
139.880 - return source().getDefaultDomain();
139.881 - }
139.882 -
139.883 - }
139.884 -
139.885 - private static class ContextInvocationHandler implements InvocationHandler {
139.886 - /*
139.887 - * MBeanServer requests that don't include jmx.context//foo=bar//
139.888 - * are forwarded to forwardMBS, which is the unadorned MBeanServer
139.889 - * that knows nothing about the context namespace.
139.890 - * MBeanServer requests that do include this prefix will
139.891 - * usually (depending on the value of the loopMBS parameter to
139.892 - * newContextForwarder) loop back to the combined MBeanServerForwarder
139.893 - * that first implements
139.894 - * jmx.context//:type=JMXNamespace and then implements
139.895 - * jmx.context//foo=bar//. The reason is that it is valid
139.896 - * to have jmx.context//foo=bar//jmx.context//baz=buh//, although
139.897 - * usually that will be combined into jmx.context//foo=bar;baz=buh//.
139.898 - *
139.899 - * Before forwarding to loopMBS, we must check for :type=JMXNamespace
139.900 - * so that jmx.context//foo=bar//:type=JMXNamespace will exist. Its
139.901 - * existence is partial because it must remain "invisible": it should
139.902 - * not show up in queryNames or getMBeanCount even though it does
139.903 - * accept getAttribute and isRegistered and all other methods that
139.904 - * reference a single MBean.
139.905 - */
139.906 - private MBeanServer forwardMBS;
139.907 - private final MBeanServer loopMBS;
139.908 - private static final MBeanServer emptyMBS = new MBeanServerSupport() {
139.909 - @Override
139.910 - public DynamicMBean getDynamicMBeanFor(ObjectName name)
139.911 - throws InstanceNotFoundException {
139.912 - throw new InstanceNotFoundException(name.toString());
139.913 - }
139.914 -
139.915 - @Override
139.916 - protected Set<ObjectName> getNames() {
139.917 - return Collections.emptySet();
139.918 - }
139.919 - };
139.920 -
139.921 - ContextInvocationHandler(MBeanServer forwardMBS, MBeanServer loopMBS) {
139.922 - this.forwardMBS = forwardMBS;
139.923 - DynamicMBean handlerMBean = new StandardMBean(
139.924 - new JMXNamespace(loopMBS), JMXNamespaceMBean.class, false);
139.925 - MBeanServerForwarder handlerMBS = new SingleMBeanForwarder(
139.926 - NAMESPACE_HANDLER_WITHOUT_NAMESPACE, handlerMBean, false);
139.927 - handlerMBS.setMBeanServer(loopMBS);
139.928 - this.loopMBS = handlerMBS;
139.929 - }
139.930 -
139.931 - public Object invoke(Object proxy, final Method method, final Object[] args)
139.932 - throws Throwable {
139.933 - String methodName = method.getName();
139.934 - Class<?>[] paramTypes = method.getParameterTypes();
139.935 -
139.936 - // If this is a method from MBeanServerForwarder, handle it here.
139.937 - // There are only two such methods: getMBeanServer() and
139.938 - // setMBeanServer(mbs).
139.939 - if (methodName.equals("getMBeanServer"))
139.940 - return forwardMBS;
139.941 - else if (methodName.equals("setMBeanServer")) {
139.942 - this.forwardMBS = (MBeanServer) args[0];
139.943 - return null;
139.944 - }
139.945 -
139.946 - // It is a method from MBeanServer.
139.947 - // Find the first parameter whose declared type is ObjectName,
139.948 - // and see if it is in the context namespace. If so we need to
139.949 - // trigger the logic for that namespace. If not, we simply
139.950 - // forward to the next MBeanServer in the chain. This logic
139.951 - // depends on the fact that if a method in the MBeanServer interface
139.952 - // has a "routing" ObjectName parameter, it is always the first
139.953 - // parameter of that type. Conversely, if a method has an
139.954 - // ObjectName parameter, then it makes sense to "route" that
139.955 - // method. Except for deserialize and instantiate, but if we
139.956 - // recognize a context namespace in those methods' ObjectName
139.957 - // parameters it is pretty harmless.
139.958 - int objectNameI = -1;
139.959 - for (int i = 0; i < paramTypes.length; i++) {
139.960 - if (paramTypes[i] == ObjectName.class) {
139.961 - objectNameI = i;
139.962 - break;
139.963 - }
139.964 - }
139.965 -
139.966 - if (objectNameI < 0)
139.967 - return invoke(method, forwardMBS, args);
139.968 -
139.969 - ObjectName target = (ObjectName) args[objectNameI];
139.970 - if (target == null ||
139.971 - !target.getDomain().startsWith(NAMESPACE_PLUS_SEP))
139.972 - return invoke(method, forwardMBS, args);
139.973 -
139.974 - String domain = target.getDomain().substring(NAMESPACE_PLUS_SEP.length());
139.975 -
139.976 - // The method routes through the (simulated) context namespace.
139.977 - // Decode the context after it, e.g. jmx.context//jmx.locale=fr//...
139.978 - // If there is no context part, we can throw an exception,
139.979 - // because a forwarder has already handled the unique MBean
139.980 - // jmx.context//:type=JMXNamespace.
139.981 - int sep = domain.indexOf(NAMESPACE_SEPARATOR);
139.982 - if (sep < 0)
139.983 - return invoke(method, emptyMBS, args); // throw exception
139.984 - final String encodedContext = domain.substring(0, sep);
139.985 -
139.986 - if (method.getName().startsWith("query") &&
139.987 - (encodedContext.contains("*") || encodedContext.contains("?"))) {
139.988 - // Queries like jmx.context//*//d:k=v return
139.989 - // an empty set, consistent with "real" namespaces.
139.990 - return Collections.EMPTY_SET;
139.991 - }
139.992 -
139.993 - Map<String, String> ctx = new TreeMap<String, String>(getContext());
139.994 - ctx.putAll(stringToMap(encodedContext));
139.995 -
139.996 - return doWithContext(ctx, new Callable<Object>() {
139.997 - public Object call() throws Exception {
139.998 - // Create a proxy connection that will strip
139.999 - // "jmx.context//" + encodedContext + "//" on input,
139.1000 - // and put it back on output.
139.1001 - //
139.1002 - // Note that using a transient ContextRoutingConnection
139.1003 - // is possible only because it doesn't rewrite
139.1004 - // notification sources - otherwise we would have to
139.1005 - // keep the ContextRoutingConnection - just to preserve
139.1006 - // the 'wrapping listeners'
139.1007 - //
139.1008 - String namespace = NAMESPACE_PLUS_SEP + encodedContext;
139.1009 - final ContextRoutingConnection route =
139.1010 - new ContextRoutingConnection(loopMBS, namespace);
139.1011 -
139.1012 - if (LOG.isLoggable(Level.FINE))
139.1013 - LOG.fine("context="+encodedContext);
139.1014 - if (LOG.isLoggable(Level.FINER))
139.1015 - LOG.finer(method.getName()+""+
139.1016 - ((args==null)?"()":(""+Arrays.asList(args))));
139.1017 -
139.1018 - return invoke(method, route, args);
139.1019 - }
139.1020 - });
139.1021 - }
139.1022 -
139.1023 - private static Object invoke(Method method, Object target, Object[] args)
139.1024 - throws Exception {
139.1025 - try {
139.1026 - return method.invoke(target, args);
139.1027 - } catch (InvocationTargetException e) {
139.1028 - Throwable cause = e.getCause();
139.1029 - if (cause instanceof Error)
139.1030 - throw (Error) cause;
139.1031 - throw (Exception) cause;
139.1032 - }
139.1033 - }
139.1034 - }
139.1035 -
139.1036 - private static String mapToString(Map<String, String> map) {
139.1037 - StringBuilder sb = new StringBuilder();
139.1038 - for (Map.Entry<String, String> entry : map.entrySet()) {
139.1039 - String key = encode(entry.getKey());
139.1040 - String value = encode(entry.getValue());
139.1041 - if (sb.length() > 0)
139.1042 - sb.append(";");
139.1043 - sb.append(key).append("=").append(value);
139.1044 - }
139.1045 - return sb.toString();
139.1046 - }
139.1047 -
139.1048 - private static Map<String, String> stringToMap(String encodedContext) {
139.1049 - Map<String, String> map = stringToMapOrNull(encodedContext);
139.1050 - if (map == null) {
139.1051 - throw new IllegalArgumentException(
139.1052 - "Invalid encoded context: " + encodedContext);
139.1053 - }
139.1054 - return map;
139.1055 - }
139.1056 -
139.1057 - private static Map<String, String> stringToMapOrNull(String encodedContext) {
139.1058 - Map<String, String> map = new LinkedHashMap<String, String>();
139.1059 - StringTokenizer stok = new StringTokenizer(encodedContext, ";");
139.1060 - while (stok.hasMoreTokens()) {
139.1061 - String tok = stok.nextToken();
139.1062 - int eq = tok.indexOf('=');
139.1063 - if (eq < 0)
139.1064 - return null;
139.1065 - String key = decode(tok.substring(0, eq));
139.1066 - if (key.equals(""))
139.1067 - return null;
139.1068 - String value = decode(tok.substring(eq + 1));
139.1069 - map.put(key, value);
139.1070 - }
139.1071 - return map;
139.1072 - }
139.1073 -
139.1074 - private static String encode(String s) {
139.1075 - try {
139.1076 - s = URLEncoder.encode(s, "UTF-8");
139.1077 - } catch (UnsupportedEncodingException e) {
139.1078 - throw new RuntimeException(e); // Should not happen
139.1079 - }
139.1080 - return s.replace("*", "%2A");
139.1081 - // The * character is left intact in URL encodings, but for us it
139.1082 - // is special (an ObjectName wildcard) so we must map it.
139.1083 - // We are assuming that URLDecoder will decode it the same way as any
139.1084 - // other hex escape.
139.1085 - }
139.1086 -
139.1087 - private static String decode(String s) {
139.1088 - try {
139.1089 - return URLDecoder.decode(s, "UTF-8");
139.1090 - } catch (UnsupportedEncodingException e) {
139.1091 - throw new RuntimeException(e);
139.1092 - }
139.1093 - }
139.1094 -}
140.1 --- a/src/share/classes/javax/management/Description.java Mon Nov 23 10:04:47 2009 +0000
140.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
140.3 @@ -1,180 +0,0 @@
140.4 -/*
140.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
140.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
140.7 - *
140.8 - * This code is free software; you can redistribute it and/or modify it
140.9 - * under the terms of the GNU General Public License version 2 only, as
140.10 - * published by the Free Software Foundation. Sun designates this
140.11 - * particular file as subject to the "Classpath" exception as provided
140.12 - * by Sun in the LICENSE file that accompanied this code.
140.13 - *
140.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
140.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
140.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
140.17 - * version 2 for more details (a copy is included in the LICENSE file that
140.18 - * accompanied this code).
140.19 - *
140.20 - * You should have received a copy of the GNU General Public License version
140.21 - * 2 along with this work; if not, write to the Free Software Foundation,
140.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
140.23 - *
140.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
140.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
140.26 - * have any questions.
140.27 - */
140.28 -
140.29 -package javax.management;
140.30 -
140.31 -import java.lang.annotation.Documented;
140.32 -import java.lang.annotation.ElementType;
140.33 -import java.lang.annotation.Retention;
140.34 -import java.lang.annotation.RetentionPolicy;
140.35 -import java.lang.annotation.Target;
140.36 -import java.util.ResourceBundle;
140.37 -
140.38 -/**
140.39 - * <p>The textual description of an MBean or part of an MBean. This
140.40 - * description is intended to be displayed to users to help them
140.41 - * understand what the MBean does. Ultimately it will be the value of
140.42 - * the {@code getDescription()} method of an {@link MBeanInfo}, {@link
140.43 - * MBeanAttributeInfo}, or similar.</p>
140.44 - *
140.45 - * <p>This annotation applies to Standard MBean interfaces and to
140.46 - * MXBean interfaces, as well as to MBean classes defined using the
140.47 - * {@link MBean @MBean} or {@link MXBean @MXBean} annotations. For
140.48 - * example, a Standard MBean might be defined like this:</p>
140.49 - *
140.50 - * <pre>
140.51 - * <b>{@code @Description}</b>("Application configuration")
140.52 - * public interface ConfigurationMBean {
140.53 - * <b>{@code @Description}</b>("Cache size in bytes")
140.54 - * public int getCacheSize();
140.55 - * public void setCacheSize(int size);
140.56 - *
140.57 - * <b>{@code @Description}</b>("Last time the configuration was changed, " +
140.58 - * "in milliseconds since 1 Jan 1970")
140.59 - * public long getLastChangedTime();
140.60 - *
140.61 - * <b>{@code @Description}</b>("Save the configuration to a file")
140.62 - * public void save(
140.63 - * <b>{@code @Description}</b>("Optional name of the file, or null for the default name")
140.64 - * String fileName);
140.65 - * }
140.66 - * </pre>
140.67 - *
140.68 - * <p>The {@code MBeanInfo} for this MBean will have a {@link
140.69 - * MBeanInfo#getDescription() getDescription()} that is {@code
140.70 - * "Application configuration"}. It will contain an {@code
140.71 - * MBeanAttributeInfo} for the {@code CacheSize} attribute that is
140.72 - * defined by the methods {@code getCacheSize} and {@code
140.73 - * setCacheSize}, and another {@code MBeanAttributeInfo} for {@code
140.74 - * LastChangedTime}. The {@link MBeanAttributeInfo#getDescription()
140.75 - * getDescription()} for {@code CacheSize} will be {@code "Cache size
140.76 - * in bytes"}. Notice that there is no need to add a
140.77 - * {@code @Description} to both {@code getCacheSize} and {@code
140.78 - * setCacheSize} - either alone will do. But if you do add a
140.79 - * {@code @Description} to both, it must be the same.</p>
140.80 - *
140.81 - * <p>The {@code MBeanInfo} will also contain an {@link
140.82 - * MBeanOperationInfo} where {@link
140.83 - * MBeanOperationInfo#getDescription() getDescription()} is {@code
140.84 - * "Save the configuration to a file"}. This {@code
140.85 - * MBeanOperationInfo} will contain an {@link MBeanParameterInfo}
140.86 - * where {@link MBeanParameterInfo#getDescription() getDescription()}
140.87 - * is {@code "Optional name of the file, or null for the default
140.88 - * name"}.</p>
140.89 - *
140.90 - * <p>The {@code @Description} annotation can also be applied to the
140.91 - * public constructors of the implementation class. Continuing the
140.92 - * above example, the {@code Configuration} class implementing {@code
140.93 - * ConfigurationMBean} might look like this:</p>
140.94 - *
140.95 - * <pre>
140.96 - * public class Configuration implements ConfigurationMBean {
140.97 - * <b>{@code @Description}</b>("A Configuration MBean with the default file name")
140.98 - * public Configuration() {
140.99 - * this(DEFAULT_FILE_NAME);
140.100 - * }
140.101 - *
140.102 - * <b>{@code @Description}</b>("A Configuration MBean with a specified file name")
140.103 - * public Configuration(
140.104 - * <b>{@code @Description}</b>("Name of the file the configuration is stored in")
140.105 - * String fileName) {...}
140.106 - * ...
140.107 - * }
140.108 - * </pre>
140.109 - *
140.110 - * <p>The {@code @Description} annotation also works in MBeans that
140.111 - * are defined using the {@code @MBean} or {@code @MXBean} annotation
140.112 - * on classes. Here is an alternative implementation of {@code
140.113 - * Configuration} that does not use an {@code ConfigurationMBean}
140.114 - * interface.</p>
140.115 - *
140.116 - * <pre>
140.117 - * <b>{@code @MBean}</b>
140.118 - * <b>{@code @Description}</b>("Application configuration")
140.119 - * public class Configuration {
140.120 - * <b>{@code @Description}</b>("A Configuration MBean with the default file name")
140.121 - * public Configuration() {
140.122 - * this(DEFAULT_FILE_NAME);
140.123 - * }
140.124 - *
140.125 - * <b>{@code @Description}</b>("A Configuration MBean with a specified file name")
140.126 - * public Configuration(
140.127 - * <b>{@code @Description}</b>("Name of the file the configuration is stored in")
140.128 - * String fileName) {...}
140.129 - *
140.130 - * <b>{@code @ManagedAttribute}</b>
140.131 - * <b>{@code @Description}</b>("Cache size in bytes")
140.132 - * public int getCacheSize() {...}
140.133 - * <b>{@code @ManagedAttribute}</b>
140.134 - * public void setCacheSize(int size) {...}
140.135 - *
140.136 - * <b>{@code @ManagedOperation}</b>
140.137 - * <b>{@code @Description}</b>("Last time the configuration was changed, " +
140.138 - * "in milliseconds since 1 Jan 1970")
140.139 - * public long getLastChangedTime() {...}
140.140 - *
140.141 - * <b>{@code @ManagedOperation}</b>
140.142 - * <b>{@code @Description}</b>("Save the configuration to a file")
140.143 - * public void save(
140.144 - * <b>{@code @Description}</b>("Optional name of the file, or null for the default name")
140.145 - * String fileName) {...}
140.146 - * ...
140.147 - * }
140.148 - * </pre>
140.149 - */
140.150 -@Documented
140.151 -@Retention(RetentionPolicy.RUNTIME)
140.152 -@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.PARAMETER,
140.153 - ElementType.TYPE})
140.154 -public @interface Description {
140.155 - /**
140.156 - * <p>The description.</p>
140.157 - */
140.158 - String value();
140.159 -
140.160 - /**
140.161 - * <p>The base name for the {@link ResourceBundle} in which the key given in
140.162 - * the {@code descriptionResourceKey} field can be found, for example
140.163 - * {@code "com.example.myapp.MBeanResources"}. If a non-default value
140.164 - * is supplied for this element, it will appear in the
140.165 - * <a href="Descriptor.html#descriptionResourceBundleBaseName"><!--
140.166 - * -->{@code Descriptor}</a> for the annotated item.</p>
140.167 - */
140.168 - @DescriptorKey(
140.169 - value = "descriptionResourceBundleBaseName", omitIfDefault = true)
140.170 - String bundleBaseName() default "";
140.171 -
140.172 - /**
140.173 - * <p>A resource key for the description of this element. In
140.174 - * conjunction with the {@link #bundleBaseName bundleBaseName},
140.175 - * this can be used to find a localized version of the description.
140.176 - * If a non-default value
140.177 - * is supplied for this element, it will appear in the
140.178 - * <a href="Descriptor.html#descriptionResourceKey"><!--
140.179 - * -->{@code Descriptor}</a> for the annotated item.</p>
140.180 - */
140.181 - @DescriptorKey(value = "descriptionResourceKey", omitIfDefault = true)
140.182 - String key() default "";
140.183 -}
141.1 --- a/src/share/classes/javax/management/Descriptor.java Mon Nov 23 10:04:47 2009 +0000
141.2 +++ b/src/share/classes/javax/management/Descriptor.java Wed Nov 25 11:08:25 2009 -0800
141.3 @@ -38,7 +38,6 @@
141.4 import java.util.Locale;
141.5 import java.util.ResourceBundle;
141.6 import javax.management.openmbean.CompositeData;
141.7 -import javax.management.openmbean.MXBeanMappingFactory;
141.8 import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
141.9 import javax.management.openmbean.OpenMBeanOperationInfoSupport;
141.10 import javax.management.openmbean.OpenMBeanParameterInfoSupport;
141.11 @@ -118,22 +117,23 @@
141.12 * deprecation, for example {@code "1.3 Replaced by the Capacity
141.13 * attribute"}.</td>
141.14 *
141.15 - * <tr><td id="descriptionResourceBundleBaseName"><i>descriptionResource<br>
141.16 - * BundleBaseName</i></td><td>String</td><td>Any</td>
141.17 + * <tr><td id="descriptionResourceBundleBaseName">descriptionResource<br>
141.18 + * BundleBaseName</td><td>String</td><td>Any</td>
141.19 *
141.20 * <td>The base name for the {@link ResourceBundle} in which the key given in
141.21 * the {@code descriptionResourceKey} field can be found, for example
141.22 - * {@code "com.example.myapp.MBeanResources"}. See
141.23 - * {@link MBeanInfo#localizeDescriptions MBeanInfo.localizeDescriptions}.</td>
141.24 + * {@code "com.example.myapp.MBeanResources"}. The meaning of this
141.25 + * field is defined by this specification but the field is not set or
141.26 + * used by the JMX API itself.</td>
141.27 *
141.28 - * <tr><td id="descriptionResourceKey"><i>descriptionResourceKey</i></td>
141.29 + * <tr><td id="descriptionResourceKey">descriptionResourceKey</td>
141.30 * <td>String</td><td>Any</td>
141.31 *
141.32 * <td>A resource key for the description of this element. In
141.33 * conjunction with the {@code descriptionResourceBundleBaseName},
141.34 * this can be used to find a localized version of the description.
141.35 - * See {@link MBeanInfo#localizeDescriptions MBeanInfo.localizeDescriptions}.
141.36 - * </td>
141.37 + * The meaning of this field is defined by this specification but the
141.38 + * field is not set or used by the JMX API itself.</td>
141.39 *
141.40 * <tr><td>enabled</td><td>String</td>
141.41 * <td>MBeanAttributeInfo<br>MBeanNotificationInfo<br>MBeanOperationInfo</td>
141.42 @@ -147,31 +147,16 @@
141.43 * might be disabled if it cannot currently be emitted but could be in
141.44 * other circumstances.</td>
141.45 *
141.46 - * <tr id="exceptions"><td><i>exceptions</i><td>String[]</td>
141.47 + * <tr id="exceptions"><td>exceptions<td>String[]</td>
141.48 * <td>MBeanAttributeInfo, MBeanConstructorInfo, MBeanOperationInfo</td>
141.49 *
141.50 * <td>The class names of the exceptions that can be thrown when invoking a
141.51 - * constructor or operation, or getting an attribute. Exceptions thrown when
141.52 + * constructor or operation, or getting an attribute. The meaning of this field
141.53 + * is defined by this specification but the field is not set or used by the
141.54 + * JMX API itself. Exceptions thrown when
141.55 * setting an attribute are specified by the field
141.56 * <a href="#setExceptions">{@code setExceptions}</a>.
141.57 *
141.58 - * <tr id="exceptionErrorCodes"><td>exceptionErrorCodes</td><td>String[]</td>
141.59 - * <td>MBeanAttributeInfo<br>MBeanConstructorInfo<br>MBeanOperationInfo</td>
141.60 - *
141.61 - * <td>The {@linkplain GenericMBeanException#getErrorCode() error codes}
141.62 - * that can appear in a {@link GenericMBeanException} thrown when getting
141.63 - * this attribute or invoking this operation or constructor. See also
141.64 - * <a href="#setExceptionErrorCodes">{@code setExceptionErrorCodes}</a>.
141.65 - *
141.66 - * <tr id="exceptionUserDataTypes"><td>exceptionUserDataTypes</td>
141.67 - * <td>{@link javax.management.openmbean.CompositeType}[]</td>
141.68 - * <td>MBeanAttributeInfo<br>MBeanConstructorInfo<br>MBeanOperationInfo</td>
141.69 - *
141.70 - * <td>The types of {@linkplain GenericMBeanException#getUserData() userData}
141.71 - * that can appear in a {@link GenericMBeanException} thrown when getting
141.72 - * this attribute or invoking this operation or constructor. See also
141.73 - * <a href="#setExceptionUserDataTypes">{@code setExceptionUserDataTypes}</a>.
141.74 - *
141.75 * <tr id="immutableInfo"><td><i>immutableInfo</i><td>String</td>
141.76 * <td>MBeanInfo</td>
141.77 *
141.78 @@ -213,7 +198,7 @@
141.79 * <td>Legal values for an attribute or parameter. See
141.80 * {@link javax.management.openmbean}.</td>
141.81 *
141.82 - * <tr id="locale"><td><i>locale</i></td>
141.83 + * <tr id="locale"><td>locale</td>
141.84 * <td>String</td><td>Any</td>
141.85 *
141.86 * <td>The {@linkplain Locale locale} of the description in this
141.87 @@ -254,21 +239,6 @@
141.88 * StandardMBean} class will have this field in its MBeanInfo
141.89 * Descriptor.</td>
141.90 *
141.91 - * <tr><td id="mxbeanMappingFactoryClass"><i>mxbeanMappingFactoryClass</i>
141.92 - * </td><td>String</td>
141.93 - * <td>MBeanInfo</td>
141.94 - *
141.95 - * <td>The name of the {@link MXBeanMappingFactory} class that was used for this
141.96 - * MXBean, if it was not the {@linkplain MXBeanMappingFactory#DEFAULT default}
141.97 - * one.</td>
141.98 - *
141.99 - * <tr><td id="objectNameTemplate"><i>objectNameTemplate</i>
141.100 - * </td><td>String</td>
141.101 - * <td>MBeanInfo</td>
141.102 - *
141.103 - * <td>The template to use to name this MBean. Its value must be compliant with
141.104 - * the specification of the {@link ObjectNameTemplate} annotation.</td>
141.105 - *
141.106 * <tr id="openType"><td><i>openType</i><td>{@link OpenType}</td>
141.107 * <td>MBeanAttributeInfo<br>MBeanOperationInfo<br>MBeanParameterInfo</td>
141.108 *
141.109 @@ -306,26 +276,11 @@
141.110 * <td>MBeanAttributeInfo</td>
141.111 *
141.112 * <td>The class names of the exceptions that can be thrown when setting
141.113 - * an attribute. Exceptions thrown when getting an attribute are specified
141.114 + * an attribute. The meaning of this field
141.115 + * is defined by this specification but the field is not set or used by the
141.116 + * JMX API itself. Exceptions thrown when getting an attribute are specified
141.117 * by the field <a href="#exceptions">{@code exceptions}</a>.
141.118 *
141.119 - * <tr id="setExceptionErrorCodes"><td>setExceptionErrorCodes</td>
141.120 - * <td>String[]</td><td>MBeanAttributeInfo</td>
141.121 - *
141.122 - * <td>The {@linkplain GenericMBeanException#getErrorCode() error codes}
141.123 - * that can appear in a {@link GenericMBeanException} thrown when setting
141.124 - * this attribute. See also
141.125 - * <a href="#exceptionErrorCodes">{@code exceptionErrorCodes}</a>.
141.126 - *
141.127 - * <tr id="setExceptionUserDataTypes"><td>setExceptionUserDataTypes</td>
141.128 - * <td>{@link javax.management.openmbean.CompositeType}[]</td>
141.129 - * <td>MBeanAttributeInfo</td>
141.130 - *
141.131 - * <td>The types of {@linkplain GenericMBeanException#getUserData() userData}
141.132 - * that can appear in a {@link GenericMBeanException} thrown when setting
141.133 - * this attribute. See also
141.134 - * <a href="#exceptionUserDataTypes">{@code exceptionUserDataTypes}</a>.
141.135 - *
141.136 * <tr><td>severity</td><td>String<br>Integer</td>
141.137 * <td>MBeanNotificationInfo</td>
141.138 *
142.1 --- a/src/share/classes/javax/management/DescriptorFields.java Mon Nov 23 10:04:47 2009 +0000
142.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
142.3 @@ -1,137 +0,0 @@
142.4 -/*
142.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
142.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
142.7 - *
142.8 - * This code is free software; you can redistribute it and/or modify it
142.9 - * under the terms of the GNU General Public License version 2 only, as
142.10 - * published by the Free Software Foundation. Sun designates this
142.11 - * particular file as subject to the "Classpath" exception as provided
142.12 - * by Sun in the LICENSE file that accompanied this code.
142.13 - *
142.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
142.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
142.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
142.17 - * version 2 for more details (a copy is included in the LICENSE file that
142.18 - * accompanied this code).
142.19 - *
142.20 - * You should have received a copy of the GNU General Public License version
142.21 - * 2 along with this work; if not, write to the Free Software Foundation,
142.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
142.23 - *
142.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
142.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
142.26 - * have any questions.
142.27 - */
142.28 -
142.29 -package javax.management;
142.30 -
142.31 -import java.lang.annotation.Documented;
142.32 -import java.lang.annotation.ElementType;
142.33 -import java.lang.annotation.Inherited;
142.34 -import java.lang.annotation.Retention;
142.35 -import java.lang.annotation.RetentionPolicy;
142.36 -import java.lang.annotation.Target;
142.37 -
142.38 -/**
142.39 - * <p>Annotation that adds fields to a {@link Descriptor}. This can be the
142.40 - * Descriptor for an MBean, or for an attribute, operation, or constructor
142.41 - * in an MBean, or for a parameter of an operation or constructor.</p>
142.42 - *
142.43 - * <p>Consider this Standard MBean interface, for example:</p>
142.44 - *
142.45 - * <pre>
142.46 - * public interface CacheControlMBean {
142.47 - * <b>@DescriptorFields("units=bytes")</b>
142.48 - * public long getCacheSize();
142.49 - * }
142.50 - * </pre>
142.51 - *
142.52 - * <p>When a Standard MBean is made using this interface, the usual rules
142.53 - * mean that it will have an attribute called {@code CacheSize} of type
142.54 - * {@code long}. The {@code DescriptorFields} annotation will ensure
142.55 - * that the {@link MBeanAttributeInfo} for this attribute will have a
142.56 - * {@code Descriptor} that has a field called {@code units} with
142.57 - * corresponding value {@code bytes}.</p>
142.58 - *
142.59 - * <p>Similarly, if the interface looks like this:</p>
142.60 - *
142.61 - * <pre>
142.62 - * public interface CacheControlMBean {
142.63 - * <b>@DescriptorFields({"units=bytes", "since=1.5"})</b>
142.64 - * public long getCacheSize();
142.65 - * }
142.66 - * </pre>
142.67 - *
142.68 - * <p>then the resulting {@code Descriptor} will contain the following
142.69 - * fields:</p>
142.70 - *
142.71 - * <table border="2">
142.72 - * <tr><th>Name</th><th>Value</th></tr>
142.73 - * <tr><td>units</td><td>"bytes"</td></tr>
142.74 - * <tr><td>since</td><td>"1.5"</td></tr>
142.75 - * </table>
142.76 - *
142.77 - * <p>The {@code @DescriptorFields} annotation can be applied to:</p>
142.78 - *
142.79 - * <ul>
142.80 - * <li>a Standard MBean or MXBean interface;
142.81 - * <li>a method in such an interface;
142.82 - * <li>a parameter of a method in a Standard MBean or MXBean interface
142.83 - * when that method is an operation (not a getter or setter for an attribute);
142.84 - * <li>a public constructor in the class that implements a Standard MBean
142.85 - * or MXBean;
142.86 - * <li>a parameter in such a constructor.
142.87 - * </ul>
142.88 - *
142.89 - * <p>Other uses of the annotation will either fail to compile or be
142.90 - * ignored.</p>
142.91 - *
142.92 - * <p>Interface annotations are checked only on the exact interface
142.93 - * that defines the management interface of a Standard MBean or an
142.94 - * MXBean, not on its parent interfaces. Method annotations are
142.95 - * checked only in the most specific interface in which the method
142.96 - * appears; in other words, if a child interface overrides a method
142.97 - * from a parent interface, only {@code @DescriptorFields} annotations in
142.98 - * the method in the child interface are considered.
142.99 - *
142.100 - * <p>The Descriptor fields contributed in this way must be consistent
142.101 - * with each other and with any fields contributed by {@link
142.102 - * DescriptorKey @DescriptorKey} annotations. That is, two
142.103 - * different annotations, or two members of the same annotation, must
142.104 - * not define a different value for the same Descriptor field. Fields
142.105 - * from annotations on a getter method must also be consistent with
142.106 - * fields from annotations on the corresponding setter method.</p>
142.107 - *
142.108 - * <p>The Descriptor resulting from these annotations will be merged
142.109 - * with any Descriptor fields provided by the implementation, such as
142.110 - * the <a href="Descriptor.html#immutableInfo">{@code
142.111 - * immutableInfo}</a> field for an MBean. The fields from the annotations
142.112 - * must be consistent with these fields provided by the implementation.</p>
142.113 - *
142.114 - * <h4>{@literal @DescriptorFields and @DescriptorKey}</h4>
142.115 - *
142.116 - * <p>The {@link DescriptorKey @DescriptorKey} annotation provides
142.117 - * another way to use annotations to define Descriptor fields.
142.118 - * <code>@DescriptorKey</code> requires more work but is also more
142.119 - * robust, because there is less risk of mistakes such as misspelling
142.120 - * the name of the field or giving an invalid value.
142.121 - * <code>@DescriptorFields</code> is more convenient but includes
142.122 - * those risks. <code>@DescriptorFields</code> is more
142.123 - * appropriate for occasional use, but for a Descriptor field that you
142.124 - * add in many places, you should consider a purpose-built annotation
142.125 - * using <code>@DescriptorKey</code>.
142.126 - *
142.127 - * @since 1.7
142.128 - */
142.129 -@Documented
142.130 -@Inherited // for @MBean and @MXBean classes
142.131 -@Target({ElementType.CONSTRUCTOR, ElementType.METHOD,
142.132 - ElementType.PARAMETER, ElementType.TYPE})
142.133 -@Retention(RetentionPolicy.RUNTIME)
142.134 -public @interface DescriptorFields {
142.135 - /**
142.136 - * <p>The descriptor fields. Each element of the string looks like
142.137 - * {@code "name=value"}.</p>
142.138 - */
142.139 - public String[] value();
142.140 -}
143.1 --- a/src/share/classes/javax/management/DescriptorKey.java Mon Nov 23 10:04:47 2009 +0000
143.2 +++ b/src/share/classes/javax/management/DescriptorKey.java Wed Nov 25 11:08:25 2009 -0800
143.3 @@ -33,11 +33,6 @@
143.4 * an MBean, or for an attribute, operation, or constructor in an
143.5 * MBean, or for a parameter of an operation or constructor.</p>
143.6 *
143.7 - * <p>(The {@link DescriptorFields @DescriptorFields} annotation
143.8 - * provides another way to add fields to a {@code Descriptor}. See
143.9 - * the documentation for that annotation for a comparison of the
143.10 - * two possibilities.)</p>
143.11 - *
143.12 * <p>Consider this annotation for example:</p>
143.13 *
143.14 * <pre>
143.15 @@ -130,13 +125,12 @@
143.16 * the method in the child interface are considered.
143.17 *
143.18 * <p>The Descriptor fields contributed in this way by different
143.19 - * annotations on the same program element must be consistent with
143.20 - * each other and with any fields contributed by a {@link
143.21 - * DescriptorFields @DescriptorFields} annotation. That is, two
143.22 - * different annotations, or two members of the same annotation, must
143.23 - * not define a different value for the same Descriptor field. Fields
143.24 - * from annotations on a getter method must also be consistent with
143.25 - * fields from annotations on the corresponding setter method.</p>
143.26 + * annotations on the same program element must be consistent. That
143.27 + * is, two different annotations, or two members of the same
143.28 + * annotation, must not define a different value for the same
143.29 + * Descriptor field. Fields from annotations on a getter method must
143.30 + * also be consistent with fields from annotations on the
143.31 + * corresponding setter method.</p>
143.32 *
143.33 * <p>The Descriptor resulting from these annotations will be merged
143.34 * with any Descriptor fields provided by the implementation, such as
143.35 @@ -175,36 +169,4 @@
143.36 @Target(ElementType.METHOD)
143.37 public @interface DescriptorKey {
143.38 String value();
143.39 -
143.40 - /**
143.41 - * <p>Do not include this field in the Descriptor if the annotation
143.42 - * element has its default value. For example, suppose {@code @Units} is
143.43 - * defined like this:</p>
143.44 - *
143.45 - * <pre>
143.46 - * @Documented
143.47 - * @Target(ElementType.METHOD)
143.48 - * @Retention(RetentionPolicy.RUNTIME)
143.49 - * public @interface Units {
143.50 - * @DescriptorKey("units")
143.51 - * String value();
143.52 - *
143.53 - * <b>@DescriptorKey(value = "descriptionResourceKey",
143.54 - * omitIfDefault = true)</b>
143.55 - * String resourceKey() default "";
143.56 - *
143.57 - * <b>@DescriptorKey(value = "descriptionResourceBundleBaseName",
143.58 - * omitIfDefault = true)</b>
143.59 - * String resourceBundleBaseName() default "";
143.60 - * }
143.61 - * </pre>
143.62 - *
143.63 - * <p>Then consider a usage such as {@code @Units("bytes")} or
143.64 - * {@code @Units(value = "bytes", resourceKey = "")}, where the
143.65 - * {@code resourceKey} and {@code resourceBundleBaseNames} elements
143.66 - * have their default values. In this case the Descriptor resulting
143.67 - * from these annotations will not include a {@code descriptionResourceKey}
143.68 - * or {@code descriptionResourceBundleBaseName} field.</p>
143.69 - */
143.70 - boolean omitIfDefault() default false;
143.71 }
144.1 --- a/src/share/classes/javax/management/DynamicWrapperMBean.java Mon Nov 23 10:04:47 2009 +0000
144.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
144.3 @@ -1,62 +0,0 @@
144.4 -/*
144.5 - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
144.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
144.7 - *
144.8 - * This code is free software; you can redistribute it and/or modify it
144.9 - * under the terms of the GNU General Public License version 2 only, as
144.10 - * published by the Free Software Foundation. Sun designates this
144.11 - * particular file as subject to the "Classpath" exception as provided
144.12 - * by Sun in the LICENSE file that accompanied this code.
144.13 - *
144.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
144.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
144.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
144.17 - * version 2 for more details (a copy is included in the LICENSE file that
144.18 - * accompanied this code).
144.19 - *
144.20 - * You should have received a copy of the GNU General Public License version
144.21 - * 2 along with this work; if not, write to the Free Software Foundation,
144.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
144.23 - *
144.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
144.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
144.26 - * have any questions.
144.27 - */
144.28 -
144.29 -package javax.management;
144.30 -
144.31 -/**
144.32 - * <p>An MBean can implement this interface to affect how the MBeanServer's
144.33 - * {@link MBeanServer#getClassLoaderFor getClassLoaderFor} and
144.34 - * {@link MBeanServer#isInstanceOf isInstanceOf} methods behave.
144.35 - * If these methods should refer to a wrapped object rather than the
144.36 - * MBean object itself, then the {@link #getWrappedObject} method should
144.37 - * return that wrapped object.</p>
144.38 - *
144.39 - * @see MBeanServer#getClassLoaderFor
144.40 - * @see MBeanServer#isInstanceOf
144.41 - */
144.42 -public interface DynamicWrapperMBean extends DynamicMBean {
144.43 - /**
144.44 - * <p>The resource corresponding to this MBean. This is the object whose
144.45 - * class name should be reflected by the MBean's
144.46 - * {@link MBeanServer#getMBeanInfo getMBeanInfo()}.<!--
144.47 - * -->{@link MBeanInfo#getClassName getClassName()} for example. For a "plain"
144.48 - * DynamicMBean it will be "this". For an MBean that wraps another
144.49 - * object, in the manner of {@link javax.management.StandardMBean}, it will be the
144.50 - * wrapped object.</p>
144.51 - *
144.52 - * @return The resource corresponding to this MBean.
144.53 - */
144.54 - public Object getWrappedObject();
144.55 -
144.56 - /**
144.57 - * <p>The {@code ClassLoader} for this MBean, which can be used to
144.58 - * retrieve resources associated with the MBean for example. Usually,
144.59 - * it will be
144.60 - * {@link #getWrappedObject()}.{@code getClass().getClassLoader()}.
144.61 - *
144.62 - * @return The {@code ClassLoader} for this MBean.
144.63 - */
144.64 - public ClassLoader getWrappedClassLoader();
144.65 -}
145.1 --- a/src/share/classes/javax/management/GenericMBeanException.java Mon Nov 23 10:04:47 2009 +0000
145.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
145.3 @@ -1,276 +0,0 @@
145.4 -/*
145.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
145.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
145.7 - *
145.8 - * This code is free software; you can redistribute it and/or modify it
145.9 - * under the terms of the GNU General Public License version 2 only, as
145.10 - * published by the Free Software Foundation. Sun designates this
145.11 - * particular file as subject to the "Classpath" exception as provided
145.12 - * by Sun in the LICENSE file that accompanied this code.
145.13 - *
145.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
145.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
145.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
145.17 - * version 2 for more details (a copy is included in the LICENSE file that
145.18 - * accompanied this code).
145.19 - *
145.20 - * You should have received a copy of the GNU General Public License version
145.21 - * 2 along with this work; if not, write to the Free Software Foundation,
145.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
145.23 - *
145.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
145.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
145.26 - * have any questions.
145.27 - */
145.28 -
145.29 -package javax.management;
145.30 -
145.31 -import javax.management.openmbean.CompositeData;
145.32 -
145.33 -/**
145.34 - * <p>A customizable exception that has an optional error code string and
145.35 - * payload. By using this exception in an MBean, you can avoid requiring
145.36 - * clients of the MBean to have custom exception classes.</p>
145.37 - *
145.38 - * <p>An instance of this class has an optional {@linkplain #getErrorCode()
145.39 - * error code}, and an optional {@linkplain #getUserData() payload} known as
145.40 - * {@code userData}. This allows you to distinguish between different
145.41 - * sorts of exception while still using this class for all of them.</p>
145.42 - *
145.43 - * <p>To produce a suitable {@code userData}, it is often simplest to use
145.44 - * the MXBean framework. For example, suppose you want to convey a severity
145.45 - * and a subsystem with your exception, which are respectively an int and a
145.46 - * String. You could define a class like this:</p>
145.47 - *
145.48 - * <pre>
145.49 - * public class ExceptionDetails {
145.50 - * private final int severity;
145.51 - * private final String subsystem;
145.52 - *
145.53 - * {@link java.beans.ConstructorProperties @ConstructorProperties}(<!--
145.54 - * -->{"severity", "subsystem"})
145.55 - * public ExceptionDetails(int severity, String subsystem) {
145.56 - * this.severity = severity;
145.57 - * this.subsystem = subsystem;
145.58 - * }
145.59 - *
145.60 - * public int getSeverity() {
145.61 - * return severity;
145.62 - * }
145.63 - *
145.64 - * public String getSubsystem() {
145.65 - * return subsystem;
145.66 - * }
145.67 - * }
145.68 - * </pre>
145.69 - *
145.70 - * <p>Then you can get the MXBean framework to transform {@code ExceptionDetails}
145.71 - * into {@link CompositeData} like this:</p>
145.72 - *
145.73 - * <pre>
145.74 - * static final <!--
145.75 - * -->{@link javax.management.openmbean.MXBeanMapping MXBeanMapping} <!--
145.76 - * -->exceptionDetailsMapping = <!--
145.77 - * -->{@link javax.management.openmbean.MXBeanMappingFactory#DEFAULT
145.78 - * MXBeanMappingFactory.DEFAULT}.mappingForType(
145.79 - * ExceptionDetails.class, MXBeanMappingFactory.DEFAULT);
145.80 - *
145.81 - * public static GenericMBeanException newGenericMBeanException(
145.82 - * String message, String errorCode, int severity, String subsystem) {
145.83 - * ExceptionDetails details = new ExceptionDetails(severity, subsystem);
145.84 - * CompositeData userData = (CompositeData)
145.85 - * exceptionDetailsMapping.toOpenValue(details);
145.86 - * return new GenericMBeanException(
145.87 - * message, errorCode, userData, (Throwable) null);
145.88 - * }
145.89 - *
145.90 - * ...
145.91 - * throw newGenericMBeanException(message, errorCode, 25, "foosystem");
145.92 - * </pre>
145.93 - *
145.94 - * <p>A client that knows the {@code ExceptionDetails} class can convert
145.95 - * back from the {@code userData} of a {@code GenericMBeanException}
145.96 - * that was generated as above:</p>
145.97 - *
145.98 - * <pre>
145.99 - * ...
145.100 - * try {
145.101 - * mbeanProxy.foo();
145.102 - * } catch (GenericMBeanException e) {
145.103 - * CompositeData userData = e.getUserData();
145.104 - * ExceptionDetails details = (ExceptionDetails)
145.105 - * exceptionDetailsMapping.fromOpenValue(userData);
145.106 - * System.out.println("Exception Severity: " + details.getSeverity());
145.107 - * }
145.108 - * ...
145.109 - * </pre>
145.110 - *
145.111 - * <p>The Descriptor field <a href="Descriptor.html#exceptionErrorCodes"><!--
145.112 - * -->exceptionErrorCodes</a> can be used to specify in the
145.113 - * {@link MBeanOperationInfo} for an operation what the possible
145.114 - * {@linkplain #getErrorCode() error codes} are when that operation throws
145.115 - * {@code GenericMBeanException}. It can also be used in an {@link
145.116 - * MBeanConstructorInfo} or {@link MBeanAttributeInfo} to specify what the
145.117 - * possible error codes are for {@code GenericMBeanException} when invoking
145.118 - * that constructor or getting that attribute, respectively. The field
145.119 - * <a href="Descriptor.html#setExceptionErrorCodes"><!--
145.120 - * -->setExceptionErrorCodes</a> can be used to specify what the possible
145.121 - * error codes are when setting an attribute.</p>
145.122 - *
145.123 - * <p>You may want to use the {@link DescriptorKey @DescriptorKey} facility
145.124 - * to define annotations that allow you to specify the error codes. If you
145.125 - * define...</p>
145.126 - *
145.127 - * <pre>
145.128 - * {@link java.lang.annotation.Documented @Documented}
145.129 - * {@link java.lang.annotation.Target @Target}(ElementType.METHOD)
145.130 - * {@link java.lang.annotation.Retention @Retention}(RetentionPolicy.RUNTIME)
145.131 - * public @interface ErrorCodes {
145.132 - * @DescriptorKey("exceptionErrorCodes")
145.133 - * String[] value();
145.134 - * }
145.135 - * </pre>
145.136 - *
145.137 - * <p>...then you can write MBean interfaces like this...</p>
145.138 - *
145.139 - * <pre>
145.140 - * public interface FooMBean { // or FooMXBean
145.141 - * @ErrorCodes({"com.example.bad", "com.example.worse"})
145.142 - * public void foo() throws GenericMBeanException;
145.143 - * }
145.144 - * </pre>
145.145 - *
145.146 - * <p>The Descriptor field <a href="Descriptor.html#exceptionUserDataTypes"><!--
145.147 - * -->exceptionUserDataTypes</a> can be used to specify in the
145.148 - * {@link MBeanOperationInfo} for an operation what the possible types of
145.149 - * {@linkplain #getUserData() userData} are when that operation throws
145.150 - * {@code GenericMBeanException}. It is an array of
145.151 - * {@link javax.management.openmbean.CompositeType CompositeType} values
145.152 - * describing the possible {@link CompositeData} formats. This field can also be used
145.153 - * in an {@link MBeanConstructorInfo} or {@link MBeanAttributeInfo} to specify
145.154 - * the possible types of user data for {@code GenericMBeanException} when
145.155 - * invoking that constructor or getting that attribute, respectively. The
145.156 - * field
145.157 - * <a href="Descriptor.html#setExceptionUserDataTypes">setExceptionUserDataTypes</a>
145.158 - * can be used to specify the possible types of user data for exceptions when
145.159 - * setting an attribute. If a Descriptor has both {@code exceptionErrorCodes}
145.160 - * and {@code exceptionUserDataTypes} then the two arrays should be the
145.161 - * same size; each pair of corresponding elements describes one kind
145.162 - * of exception. Similarly for {@code setExceptionErrorCodes} and {@code
145.163 - * setExceptionUserDataTypes}.
145.164 - *
145.165 - *
145.166 - * <h4>Serialization</h4>
145.167 - *
145.168 - * <p>For compatibility reasons, instances of this class are serialized as
145.169 - * instances of {@link MBeanException}. Special logic in that class converts
145.170 - * them back to instances of this class at deserialization time. If the
145.171 - * serialized object is deserialized in an earlier version of the JMX API
145.172 - * that does not include this class, then it will appear as just an {@code
145.173 - * MBeanException} and the error code or userData will not be available.</p>
145.174 - *
145.175 - * @since 1.7
145.176 - */
145.177 -public class GenericMBeanException extends MBeanException {
145.178 - private static final long serialVersionUID = -1560202003985932823L;
145.179 -
145.180 - /**
145.181 - * <p>Constructs a new {@code GenericMBeanException} with the given
145.182 - * detail message. This constructor is
145.183 - * equivalent to {@link #GenericMBeanException(String, String,
145.184 - * CompositeData, Throwable) GenericMBeanException(message, "",
145.185 - * null, null)}.</p>
145.186 - *
145.187 - * @param message the exception detail message.
145.188 - */
145.189 - public GenericMBeanException(String message) {
145.190 - this(message, "", null, null);
145.191 - }
145.192 -
145.193 - /**
145.194 - * <p>Constructs a new {@code GenericMBeanException} with the given
145.195 - * detail message and cause. This constructor is
145.196 - * equivalent to {@link #GenericMBeanException(String, String,
145.197 - * CompositeData, Throwable) GenericMBeanException(message, "",
145.198 - * null, cause)}.</p>
145.199 - *
145.200 - * @param message the exception detail message.
145.201 - * @param cause the cause of this exception. Can be null.
145.202 - */
145.203 - public GenericMBeanException(String message, Throwable cause) {
145.204 - this(message, "", null, cause);
145.205 - }
145.206 -
145.207 - /**
145.208 - * <p>Constructs a new {@code GenericMBeanException} with the given
145.209 - * detail message, error code, and user data. This constructor is
145.210 - * equivalent to {@link #GenericMBeanException(String, String,
145.211 - * CompositeData, Throwable) GenericMBeanException(message, errorCode,
145.212 - * userData, null)}.</p>
145.213 - *
145.214 - * @param message the exception detail message.
145.215 - * @param errorCode the exception error code. Specifying a null value
145.216 - * is equivalent to specifying an empty string. It is recommended to use
145.217 - * the same reverse domain name convention as package names, for example
145.218 - * "com.example.foo.UnexpectedFailure". There is no requirement that the
145.219 - * error code be a syntactically valid Java identifier.
145.220 - * @param userData extra information about the exception. Can be null.
145.221 - */
145.222 - public GenericMBeanException(
145.223 - String message, String errorCode, CompositeData userData) {
145.224 - this(message, errorCode, userData, null);
145.225 - }
145.226 -
145.227 - /**
145.228 - * <p>Constructs a new {@code GenericMBeanException} with the given
145.229 - * detail message, error code, user data, and cause.</p>
145.230 - *
145.231 - * @param message the exception detail message.
145.232 - * @param errorCode the exception error code. Specifying a null value
145.233 - * is equivalent to specifying an empty string. It is recommended to use
145.234 - * the same reverse domain name convention as package names, for example
145.235 - * "com.example.foo.UnexpectedFailure". There is no requirement that the
145.236 - * error code be a syntactically valid Java identifier.
145.237 - * @param userData extra information about the exception. Can be null.
145.238 - * @param cause the cause of this exception. Can be null.
145.239 - */
145.240 - public GenericMBeanException(
145.241 - String message, String errorCode, CompositeData userData,
145.242 - Throwable cause) {
145.243 - super(message, (errorCode == null) ? "" : errorCode, userData, cause);
145.244 - }
145.245 -
145.246 - /**
145.247 - * <p>Returns the error code of this exception.</p>
145.248 - *
145.249 - * @return the error code. This value is never null.
145.250 - */
145.251 - public String getErrorCode() {
145.252 - return errorCode;
145.253 - }
145.254 -
145.255 - /**
145.256 - * <p>Returns the userData of this exception.</p>
145.257 - *
145.258 - * @return the userData. Can be null.
145.259 - */
145.260 - public CompositeData getUserData() {
145.261 - return userData;
145.262 - }
145.263 -
145.264 - /**
145.265 - * <p>Instances of this class are serialized as instances of
145.266 - * {@link MBeanException}. {@code MBeanException} has private fields that can
145.267 - * not be set by its public constructors. They can only be set in objects
145.268 - * returned by this method. When an {@code MBeanException} instance is
145.269 - * deserialized, if those fields are present then its {@code readResolve}
145.270 - * method will substitute a {@code GenericMBeanException} equivalent to
145.271 - * this one.</p>
145.272 - */
145.273 - Object writeReplace() {
145.274 - MBeanException x = new MBeanException(
145.275 - getMessage(), errorCode, userData, getCause());
145.276 - x.setStackTrace(this.getStackTrace());
145.277 - return x;
145.278 - }
145.279 -}
146.1 --- a/src/share/classes/javax/management/Impact.java Mon Nov 23 10:04:47 2009 +0000
146.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
146.3 @@ -1,105 +0,0 @@
146.4 -/*
146.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
146.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
146.7 - *
146.8 - * This code is free software; you can redistribute it and/or modify it
146.9 - * under the terms of the GNU General Public License version 2 only, as
146.10 - * published by the Free Software Foundation. Sun designates this
146.11 - * particular file as subject to the "Classpath" exception as provided
146.12 - * by Sun in the LICENSE file that accompanied this code.
146.13 - *
146.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
146.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
146.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
146.17 - * version 2 for more details (a copy is included in the LICENSE file that
146.18 - * accompanied this code).
146.19 - *
146.20 - * You should have received a copy of the GNU General Public License version
146.21 - * 2 along with this work; if not, write to the Free Software Foundation,
146.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
146.23 - *
146.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
146.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
146.26 - * have any questions.
146.27 - */
146.28 -
146.29 -package javax.management;
146.30 -
146.31 -/**
146.32 - * <p>Defines the impact of an MBean operation, in particular whether it
146.33 - * has an effect on the MBean or simply returns information. This enum
146.34 - * is used in the {@link ManagedOperation @ManagedOperation} annotation.
146.35 - * Its {@link #getCode()} method can be used to get an {@code int} suitable
146.36 - * for use as the {@code impact} parameter in an {@link MBeanOperationInfo}
146.37 - * constructor.</p>
146.38 - */
146.39 -public enum Impact {
146.40 - /**
146.41 - * The operation is read-like: it returns information but does not change
146.42 - * any state.
146.43 - * @see MBeanOperationInfo#INFO
146.44 - */
146.45 - INFO(MBeanOperationInfo.INFO),
146.46 -
146.47 - /**
146.48 - * The operation is write-like: it has an effect but does not return
146.49 - * any information from the MBean.
146.50 - * @see MBeanOperationInfo#ACTION
146.51 - */
146.52 - ACTION(MBeanOperationInfo.ACTION),
146.53 -
146.54 - /**
146.55 - * The operation is both read-like and write-like: it has an effect,
146.56 - * and it also returns information from the MBean.
146.57 - * @see MBeanOperationInfo#ACTION_INFO
146.58 - */
146.59 - ACTION_INFO(MBeanOperationInfo.ACTION_INFO),
146.60 -
146.61 - /**
146.62 - * The impact of the operation is unknown or cannot be expressed
146.63 - * using one of the other values.
146.64 - * @see MBeanOperationInfo#UNKNOWN
146.65 - */
146.66 - UNKNOWN(MBeanOperationInfo.UNKNOWN);
146.67 -
146.68 - private final int code;
146.69 -
146.70 - /**
146.71 - * An instance of this enumeration, with the corresponding {@code int}
146.72 - * code used by the {@link MBeanOperationInfo} constructors.
146.73 - *
146.74 - * @param code the code used by the {@code MBeanOperationInfo} constructors.
146.75 - */
146.76 - Impact(int code) {
146.77 - this.code = code;
146.78 - }
146.79 -
146.80 - /**
146.81 - * The equivalent {@code int} code used by the {@link MBeanOperationInfo}
146.82 - * constructors.
146.83 - * @return the {@code int} code.
146.84 - */
146.85 - public int getCode() {
146.86 - return code;
146.87 - }
146.88 -
146.89 - /**
146.90 - * Return the {@code Impact} value corresponding to the given {@code int}
146.91 - * code. The {@code code} is the value that would be used in an
146.92 - * {@code MBeanOperationInfo} constructor.
146.93 - *
146.94 - * @param code the {@code int} code.
146.95 - *
146.96 - * @return an {@code Impact} value {@code x} such that
146.97 - * {@code code == x.}{@link #getCode()}, or {@code Impact.UNKNOWN}
146.98 - * if there is no such value.
146.99 - */
146.100 - public static Impact forCode(int code) {
146.101 - switch (code) {
146.102 - case MBeanOperationInfo.ACTION: return ACTION;
146.103 - case MBeanOperationInfo.INFO: return INFO;
146.104 - case MBeanOperationInfo.ACTION_INFO: return ACTION_INFO;
146.105 - default: return UNKNOWN;
146.106 - }
146.107 - }
146.108 -}
147.1 --- a/src/share/classes/javax/management/InstanceNotFoundException.java Mon Nov 23 10:04:47 2009 +0000
147.2 +++ b/src/share/classes/javax/management/InstanceNotFoundException.java Wed Nov 25 11:08:25 2009 -0800
147.3 @@ -1,5 +1,5 @@
147.4 /*
147.5 - * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
147.6 + * Copyright 1999-2003 Sun Microsystems, Inc. All Rights Reserved.
147.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
147.8 *
147.9 * This code is free software; you can redistribute it and/or modify it
147.10 @@ -51,16 +51,4 @@
147.11 public InstanceNotFoundException(String message) {
147.12 super(message);
147.13 }
147.14 -
147.15 - /**
147.16 - * Constructor for the frequent case where the message is the ObjectName
147.17 - * of the missing MBean.
147.18 - *
147.19 - * @param name the ObjectName of the missing MBean.
147.20 - *
147.21 - * @since 1.7
147.22 - */
147.23 - public InstanceNotFoundException(ObjectName name) {
147.24 - this(String.valueOf(name));
147.25 - }
147.26 }
148.1 --- a/src/share/classes/javax/management/JMRuntimeException.java Mon Nov 23 10:04:47 2009 +0000
148.2 +++ b/src/share/classes/javax/management/JMRuntimeException.java Wed Nov 25 11:08:25 2009 -0800
148.3 @@ -58,22 +58,6 @@
148.4 * specification. A later version may make it public.
148.5 */
148.6 JMRuntimeException(String message, Throwable cause) {
148.7 - super(message);
148.8 -
148.9 - /* Make a best effort to set the cause, but if we don't
148.10 - succeed, too bad, you don't get that useful debugging
148.11 - information. We jump through hoops here so that we can
148.12 - work on platforms prior to J2SE 1.4 where the
148.13 - Throwable.initCause method was introduced. If we change
148.14 - the public interface of JMRuntimeException in a future
148.15 - version we can add getCause() so we don't need to do this. */
148.16 - try {
148.17 - java.lang.reflect.Method initCause =
148.18 - Throwable.class.getMethod("initCause",
148.19 - new Class<?>[] {Throwable.class});
148.20 - initCause.invoke(this, new Object[] {cause});
148.21 - } catch (Exception e) {
148.22 - // OK: just means we won't have debugging info
148.23 - }
148.24 + super(message, cause);
148.25 }
148.26 }
149.1 --- a/src/share/classes/javax/management/JMX.java Mon Nov 23 10:04:47 2009 +0000
149.2 +++ b/src/share/classes/javax/management/JMX.java Wed Nov 25 11:08:25 2009 -0800
149.3 @@ -1,5 +1,5 @@
149.4 /*
149.5 - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
149.6 + * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
149.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
149.8 *
149.9 * This code is free software; you can redistribute it and/or modify it
149.10 @@ -26,20 +26,8 @@
149.11 package javax.management;
149.12
149.13 import com.sun.jmx.mbeanserver.Introspector;
149.14 -import com.sun.jmx.mbeanserver.MBeanInjector;
149.15 -import com.sun.jmx.remote.util.ClassLogger;
149.16 -import java.beans.BeanInfo;
149.17 -import java.beans.PropertyDescriptor;
149.18 -import java.io.IOException;
149.19 -import java.io.Serializable;
149.20 import java.lang.reflect.InvocationHandler;
149.21 -import java.lang.reflect.InvocationTargetException;
149.22 -import java.lang.reflect.Method;
149.23 import java.lang.reflect.Proxy;
149.24 -import java.util.Map;
149.25 -import java.util.TreeMap;
149.26 -import javax.management.namespace.JMXNamespaces;
149.27 -import javax.management.openmbean.MXBeanMappingFactory;
149.28
149.29 /**
149.30 * Static methods from the JMX API. There are no instances of this class.
149.31 @@ -60,27 +48,6 @@
149.32 */
149.33 public static final String DEFAULT_VALUE_FIELD = "defaultValue";
149.34
149.35 - /**
149.36 - * The name of the <a
149.37 - * href="Descriptor.html#descriptionResourceBundleBaseName">{@code
149.38 - * descriptionResourceBundleBaseName}</a> field.
149.39 - */
149.40 - public static final String DESCRIPTION_RESOURCE_BUNDLE_BASE_NAME_FIELD =
149.41 - "descriptionResourceBundleBaseName";
149.42 -
149.43 - /**
149.44 - * The name of the <a href="Descriptor.html#descriptionResourceKey">{@code
149.45 - * descriptionResourceKey}</a> field.
149.46 - */
149.47 - public static final String DESCRIPTION_RESOURCE_KEY_FIELD =
149.48 - "descriptionResourceKey";
149.49 -
149.50 - /**
149.51 - * The name of the <a href="Descriptor.html#exceptions">{@code
149.52 - * exceptions}</a> field.
149.53 - */
149.54 - public static final String EXCEPTIONS_FIELD = "exceptions";
149.55 -
149.56 /**
149.57 * The name of the <a href="Descriptor.html#immutableInfo">{@code
149.58 * immutableInfo}</a> field.
149.59 @@ -100,12 +67,6 @@
149.60 public static final String LEGAL_VALUES_FIELD = "legalValues";
149.61
149.62 /**
149.63 - * The name of the <a href="Descriptor.html#locale">{@code locale}</a>
149.64 - * field.
149.65 - */
149.66 - public static final String LOCALE_FIELD = "locale";
149.67 -
149.68 - /**
149.69 * The name of the <a href="Descriptor.html#maxValue">{@code
149.70 * maxValue}</a> field.
149.71 */
149.72 @@ -124,14 +85,6 @@
149.73 public static final String MXBEAN_FIELD = "mxbean";
149.74
149.75 /**
149.76 - * The name of the
149.77 - * <a href="Descriptor.html#mxbeanMappingFactoryClass">{@code
149.78 - * mxbeanMappingFactoryClass}</a> field.
149.79 - */
149.80 - public static final String MXBEAN_MAPPING_FACTORY_CLASS_FIELD =
149.81 - "mxbeanMappingFactoryClass";
149.82 -
149.83 - /**
149.84 * The name of the <a href="Descriptor.html#openType">{@code
149.85 * openType}</a> field.
149.86 */
149.87 @@ -144,276 +97,6 @@
149.88 public static final String ORIGINAL_TYPE_FIELD = "originalType";
149.89
149.90 /**
149.91 - * The name of the <a href="Descriptor.html#setExceptions">{@code
149.92 - * setExceptions}</a> field.
149.93 - */
149.94 - public static final String SET_EXCEPTIONS_FIELD = "setExceptions";
149.95 -
149.96 - /**
149.97 - * The name of the <a href="Descriptor.html#objectNameTemplate">{@code
149.98 - * objectNameTemplate}</a> field.
149.99 - */
149.100 - public static final String OBJECT_NAME_TEMPLATE = "objectNameTemplate";
149.101 -
149.102 - /**
149.103 - * <p>Options to apply to an MBean proxy or to an instance of {@link
149.104 - * StandardMBean}.</p>
149.105 - *
149.106 - * <p>For example, to specify the "wrapped object visible" option for a
149.107 - * {@code StandardMBean}, you might write this:</p>
149.108 - *
149.109 - * <pre>
149.110 - * StandardMBean.Options opts = new StandardMBean.Options();
149.111 - * opts.setWrappedObjectVisible(true);
149.112 - * StandardMBean mbean = new StandardMBean(impl, intf, opts);
149.113 - * </pre>
149.114 - *
149.115 - * @see javax.management.JMX.ProxyOptions
149.116 - * @see javax.management.StandardMBean.Options
149.117 - */
149.118 - public static class MBeanOptions implements Serializable, Cloneable {
149.119 - private static final long serialVersionUID = -6380842449318177843L;
149.120 -
149.121 - static final MBeanOptions MXBEAN = new MBeanOptions();
149.122 - static {
149.123 - MXBEAN.setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT);
149.124 - }
149.125 -
149.126 - private MXBeanMappingFactory mappingFactory;
149.127 -
149.128 - /**
149.129 - * <p>Construct an {@code MBeanOptions} object where all options have
149.130 - * their default values.</p>
149.131 - */
149.132 - public MBeanOptions() {}
149.133 -
149.134 - @Override
149.135 - public MBeanOptions clone() {
149.136 - try {
149.137 - return (MBeanOptions) super.clone();
149.138 - } catch (CloneNotSupportedException e) {
149.139 - throw new AssertionError(e);
149.140 - }
149.141 - }
149.142 -
149.143 - /**
149.144 - * <p>True if this is an MXBean proxy or a StandardMBean instance
149.145 - * that is an MXBean. The default value is false.</p>
149.146 - *
149.147 - * <p>This method is equivalent to {@link #getMXBeanMappingFactory()
149.148 - * this.getMXBeanMappingFactory()}{@code != null}.</p>
149.149 - *
149.150 - * @return true if this is an MXBean proxy or a StandardMBean instance
149.151 - * that is an MXBean.
149.152 - */
149.153 - public boolean isMXBean() {
149.154 - return (this.mappingFactory != null);
149.155 - }
149.156 -
149.157 - /**
149.158 - * <p>The mappings between Java types and Open Types to be used in
149.159 - * an MXBean proxy or a StandardMBean instance that is an MXBean,
149.160 - * or null if this instance is not for an MXBean.
149.161 - * The default value is null.</p>
149.162 - *
149.163 - * @return the mappings to be used in this proxy or StandardMBean,
149.164 - * or null if this instance is not for an MXBean.
149.165 - */
149.166 - public MXBeanMappingFactory getMXBeanMappingFactory() {
149.167 - return mappingFactory;
149.168 - }
149.169 -
149.170 - /**
149.171 - * <p>Set the {@link #getMXBeanMappingFactory() MXBeanMappingFactory} to
149.172 - * the given value. The value should be null if this instance is not
149.173 - * for an MXBean. If this instance is for an MXBean, the value should
149.174 - * usually be either a custom mapping factory, or
149.175 - * {@link MXBeanMappingFactory#forInterface
149.176 - * MXBeanMappingFactory.forInterface}{@code (mxbeanInterface)}
149.177 - * which signifies
149.178 - * that the {@linkplain MXBeanMappingFactory#DEFAULT default} mapping
149.179 - * factory should be used unless an {@code @}{@link
149.180 - * javax.management.openmbean.MXBeanMappingFactoryClass
149.181 - * MXBeanMappingFactoryClass} annotation on {@code mxbeanInterface}
149.182 - * specifies otherwise.</p>
149.183 - *
149.184 - * <p>Examples:</p>
149.185 - * <pre>
149.186 - * MBeanOptions opts = new MBeanOptions();
149.187 - * opts.setMXBeanMappingFactory(myMappingFactory);
149.188 - * MyMXBean proxy = JMX.newMBeanProxy(
149.189 - * mbeanServerConnection, objectName, MyMXBean.class, opts);
149.190 - *
149.191 - * // ...or...
149.192 - *
149.193 - * MBeanOptions opts = new MBeanOptions();
149.194 - * MXBeanMappingFactory defaultFactoryForMyMXBean =
149.195 - * MXBeanMappingFactory.forInterface(MyMXBean.class);
149.196 - * opts.setMXBeanMappingFactory(defaultFactoryForMyMXBean);
149.197 - * MyMXBean proxy = JMX.newMBeanProxy(
149.198 - * mbeanServerConnection, objectName, MyMXBean.class, opts);
149.199 - * </pre>
149.200 - *
149.201 - * @param f the new value. If null, this instance is not for an
149.202 - * MXBean.
149.203 - */
149.204 - public void setMXBeanMappingFactory(MXBeanMappingFactory f) {
149.205 - this.mappingFactory = f;
149.206 - }
149.207 -
149.208 - /* To maximise object sharing, classes in this package can replace
149.209 - * a private MBeanOptions with no MXBeanMappingFactory with one
149.210 - * of these shared instances. But they must be EXTREMELY careful
149.211 - * never to give out the shared instances to user code, which could
149.212 - * modify them.
149.213 - */
149.214 - private static final MBeanOptions[] CANONICALS = {
149.215 - new MBeanOptions(), MXBEAN,
149.216 - };
149.217 - // Overridden in local subclasses:
149.218 - MBeanOptions[] canonicals() {
149.219 - return CANONICALS;
149.220 - }
149.221 -
149.222 - // This is only used by the logic for canonical instances.
149.223 - // Overridden in local subclasses:
149.224 - boolean same(MBeanOptions opt) {
149.225 - return (opt.mappingFactory == mappingFactory);
149.226 - }
149.227 -
149.228 - final MBeanOptions canonical() {
149.229 - for (MBeanOptions opt : canonicals()) {
149.230 - if (opt.getClass() == this.getClass() && same(opt))
149.231 - return opt;
149.232 - }
149.233 - return this;
149.234 - }
149.235 -
149.236 - final MBeanOptions uncanonical() {
149.237 - for (MBeanOptions opt : canonicals()) {
149.238 - if (this == opt)
149.239 - return clone();
149.240 - }
149.241 - return this;
149.242 - }
149.243 -
149.244 - private Map<String, Object> toMap() {
149.245 - Map<String, Object> map = new TreeMap<String, Object>();
149.246 - try {
149.247 - BeanInfo bi = java.beans.Introspector.getBeanInfo(getClass());
149.248 - PropertyDescriptor[] pds = bi.getPropertyDescriptors();
149.249 - for (PropertyDescriptor pd : pds) {
149.250 - String name = pd.getName();
149.251 - if (name.equals("class"))
149.252 - continue;
149.253 - Method get = pd.getReadMethod();
149.254 - if (get != null)
149.255 - map.put(name, get.invoke(this));
149.256 - }
149.257 - } catch (Exception e) {
149.258 - Throwable t = e;
149.259 - if (t instanceof InvocationTargetException)
149.260 - t = t.getCause();
149.261 - map.put("Exception", t);
149.262 - }
149.263 - return map;
149.264 - }
149.265 -
149.266 - @Override
149.267 - public String toString() {
149.268 - return getClass().getSimpleName() + toMap();
149.269 - // For example "MBeanOptions{MXBean=true, <etc>}".
149.270 - }
149.271 -
149.272 - /**
149.273 - * <p>Indicates whether some other object is "equal to" this one. The
149.274 - * result is true if and only if the other object is also an instance
149.275 - * of MBeanOptions or a subclass, and has the same properties with
149.276 - * the same values.</p>
149.277 - * @return {@inheritDoc}
149.278 - */
149.279 - @Override
149.280 - public boolean equals(Object obj) {
149.281 - if (obj == this)
149.282 - return true;
149.283 - if (obj == null || obj.getClass() != this.getClass())
149.284 - return false;
149.285 - return toMap().equals(((MBeanOptions) obj).toMap());
149.286 - }
149.287 -
149.288 - @Override
149.289 - public int hashCode() {
149.290 - return toMap().hashCode();
149.291 - }
149.292 - }
149.293 -
149.294 - /**
149.295 - * <p>Options to apply to an MBean proxy.</p>
149.296 - *
149.297 - * @see #newMBeanProxy
149.298 - */
149.299 - public static class ProxyOptions extends MBeanOptions {
149.300 - private static final long serialVersionUID = 7238804866098386559L;
149.301 -
149.302 - private boolean notificationEmitter;
149.303 -
149.304 - /**
149.305 - * <p>Construct a {@code ProxyOptions} object where all options have
149.306 - * their default values.</p>
149.307 - */
149.308 - public ProxyOptions() {}
149.309 -
149.310 - @Override
149.311 - public ProxyOptions clone() {
149.312 - return (ProxyOptions) super.clone();
149.313 - }
149.314 -
149.315 - /**
149.316 - * <p>Defines whether the returned proxy should
149.317 - * implement {@link NotificationEmitter}. The default value is false.</p>
149.318 - *
149.319 - * @return true if this proxy will be a NotificationEmitter.
149.320 - *
149.321 - * @see JMX#newMBeanProxy(MBeanServerConnection, ObjectName, Class,
149.322 - * MBeanOptions)
149.323 - */
149.324 - public boolean isNotificationEmitter() {
149.325 - return this.notificationEmitter;
149.326 - }
149.327 -
149.328 - /**
149.329 - * <p>Set the {@link #isNotificationEmitter NotificationEmitter} option to
149.330 - * the given value.</p>
149.331 - * @param emitter the new value.
149.332 - */
149.333 - public void setNotificationEmitter(boolean emitter) {
149.334 - this.notificationEmitter = emitter;
149.335 - }
149.336 -
149.337 - // Canonical objects for each of (MXBean,!MXBean) x (Emitter,!Emitter)
149.338 - private static final ProxyOptions[] CANONICALS = {
149.339 - new ProxyOptions(), new ProxyOptions(),
149.340 - new ProxyOptions(), new ProxyOptions(),
149.341 - };
149.342 - static {
149.343 - CANONICALS[1].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT);
149.344 - CANONICALS[2].setNotificationEmitter(true);
149.345 - CANONICALS[3].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT);
149.346 - CANONICALS[3].setNotificationEmitter(true);
149.347 - }
149.348 - @Override
149.349 - MBeanOptions[] canonicals() {
149.350 - return CANONICALS;
149.351 - }
149.352 -
149.353 - @Override
149.354 - boolean same(MBeanOptions opt) {
149.355 - return (super.same(opt) && opt instanceof ProxyOptions &&
149.356 - ((ProxyOptions) opt).notificationEmitter == notificationEmitter);
149.357 - }
149.358 - }
149.359 -
149.360 - /**
149.361 * <p>Make a proxy for a Standard MBean in a local or remote
149.362 * MBean Server.</p>
149.363 *
149.364 @@ -501,12 +184,6 @@
149.365 * likewise for the other methods of {@link
149.366 * NotificationBroadcaster} and {@link NotificationEmitter}.</p>
149.367 *
149.368 - * <p>This method is equivalent to {@link
149.369 - * #newMBeanProxy(MBeanServerConnection, ObjectName, Class, JMX.MBeanOptions)
149.370 - * newMBeanProxy(connection, objectName, interfaceClass, opts)}, where
149.371 - * {@code opts} is a {@link JMX.ProxyOptions} representing the
149.372 - * {@code notificationEmitter} parameter.</p>
149.373 - *
149.374 * @param connection the MBean server to forward to.
149.375 * @param objectName the name of the MBean within
149.376 * {@code connection} to forward to.
149.377 @@ -515,18 +192,22 @@
149.378 * @param notificationEmitter make the returned proxy
149.379 * implement {@link NotificationEmitter} by forwarding its methods
149.380 * via {@code connection}.
149.381 + *
149.382 * @param <T> allows the compiler to know that if the {@code
149.383 * interfaceClass} parameter is {@code MyMBean.class}, for
149.384 * example, then the return type is {@code MyMBean}.
149.385 + *
149.386 * @return the new proxy instance.
149.387 */
149.388 public static <T> T newMBeanProxy(MBeanServerConnection connection,
149.389 ObjectName objectName,
149.390 Class<T> interfaceClass,
149.391 boolean notificationEmitter) {
149.392 - ProxyOptions opts = new ProxyOptions();
149.393 - opts.setNotificationEmitter(notificationEmitter);
149.394 - return newMBeanProxy(connection, objectName, interfaceClass, opts);
149.395 + return MBeanServerInvocationHandler.newProxyInstance(
149.396 + connection,
149.397 + objectName,
149.398 + interfaceClass,
149.399 + notificationEmitter);
149.400 }
149.401
149.402 /**
149.403 @@ -599,6 +280,10 @@
149.404 *
149.405 * </ul>
149.406 *
149.407 + * <p>The object returned by this method is a
149.408 + * {@link Proxy} whose {@code InvocationHandler} is an
149.409 + * {@link MBeanServerInvocationHandler}.</p>
149.410 + *
149.411 * <p>This method is equivalent to {@link
149.412 * #newMXBeanProxy(MBeanServerConnection, ObjectName, Class,
149.413 * boolean) newMXBeanProxy(connection, objectName, interfaceClass,
149.414 @@ -641,17 +326,6 @@
149.415 * likewise for the other methods of {@link
149.416 * NotificationBroadcaster} and {@link NotificationEmitter}.</p>
149.417 *
149.418 - * <p>This method is equivalent to {@link
149.419 - * #newMBeanProxy(MBeanServerConnection, ObjectName, Class, JMX.MBeanOptions)
149.420 - * newMBeanProxy(connection, objectName, interfaceClass, opts)}, where
149.421 - * {@code opts} is a {@link JMX.ProxyOptions} where the {@link
149.422 - * JMX.ProxyOptions#getMXBeanMappingFactory() MXBeanMappingFactory}
149.423 - * property is
149.424 - * {@link MXBeanMappingFactory#forInterface(Class)
149.425 - * MXBeanMappingFactory.forInterface(interfaceClass)} and the {@link
149.426 - * JMX.ProxyOptions#isNotificationEmitter() notificationEmitter} property
149.427 - * is equal to the {@code notificationEmitter} parameter.</p>
149.428 - *
149.429 * @param connection the MBean server to forward to.
149.430 * @param objectName the name of the MBean within
149.431 * {@code connection} to forward to.
149.432 @@ -660,130 +334,26 @@
149.433 * @param notificationEmitter make the returned proxy
149.434 * implement {@link NotificationEmitter} by forwarding its methods
149.435 * via {@code connection}.
149.436 + *
149.437 * @param <T> allows the compiler to know that if the {@code
149.438 * interfaceClass} parameter is {@code MyMXBean.class}, for
149.439 * example, then the return type is {@code MyMXBean}.
149.440 + *
149.441 * @return the new proxy instance.
149.442 */
149.443 public static <T> T newMXBeanProxy(MBeanServerConnection connection,
149.444 ObjectName objectName,
149.445 Class<T> interfaceClass,
149.446 boolean notificationEmitter) {
149.447 - ProxyOptions opts = new ProxyOptions();
149.448 - MXBeanMappingFactory f = MXBeanMappingFactory.forInterface(interfaceClass);
149.449 - opts.setMXBeanMappingFactory(f);
149.450 - opts.setNotificationEmitter(notificationEmitter);
149.451 - return newMBeanProxy(connection, objectName, interfaceClass, opts);
149.452 - }
149.453 -
149.454 - /**
149.455 - * <p>Make a proxy for a Standard MBean or MXBean in a local or remote MBean
149.456 - * Server that may also support the methods of {@link
149.457 - * NotificationEmitter} and (for an MXBean) that may define custom MXBean
149.458 - * type mappings.</p>
149.459 - *
149.460 - * <p>This method behaves the same as
149.461 - * {@link #newMBeanProxy(MBeanServerConnection, ObjectName, Class)} or
149.462 - * {@link #newMXBeanProxy(MBeanServerConnection, ObjectName, Class)},
149.463 - * according as {@code opts.isMXBean()} is respectively false or true; but
149.464 - * with the following changes based on {@code opts}.</p>
149.465 - *
149.466 - * <ul>
149.467 - * <li>If {@code opts.isNotificationEmitter()} is {@code
149.468 - * true}, then the MBean is assumed to be a {@link
149.469 - * NotificationBroadcaster} or {@link NotificationEmitter} and the
149.470 - * returned proxy will implement {@link NotificationEmitter} as
149.471 - * well as {@code interfaceClass}. A call to {@link
149.472 - * NotificationBroadcaster#addNotificationListener} on the proxy
149.473 - * will result in a call to {@link
149.474 - * MBeanServerConnection#addNotificationListener(ObjectName,
149.475 - * NotificationListener, NotificationFilter, Object)}, and
149.476 - * likewise for the other methods of {@link
149.477 - * NotificationBroadcaster} and {@link NotificationEmitter}.</li>
149.478 - *
149.479 - * <li>If {@code opts.getMXBeanMappingFactory()} is not null,
149.480 - * then the mappings it defines will be applied to convert between
149.481 - * arbitrary Java types and Open Types.</li>
149.482 - * </ul>
149.483 - *
149.484 - * <p>The object returned by this method is a
149.485 - * {@link Proxy} whose {@code InvocationHandler} is an
149.486 - * {@link MBeanServerInvocationHandler}. This means that it is possible
149.487 - * to retrieve the parameters that were used to produce the proxy. If the
149.488 - * proxy was produced as follows...</p>
149.489 - *
149.490 - * <pre>
149.491 - * FooMBean proxy =
149.492 - * JMX.newMBeanProxy(connection, objectName, FooMBean.class, opts);
149.493 - * </pre>
149.494 - *
149.495 - * <p>...then you can get the {@code MBeanServerInvocationHandler} like
149.496 - * this...</p>
149.497 - *
149.498 - * <pre>
149.499 - * MBeanServerInvocationHandler mbsih = (MBeanServerInvocationHandler)
149.500 - * {@link Proxy#getInvocationHandler(Object)
149.501 - * Proxy.getInvocationHandler}(proxy);
149.502 - * </pre>
149.503 - *
149.504 - * <p>...and you can retrieve {@code connection}, {@code
149.505 - * objectName}, and {@code opts} using the {@link
149.506 - * MBeanServerInvocationHandler#getMBeanServerConnection()
149.507 - * getMBeanServerConnection()}, {@link
149.508 - * MBeanServerInvocationHandler#getObjectName() getObjectName()}, and
149.509 - * {@link MBeanServerInvocationHandler#getMBeanOptions() getMBeanOptions()}
149.510 - * methods on {@code mbsih}. You can retrieve {@code FooMBean.class}
149.511 - * using {@code proxy.getClass().}{@link
149.512 - * Class#getInterfaces() getInterfaces()}.</p>
149.513 - *
149.514 - * @param connection the MBean server to forward to.
149.515 - * @param objectName the name of the MBean within
149.516 - * {@code connection} to forward to.
149.517 - * @param interfaceClass the Standard MBean or MXBean interface,
149.518 - * which will also be implemented by the returned proxy.
149.519 - * @param opts the options to apply for this proxy. Can be null,
149.520 - * in which case default options are applied.
149.521 - * @param <T> allows the compiler to know that if the {@code
149.522 - * interfaceClass} parameter is {@code MyMXBean.class}, for
149.523 - * example, then the return type is {@code MyMXBean}.
149.524 - * @return the new proxy instance.
149.525 - *
149.526 - * @throws IllegalArgumentException if {@code interfaceClass} is not a
149.527 - * valid MXBean interface.
149.528 - */
149.529 - public static <T> T newMBeanProxy(MBeanServerConnection connection,
149.530 - ObjectName objectName,
149.531 - Class<T> interfaceClass,
149.532 - MBeanOptions opts) {
149.533 + // Check interface for MXBean compliance
149.534 + //
149.535 try {
149.536 - return newMBeanProxy2(connection, objectName, interfaceClass, opts);
149.537 + Introspector.testComplianceMXBeanInterface(interfaceClass);
149.538 } catch (NotCompliantMBeanException e) {
149.539 throw new IllegalArgumentException(e);
149.540 }
149.541 - }
149.542 -
149.543 - private static <T> T newMBeanProxy2(MBeanServerConnection connection,
149.544 - ObjectName objectName,
149.545 - Class<T> interfaceClass,
149.546 - MBeanOptions opts)
149.547 - throws NotCompliantMBeanException {
149.548 -
149.549 - if (opts == null)
149.550 - opts = new MBeanOptions();
149.551 -
149.552 - boolean notificationEmitter = opts instanceof ProxyOptions &&
149.553 - ((ProxyOptions) opts).isNotificationEmitter();
149.554 -
149.555 - MXBeanMappingFactory mappingFactory = opts.getMXBeanMappingFactory();
149.556 -
149.557 - if (mappingFactory != null) {
149.558 - // Check interface for MXBean compliance
149.559 - Introspector.testComplianceMXBeanInterface(interfaceClass,
149.560 - mappingFactory);
149.561 - }
149.562 -
149.563 InvocationHandler handler = new MBeanServerInvocationHandler(
149.564 - connection, objectName, opts);
149.565 + connection, objectName, true);
149.566 final Class<?>[] interfaces;
149.567 if (notificationEmitter) {
149.568 interfaces =
149.569 @@ -822,109 +392,4 @@
149.570 // exactly the string "MXBean" since that would mean there
149.571 // was no package name, which is pretty unlikely in practice.
149.572 }
149.573 -
149.574 - /**
149.575 - * <p>Test if an MBean can emit notifications. An MBean can emit
149.576 - * notifications if either it implements {@link NotificationBroadcaster}
149.577 - * (perhaps through its child interface {@link NotificationEmitter}), or
149.578 - * it uses <a href="MBeanRegistration.html#injection">resource
149.579 - * injection</a> to obtain an instance of {@link SendNotification}
149.580 - * through which it can send notifications.</p>
149.581 - *
149.582 - * @param mbean an MBean object.
149.583 - * @return true if the given object is a valid MBean that can emit
149.584 - * notifications; false if the object is a valid MBean but that
149.585 - * cannot emit notifications.
149.586 - * @throws NotCompliantMBeanException if the given object is not
149.587 - * a valid MBean.
149.588 - */
149.589 - public static boolean isNotificationSource(Object mbean)
149.590 - throws NotCompliantMBeanException {
149.591 - for (int i = 0; i < 2; i++) {
149.592 - if (mbean instanceof NotificationBroadcaster ||
149.593 - MBeanInjector.injectsSendNotification(mbean))
149.594 - return true;
149.595 - if (mbean instanceof DynamicWrapperMBean)
149.596 - mbean = ((DynamicWrapperMBean) mbean).getWrappedObject();
149.597 - else
149.598 - break;
149.599 - }
149.600 - return false;
149.601 - }
149.602 -
149.603 - /**
149.604 - * <p>Return the version of the JMX specification that a (possibly remote)
149.605 - * MBean Server is using. The JMX specification described in this
149.606 - * documentation is version 2.0. The earlier versions that might be
149.607 - * reported by this method are 1.0, 1.1, 1.2, and 1.4. (There is no 1.3.)
149.608 - * All of these versions and all future versions can be compared using
149.609 - * {@link String#compareTo(String)}. So, for example, to tell if
149.610 - * {@code mbsc} is running at least version 2.0 you can write:</p>
149.611 - *
149.612 - * <pre>
149.613 - * String version = JMX.getSpecificationVersion(mbsc, null);
149.614 - * boolean atLeast2dot0 = (version.compareTo("2.0") >= 0);
149.615 - * </pre>
149.616 - *
149.617 - * <p>A remote MBean Server might be running an earlier version of the
149.618 - * JMX API, and in that case <a href="package-summary.html#interop">certain
149.619 - * features</a> might not be available in it.</p>
149.620 - *
149.621 - * <p>The version of the MBean Server {@code mbsc} is not necessarily
149.622 - * the version of all namespaces within that MBean Server, for example
149.623 - * if some of them use {@link javax.management.namespace.JMXRemoteNamespace
149.624 - * JMXRemoteNamespace}. To determine the version of the namespace
149.625 - * that a particular MBean is in, give its name as the {@code mbeanName}
149.626 - * parameter.</p>
149.627 - *
149.628 - * @param mbsc a connection to an MBean Server.
149.629 - *
149.630 - * @param mbeanName the name of an MBean within that MBean Server, or null.
149.631 - * If non-null, the namespace of this name, as determined by
149.632 - * {@link JMXNamespaces#getContainingNamespace
149.633 - * JMXNamespaces.getContainingNamespace}, is the one whose specification
149.634 - * version will be returned.
149.635 - *
149.636 - * @return the JMX specification version reported by that MBean Server.
149.637 - *
149.638 - * @throws IllegalArgumentException if {@code mbsc} is null, or if
149.639 - * {@code mbeanName} includes a wildcard character ({@code *} or {@code ?})
149.640 - * in its namespace.
149.641 - *
149.642 - * @throws IOException if the version cannot be obtained, either because
149.643 - * there is a communication problem or because the remote MBean Server
149.644 - * does not have the appropriate {@linkplain
149.645 - * MBeanServerDelegateMBean#getSpecificationVersion() attribute}.
149.646 - *
149.647 - * @see <a href="package-summary.html#interop">Interoperability between
149.648 - * versions of the JMX specification</a>
149.649 - * @see MBeanServerDelegateMBean#getSpecificationVersion
149.650 - */
149.651 - public static String getSpecificationVersion(
149.652 - MBeanServerConnection mbsc, ObjectName mbeanName)
149.653 - throws IOException {
149.654 - if (mbsc == null)
149.655 - throw new IllegalArgumentException("Null MBeanServerConnection");
149.656 -
149.657 - String namespace;
149.658 - if (mbeanName == null)
149.659 - namespace = "";
149.660 - else
149.661 - namespace = JMXNamespaces.getContainingNamespace(mbeanName);
149.662 - if (namespace.contains("*") || namespace.contains("?")) {
149.663 - throw new IllegalArgumentException(
149.664 - "ObjectName contains namespace wildcard: " + mbeanName);
149.665 - }
149.666 -
149.667 - try {
149.668 - if (namespace.length() > 0)
149.669 - mbsc = JMXNamespaces.narrowToNamespace(mbsc, namespace);
149.670 - return (String) mbsc.getAttribute(
149.671 - MBeanServerDelegate.DELEGATE_NAME, "SpecificationVersion");
149.672 - } catch (IOException e) {
149.673 - throw e;
149.674 - } catch (Exception e) {
149.675 - throw new IOException(e);
149.676 - }
149.677 - }
149.678 }
150.1 --- a/src/share/classes/javax/management/MBean.java Mon Nov 23 10:04:47 2009 +0000
150.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
150.3 @@ -1,68 +0,0 @@
150.4 -/*
150.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
150.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
150.7 - *
150.8 - * This code is free software; you can redistribute it and/or modify it
150.9 - * under the terms of the GNU General Public License version 2 only, as
150.10 - * published by the Free Software Foundation. Sun designates this
150.11 - * particular file as subject to the "Classpath" exception as provided
150.12 - * by Sun in the LICENSE file that accompanied this code.
150.13 - *
150.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
150.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
150.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
150.17 - * version 2 for more details (a copy is included in the LICENSE file that
150.18 - * accompanied this code).
150.19 - *
150.20 - * You should have received a copy of the GNU General Public License version
150.21 - * 2 along with this work; if not, write to the Free Software Foundation,
150.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
150.23 - *
150.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
150.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
150.26 - * have any questions.
150.27 - */
150.28 -
150.29 -package javax.management;
150.30 -
150.31 -import java.lang.annotation.ElementType;
150.32 -import java.lang.annotation.Inherited;
150.33 -import java.lang.annotation.Retention;
150.34 -import java.lang.annotation.RetentionPolicy;
150.35 -import java.lang.annotation.Target;
150.36 -
150.37 -/**
150.38 - * <p>Indicates that the annotated class is a Standard MBean. A Standard
150.39 - * MBean class can be defined as in this example:</p>
150.40 - *
150.41 - * <pre>
150.42 - * {@code @MBean}
150.43 - * public class Configuration {
150.44 - * {@link ManagedAttribute @ManagedAttribute}
150.45 - * public int getCacheSize() {...}
150.46 - * {@code @ManagedAttribute}
150.47 - * public void setCacheSize(int size);
150.48 - *
150.49 - * {@code @ManagedAttribute}
150.50 - * public long getLastChangedTime();
150.51 - *
150.52 - * {@link ManagedOperation @ManagedOperation}
150.53 - * public void save();
150.54 - * }
150.55 - * </pre>
150.56 - *
150.57 - * <p>The class must be public. Public methods within the class can be
150.58 - * annotated with {@code @ManagedOperation} to indicate that they are
150.59 - * MBean operations. Public getter and setter methods within the class
150.60 - * can be annotated with {@code @ManagedAttribute} to indicate that they define
150.61 - * MBean attributes.</p>
150.62 - *
150.63 - * <p>If the MBean is to be an MXBean rather than a Standard MBean, then
150.64 - * the {@link MXBean @MXBean} annotation must be used instead of
150.65 - * {@code @MBean}.</p>
150.66 - */
150.67 -@Retention(RetentionPolicy.RUNTIME)
150.68 -@Target(ElementType.TYPE)
150.69 -@Inherited
150.70 -public @interface MBean {
150.71 -}
151.1 --- a/src/share/classes/javax/management/MBeanAttributeInfo.java Mon Nov 23 10:04:47 2009 +0000
151.2 +++ b/src/share/classes/javax/management/MBeanAttributeInfo.java Wed Nov 25 11:08:25 2009 -0800
151.3 @@ -186,10 +186,8 @@
151.4 (getter != null),
151.5 (setter != null),
151.6 isIs(getter),
151.7 - ImmutableDescriptor.union(Introspector.
151.8 - descriptorForElement(getter, false),
151.9 - Introspector.descriptorForElement(setter,
151.10 - true)));
151.11 + ImmutableDescriptor.union(Introspector.descriptorForElement(getter),
151.12 + Introspector.descriptorForElement(setter)));
151.13 }
151.14
151.15 /**
152.1 --- a/src/share/classes/javax/management/MBeanConstructorInfo.java Mon Nov 23 10:04:47 2009 +0000
152.2 +++ b/src/share/classes/javax/management/MBeanConstructorInfo.java Wed Nov 25 11:08:25 2009 -0800
152.3 @@ -67,7 +67,7 @@
152.4 public MBeanConstructorInfo(String description, Constructor<?> constructor) {
152.5 this(constructor.getName(), description,
152.6 constructorSignature(constructor),
152.7 - Introspector.descriptorForElement(constructor, false));
152.8 + Introspector.descriptorForElement(constructor));
152.9 }
152.10
152.11 /**
153.1 --- a/src/share/classes/javax/management/MBeanException.java Mon Nov 23 10:04:47 2009 +0000
153.2 +++ b/src/share/classes/javax/management/MBeanException.java Wed Nov 25 11:08:25 2009 -0800
153.3 @@ -25,8 +25,6 @@
153.4
153.5 package javax.management;
153.6
153.7 -import javax.management.openmbean.CompositeData;
153.8 -
153.9
153.10 /**
153.11 * Represents "user defined" exceptions thrown by MBean methods
153.12 @@ -43,26 +41,6 @@
153.13 private static final long serialVersionUID = 4066342430588744142L;
153.14
153.15 /**
153.16 - * @serial This field is null for instances of this class that were
153.17 - * produced by its public constructors. It is non-null for instances
153.18 - * of this class that represent serialized instances of {@link
153.19 - * GenericMBeanException}.
153.20 - *
153.21 - * @see GenericMBeanException#getErrorCode()
153.22 - */
153.23 - final String errorCode;
153.24 -
153.25 - /**
153.26 - * @serial This field is null for instances of this class that were
153.27 - * produced by its public constructors. It may be non-null for instances
153.28 - * of this class that represent serialized instances of {@link
153.29 - * GenericMBeanException}.
153.30 - *
153.31 - * @see GenericMBeanException#getUserData()
153.32 - */
153.33 - final CompositeData userData;
153.34 -
153.35 - /**
153.36 * @serial Encapsulated {@link Exception}
153.37 */
153.38 private java.lang.Exception exception ;
153.39 @@ -73,8 +51,9 @@
153.40 *
153.41 * @param e the wrapped exception.
153.42 */
153.43 - public MBeanException(Exception e) {
153.44 - this(null, null, null, e);
153.45 + public MBeanException(java.lang.Exception e) {
153.46 + super() ;
153.47 + exception = e ;
153.48 }
153.49
153.50 /**
153.51 @@ -84,19 +63,11 @@
153.52 * @param e the wrapped exception.
153.53 * @param message the detail message.
153.54 */
153.55 - public MBeanException(Exception e, String message) {
153.56 - this(message, null, null, e);
153.57 + public MBeanException(java.lang.Exception e, String message) {
153.58 + super(message) ;
153.59 + exception = e ;
153.60 }
153.61
153.62 - MBeanException(
153.63 - String message, String errorCode, CompositeData userData, Throwable cause) {
153.64 - super(message);
153.65 - initCause(cause);
153.66 - if (cause instanceof Exception)
153.67 - this.exception = (Exception) cause;
153.68 - this.errorCode = errorCode;
153.69 - this.userData = userData;
153.70 - }
153.71
153.72 /**
153.73 * Return the actual {@link Exception} thrown.
153.74 @@ -108,24 +79,11 @@
153.75 }
153.76
153.77 /**
153.78 - * This method is invoked when deserializing instances of this class.
153.79 - * If the {@code errorCode} field of the deserialized instance is not
153.80 - * null, this method returns an instance of {@link GenericMBeanException}
153.81 - * instead. Otherwise it returns {@code this}.
153.82 - * @return {@code this}, or a {@code GenericMBeanException}.
153.83 + * Return the actual {@link Exception} thrown.
153.84 + *
153.85 + * @return the wrapped exception.
153.86 */
153.87 - Object readResolve() {
153.88 - if (errorCode == null) {
153.89 - // serial compatibility: earlier versions did not set
153.90 - // Throwable.cause because they overrode getCause().
153.91 - if (getCause() == null && exception != null)
153.92 - initCause(exception);
153.93 - return this;
153.94 - } else {
153.95 - Throwable t = new GenericMBeanException(
153.96 - getMessage(), errorCode, userData, getCause());
153.97 - t.setStackTrace(this.getStackTrace());
153.98 - return t;
153.99 - }
153.100 + public Throwable getCause() {
153.101 + return exception;
153.102 }
153.103 }
154.1 --- a/src/share/classes/javax/management/MBeanInfo.java Mon Nov 23 10:04:47 2009 +0000
154.2 +++ b/src/share/classes/javax/management/MBeanInfo.java Wed Nov 25 11:08:25 2009 -0800
154.3 @@ -25,7 +25,6 @@
154.4
154.5 package javax.management;
154.6
154.7 -import com.sun.jmx.mbeanserver.Util;
154.8 import java.io.IOException;
154.9 import java.io.StreamCorruptedException;
154.10 import java.io.Serializable;
154.11 @@ -38,12 +37,6 @@
154.12 import java.security.AccessController;
154.13 import java.security.PrivilegedAction;
154.14
154.15 -import java.util.HashMap;
154.16 -import java.util.Locale;
154.17 -import java.util.MissingResourceException;
154.18 -import java.util.ResourceBundle;
154.19 -import java.util.logging.Level;
154.20 -import java.util.logging.Logger;
154.21 import static javax.management.ImmutableDescriptor.nonNullDescriptor;
154.22
154.23 /**
154.24 @@ -80,50 +73,27 @@
154.25 * constructors in that object;
154.26 *
154.27 * <li>{@link #getAttributes()} returns the list of all attributes
154.28 - * whose existence is deduced as follows:
154.29 - * <ul>
154.30 - * <li>if the Standard MBean is defined with an MBean interface,
154.31 - * from <code>get<i>Name</i></code>, <code>is<i>Name</i></code>, or
154.32 - * <code>set<i>Name</i></code> methods that conform to the conventions
154.33 + * whose existence is deduced from the presence in the MBean interface
154.34 + * of a <code>get<i>Name</i></code>, <code>is<i>Name</i></code>, or
154.35 + * <code>set<i>Name</i></code> method that conforms to the conventions
154.36 * for Standard MBeans;
154.37 - * <li>if the Standard MBean is defined with the {@link MBean @MBean} or
154.38 - * {@link MXBean @MXBean} annotation on a class, from methods with the
154.39 - * {@link ManagedAttribute @ManagedAttribute} annotation;
154.40 - * </ul>
154.41 *
154.42 - * <li>{@link #getOperations()} returns the list of all operations whose
154.43 - * existence is deduced as follows:
154.44 - * <ul>
154.45 - * <li>if the Standard MBean is defined with an MBean interface, from methods in
154.46 + * <li>{@link #getOperations()} returns the list of all methods in
154.47 * the MBean interface that do not represent attributes;
154.48 - * <li>if the Standard MBean is defined with the {@link MBean @MBean} or
154.49 - * {@link MXBean @MXBean} annotation on a class, from methods with the
154.50 - * {@link ManagedOperation @ManagedOperation} annotation;
154.51 - * </ul>
154.52 *
154.53 - * <li>{@link #getNotifications()} returns:
154.54 - * <ul>
154.55 - * <li>if the MBean implements the {@link NotificationBroadcaster} interface,
154.56 - * the result of calling {@link
154.57 + * <li>{@link #getNotifications()} returns an empty array if the MBean
154.58 + * does not implement the {@link NotificationBroadcaster} interface,
154.59 + * otherwise the result of calling {@link
154.60 * NotificationBroadcaster#getNotificationInfo()} on it;
154.61 - * <li>otherwise, if there is a {@link NotificationInfo @NotificationInfo}
154.62 - * or {@link NotificationInfos @NotificationInfos} annotation on the
154.63 - * MBean interface or <code>@MBean</code> or <code>@MXBean</code>
154.64 - * class, the array implied by those annotations;
154.65 - * <li>otherwise an empty array;
154.66 - * </ul>
154.67 *
154.68 * <li>{@link #getDescriptor()} returns a descriptor containing the contents
154.69 * of any descriptor annotations in the MBean interface (see
154.70 - * {@link DescriptorFields @DescriptorFields} and
154.71 * {@link DescriptorKey @DescriptorKey}).
154.72 *
154.73 * </ul>
154.74 *
154.75 * <p>The description returned by {@link #getDescription()} and the
154.76 - * descriptions of the contained attributes and operations are determined
154.77 - * by the corresponding {@link Description} annotations if any;
154.78 - * otherwise their contents are not specified.</p>
154.79 + * descriptions of the contained attributes and operations are not specified.</p>
154.80 *
154.81 * <p>The remaining details of the <code>MBeanInfo</code> for a
154.82 * Standard MBean are not specified. This includes the description of
154.83 @@ -758,377 +728,4 @@
154.84 throw new StreamCorruptedException("Got unexpected byte.");
154.85 }
154.86 }
154.87 -
154.88 - /**
154.89 - * <p>Return an {@code MBeanInfo} object that is the same as this one
154.90 - * except that its descriptions are localized in the given locale.
154.91 - * This means the text returned by {@link MBeanInfo#getDescription}
154.92 - * (the description of the MBean itself), and the text returned by the
154.93 - * {@link MBeanFeatureInfo#getDescription getDescription()} method
154.94 - * for every {@linkplain MBeanAttributeInfo attribute}, {@linkplain
154.95 - * MBeanOperationInfo operation}, {@linkplain MBeanConstructorInfo
154.96 - * constructor}, and {@linkplain MBeanNotificationInfo notification}
154.97 - * contained in the {@code MBeanInfo}.</p>
154.98 - *
154.99 - * <p>Here is how the description {@code this.getDescription()} is
154.100 - * localized.</p>
154.101 - *
154.102 - * <p>First, if the {@linkplain #getDescriptor() descriptor}
154.103 - * of this {@code MBeanInfo} contains a field <code><a
154.104 - * href="Descriptor.html#locale">"locale"</a></code>, and the value of
154.105 - * the field is the same as {@code locale.toString()}, then this {@code
154.106 - * MBeanInfo} is returned. Otherwise, localization proceeds as follows,
154.107 - * and the {@code "locale"} field in the returned {@code MBeanInfo} will
154.108 - * be {@code locale.toString()}.
154.109 - *
154.110 - * <p>A <em>{@code className}</em> is determined. If this
154.111 - * {@code MBeanInfo} contains a descriptor with the field
154.112 - * <a href="Descriptor.html#interfaceClassName">{@code
154.113 - * "interfaceClassName"}</a>, then the value of that field is the
154.114 - * {@code className}. Otherwise, it is {@link #getClassName()}.
154.115 - * Everything before the last period (.) in the {@code className} is
154.116 - * the <em>{@code package}</em>, and everything after is the <em>{@code
154.117 - * simpleClassName}</em>. (If there is no period, then the {@code package}
154.118 - * is empty and the {@code simpleClassName} is the same as the {@code
154.119 - * className}.)</p>
154.120 - *
154.121 - * <p>A <em>{@code resourceKey}</em> is determined. If this {@code
154.122 - * MBeanInfo} contains a {@linkplain MBeanInfo#getDescriptor() descriptor}
154.123 - * with a field {@link JMX#DESCRIPTION_RESOURCE_KEY_FIELD
154.124 - * "descriptionResourceKey"}, the value of the field is
154.125 - * the {@code resourceKey}. Otherwise, the {@code resourceKey} is {@code
154.126 - * simpleClassName + ".mbean"}.</p>
154.127 - *
154.128 - * <p>A <em>{@code resourceBundleBaseName}</em> is determined. If
154.129 - * this {@code MBeanInfo} contains a descriptor with a field {@link
154.130 - * JMX#DESCRIPTION_RESOURCE_BUNDLE_BASE_NAME_FIELD
154.131 - * "descriptionResourceBundleBaseName"}, the value of the field
154.132 - * is the {@code resourceBundleBaseName}. Otherwise, the {@code
154.133 - * resourceBundleBaseName} is {@code package + ".MBeanDescriptions"}.
154.134 - *
154.135 - * <p>Then, a {@link java.util.ResourceBundle ResourceBundle} is
154.136 - * determined, using<br> {@link java.util.ResourceBundle#getBundle(String,
154.137 - * Locale, ClassLoader) ResourceBundle.getBundle(resourceBundleBaseName,
154.138 - * locale, loader)}. If this succeeds, and if {@link
154.139 - * java.util.ResourceBundle#getString(String) getString(resourceKey)}
154.140 - * returns a string, then that string is the localized description.
154.141 - * Otherwise, the original description is unchanged.</p>
154.142 - *
154.143 - * <p>A localized description for an {@code MBeanAttributeInfo} is
154.144 - * obtained similarly. The default {@code resourceBundleBaseName}
154.145 - * is the same as above. The default description and the
154.146 - * descriptor fields {@code "descriptionResourceKey"} and {@code
154.147 - * "descriptionResourceBundleBaseName"} come from the {@code
154.148 - * MBeanAttributeInfo} rather than the {@code MBeanInfo}. If the
154.149 - * attribute's {@linkplain MBeanFeatureInfo#getName() name} is {@code
154.150 - * Foo} then its default {@code resourceKey} is {@code simpleClassName +
154.151 - * ".attribute.Foo"}.</p>
154.152 - *
154.153 - * <p>Similar rules apply for operations, constructors, and notifications.
154.154 - * If the name of the operation, constructor, or notification is {@code
154.155 - * Foo} then the default {@code resourceKey} is respectively {@code
154.156 - * simpleClassName + ".operation.Foo"}, {@code simpleClassName +
154.157 - * ".constructor.Foo"}, or {@code simpleClassName + ".notification.Foo"}.
154.158 - * If two operations or constructors have the same name (overloading) then
154.159 - * they have the same default {@code resourceKey}; if different localized
154.160 - * descriptions are needed then a non-default key must be supplied using
154.161 - * {@code "descriptionResourceKey"}.</p>
154.162 - *
154.163 - * <p>Similar rules also apply for descriptions of parameters ({@link
154.164 - * MBeanParameterInfo}). The default {@code resourceKey} for a parameter
154.165 - * whose {@linkplain MBeanFeatureInfo#getName() name} is {@code
154.166 - * Bar} in an operation or constructor called {@code Foo} is {@code
154.167 - * simpleClassName + ".operation.Foo.Bar"} or {@code simpleClassName +
154.168 - * ".constructor.Foo.Bar"} respectively.</p>
154.169 - *
154.170 - * <h4>Example</h4>
154.171 - *
154.172 - * <p>Suppose you have an MBean defined by these two Java source files:</p>
154.173 - *
154.174 - * <pre>
154.175 - * // ConfigurationMBean.java
154.176 - * package com.example;
154.177 - * public interface ConfigurationMBean {
154.178 - * public String getName();
154.179 - * public void save(String fileName);
154.180 - * }
154.181 - *
154.182 - * // Configuration.java
154.183 - * package com.example;
154.184 - * public class Configuration implements ConfigurationMBean {
154.185 - * public Configuration(String defaultName) {
154.186 - * ...
154.187 - * }
154.188 - * ...
154.189 - * }
154.190 - * </pre>
154.191 - *
154.192 - * <p>Then you could define the default descriptions for the MBean, by
154.193 - * including a resource bundle called {@code com/example/MBeanDescriptions}
154.194 - * with the compiled classes. Most often this is done by creating a file
154.195 - * {@code MBeanDescriptions.properties} in the same directory as {@code
154.196 - * ConfigurationMBean.java}. Make sure that this file is copied into the
154.197 - * same place as the compiled classes; in typical build environments that
154.198 - * will be true by default.</p>
154.199 - *
154.200 - * <p>The file {@code com/example/MBeanDescriptions.properties} might
154.201 - * look like this:</p>
154.202 - *
154.203 - * <pre>
154.204 - * # Description of the MBean
154.205 - * ConfigurationMBean.mbean = Configuration manager
154.206 - *
154.207 - * # Description of the Name attribute
154.208 - * ConfigurationMBean.attribute.Name = The name of the configuration
154.209 - *
154.210 - * # Description of the save operation
154.211 - * ConfigurationMBean.operation.save = Save the configuration to a file
154.212 - *
154.213 - * # Description of the parameter to the save operation.
154.214 - * # Parameter names from the original Java source are not available,
154.215 - * # so the default names are p1, p2, etc. If the names were available,
154.216 - * # this would be ConfigurationMBean.operation.save.fileName
154.217 - * ConfigurationMBean.operation.save.p1 = The name of the file
154.218 - *
154.219 - * # Description of the constructor. The default name of a constructor is
154.220 - * # its fully-qualified class name.
154.221 - * ConfigurationMBean.constructor.com.example.Configuration = <!--
154.222 - * -->Constructor with name of default file
154.223 - * # Description of the constructor parameter.
154.224 - * ConfigurationMBean.constructor.com.example.Configuration.p1 = <!--
154.225 - * -->Name of the default file
154.226 - * </pre>
154.227 - *
154.228 - * <p>Starting with this file, you could create descriptions for the French
154.229 - * locale by creating {@code com/example/MBeanDescriptions_fr.properties}.
154.230 - * The keys in this file are the same as before but the text has been
154.231 - * translated:
154.232 - *
154.233 - * <pre>
154.234 - * ConfigurationMBean.mbean = Gestionnaire de configuration
154.235 - *
154.236 - * ConfigurationMBean.attribute.Name = Le nom de la configuration
154.237 - *
154.238 - * ConfigurationMBean.operation.save = Sauvegarder la configuration <!--
154.239 - * -->dans un fichier
154.240 - *
154.241 - * ConfigurationMBean.operation.save.p1 = Le nom du fichier
154.242 - *
154.243 - * ConfigurationMBean.constructor.com.example.Configuration = <!--
154.244 - * -->Constructeur avec nom du fichier par défaut
154.245 - * ConfigurationMBean.constructor.com.example.Configuration.p1 = <!--
154.246 - * -->Nom du fichier par défaut
154.247 - * </pre>
154.248 - *
154.249 - * <p>The descriptions in {@code MBeanDescriptions.properties} and
154.250 - * {@code MBeanDescriptions_fr.properties} will only be consulted if
154.251 - * {@code localizeDescriptions} is called, perhaps because the
154.252 - * MBean Server has been wrapped by {@link
154.253 - * ClientContext#newLocalizeMBeanInfoForwarder} or because the
154.254 - * connector server has been created with the {@link
154.255 - * javax.management.remote.JMXConnectorServer#LOCALIZE_MBEAN_INFO_FORWARDER
154.256 - * LOCALIZE_MBEAN_INFO_FORWARDER} option. If you want descriptions
154.257 - * even when there is no localization step, then you should consider
154.258 - * using {@link Description @Description} annotations. Annotations
154.259 - * provide descriptions by default but are overridden if {@code
154.260 - * localizeDescriptions} is called.</p>
154.261 - *
154.262 - * @param locale the target locale for descriptions. Cannot be null.
154.263 - *
154.264 - * @param loader the {@code ClassLoader} to use for looking up resource
154.265 - * bundles.
154.266 - *
154.267 - * @return an {@code MBeanInfo} with descriptions appropriately localized.
154.268 - *
154.269 - * @throws NullPointerException if {@code locale} is null.
154.270 - */
154.271 - public MBeanInfo localizeDescriptions(Locale locale, ClassLoader loader) {
154.272 - if (locale == null)
154.273 - throw new NullPointerException("locale");
154.274 - Descriptor d = getDescriptor();
154.275 - String mbiLocaleString = (String) d.getFieldValue(JMX.LOCALE_FIELD);
154.276 - if (locale.toString().equals(mbiLocaleString))
154.277 - return this;
154.278 - return new Rewriter(this, locale, loader).getMBeanInfo();
154.279 - }
154.280 -
154.281 - private static class Rewriter {
154.282 - private final MBeanInfo mbi;
154.283 - private final ClassLoader loader;
154.284 - private final Locale locale;
154.285 - private final String packageName;
154.286 - private final String simpleClassNamePlusDot;
154.287 - private ResourceBundle defaultBundle;
154.288 - private boolean defaultBundleLoaded;
154.289 -
154.290 - // ResourceBundle.getBundle throws NullPointerException
154.291 - // if the loader is null, even though that is perfectly
154.292 - // valid and means the bootstrap loader. So we work
154.293 - // around with a ClassLoader that is equivalent to the
154.294 - // bootstrap loader but is not null.
154.295 - private static final ClassLoader bootstrapLoader =
154.296 - new ClassLoader(null) {};
154.297 -
154.298 - Rewriter(MBeanInfo mbi, Locale locale, ClassLoader loader) {
154.299 - this.mbi = mbi;
154.300 - this.locale = locale;
154.301 - if (loader == null)
154.302 - loader = bootstrapLoader;
154.303 - this.loader = loader;
154.304 -
154.305 - String intfName = (String)
154.306 - mbi.getDescriptor().getFieldValue("interfaceClassName");
154.307 - if (intfName == null)
154.308 - intfName = mbi.getClassName();
154.309 - int lastDot = intfName.lastIndexOf('.');
154.310 - this.packageName = intfName.substring(0, lastDot + 1);
154.311 - this.simpleClassNamePlusDot = intfName.substring(lastDot + 1) + ".";
154.312 - // Inner classes show up as Outer$Inner so won't match the dot.
154.313 - // When there is no dot, lastDot is -1,
154.314 - // packageName is empty, and simpleClassNamePlusDot is intfName.
154.315 - }
154.316 -
154.317 - MBeanInfo getMBeanInfo() {
154.318 - MBeanAttributeInfo[] mbais =
154.319 - rewrite(mbi.getAttributes(), "attribute.");
154.320 - MBeanOperationInfo[] mbois =
154.321 - rewrite(mbi.getOperations(), "operation.");
154.322 - MBeanConstructorInfo[] mbcis =
154.323 - rewrite(mbi.getConstructors(), "constructor.");
154.324 - MBeanNotificationInfo[] mbnis =
154.325 - rewrite(mbi.getNotifications(), "notification.");
154.326 - Descriptor d = mbi.getDescriptor();
154.327 - d = changeLocale(d);
154.328 - String description = getDescription(d, "mbean", "");
154.329 - if (description == null)
154.330 - description = mbi.getDescription();
154.331 - return new MBeanInfo(
154.332 - mbi.getClassName(), description,
154.333 - mbais, mbcis, mbois, mbnis, d);
154.334 - }
154.335 -
154.336 - private Descriptor changeLocale(Descriptor d) {
154.337 - if (d.getFieldValue(JMX.LOCALE_FIELD) != null) {
154.338 - Map<String, Object> map = new HashMap<String, Object>();
154.339 - for (String field : d.getFieldNames())
154.340 - map.put(field, d.getFieldValue(field));
154.341 - map.remove(JMX.LOCALE_FIELD);
154.342 - d = new ImmutableDescriptor(map);
154.343 - }
154.344 - return ImmutableDescriptor.union(
154.345 - d, new ImmutableDescriptor(JMX.LOCALE_FIELD + "=" + locale));
154.346 - }
154.347 -
154.348 - private String getDescription(
154.349 - Descriptor d, String defaultPrefix, String defaultSuffix) {
154.350 - ResourceBundle bundle = bundleFromDescriptor(d);
154.351 - if (bundle == null)
154.352 - return null;
154.353 - String key =
154.354 - (String) d.getFieldValue(JMX.DESCRIPTION_RESOURCE_KEY_FIELD);
154.355 - if (key == null)
154.356 - key = simpleClassNamePlusDot + defaultPrefix + defaultSuffix;
154.357 - return descriptionFromResource(bundle, key);
154.358 - }
154.359 -
154.360 - private <T extends MBeanFeatureInfo> T[] rewrite(
154.361 - T[] features, String resourcePrefix) {
154.362 - for (int i = 0; i < features.length; i++) {
154.363 - T feature = features[i];
154.364 - Descriptor d = feature.getDescriptor();
154.365 - String description =
154.366 - getDescription(d, resourcePrefix, feature.getName());
154.367 - if (description != null &&
154.368 - !description.equals(feature.getDescription())) {
154.369 - features[i] = setDescription(feature, description);
154.370 - }
154.371 - }
154.372 - return features;
154.373 - }
154.374 -
154.375 - private <T extends MBeanFeatureInfo> T setDescription(
154.376 - T feature, String description) {
154.377 -
154.378 - Object newf;
154.379 - String name = feature.getName();
154.380 - Descriptor d = feature.getDescriptor();
154.381 -
154.382 - if (feature instanceof MBeanAttributeInfo) {
154.383 - MBeanAttributeInfo mbai = (MBeanAttributeInfo) feature;
154.384 - newf = new MBeanAttributeInfo(
154.385 - name, mbai.getType(), description,
154.386 - mbai.isReadable(), mbai.isWritable(), mbai.isIs(),
154.387 - d);
154.388 - } else if (feature instanceof MBeanOperationInfo) {
154.389 - MBeanOperationInfo mboi = (MBeanOperationInfo) feature;
154.390 - MBeanParameterInfo[] sig = rewrite(
154.391 - mboi.getSignature(), "operation." + name + ".");
154.392 - newf = new MBeanOperationInfo(
154.393 - name, description, sig,
154.394 - mboi.getReturnType(), mboi.getImpact(), d);
154.395 - } else if (feature instanceof MBeanConstructorInfo) {
154.396 - MBeanConstructorInfo mbci = (MBeanConstructorInfo) feature;
154.397 - MBeanParameterInfo[] sig = rewrite(
154.398 - mbci.getSignature(), "constructor." + name + ".");
154.399 - newf = new MBeanConstructorInfo(
154.400 - name, description, sig, d);
154.401 - } else if (feature instanceof MBeanNotificationInfo) {
154.402 - MBeanNotificationInfo mbni = (MBeanNotificationInfo) feature;
154.403 - newf = new MBeanNotificationInfo(
154.404 - mbni.getNotifTypes(), name, description, d);
154.405 - } else if (feature instanceof MBeanParameterInfo) {
154.406 - MBeanParameterInfo mbpi = (MBeanParameterInfo) feature;
154.407 - newf = new MBeanParameterInfo(
154.408 - name, mbpi.getType(), description, d);
154.409 - } else {
154.410 - logger().log(Level.FINE, "Unknown feature type: " +
154.411 - feature.getClass());
154.412 - newf = feature;
154.413 - }
154.414 -
154.415 - return Util.<T>cast(newf);
154.416 - }
154.417 -
154.418 - private ResourceBundle bundleFromDescriptor(Descriptor d) {
154.419 - String bundleName = (String) d.getFieldValue(
154.420 - JMX.DESCRIPTION_RESOURCE_BUNDLE_BASE_NAME_FIELD);
154.421 -
154.422 - if (bundleName != null)
154.423 - return getBundle(bundleName);
154.424 -
154.425 - if (defaultBundleLoaded)
154.426 - return defaultBundle;
154.427 -
154.428 - bundleName = packageName + "MBeanDescriptions";
154.429 - defaultBundle = getBundle(bundleName);
154.430 - defaultBundleLoaded = true;
154.431 - return defaultBundle;
154.432 - }
154.433 -
154.434 - private String descriptionFromResource(
154.435 - ResourceBundle bundle, String key) {
154.436 - try {
154.437 - return bundle.getString(key);
154.438 - } catch (MissingResourceException e) {
154.439 - logger().log(Level.FINEST, "No resource for " + key, e);
154.440 - } catch (Exception e) {
154.441 - logger().log(Level.FINE, "Bad resource for " + key, e);
154.442 - }
154.443 - return null;
154.444 - }
154.445 -
154.446 - private ResourceBundle getBundle(String name) {
154.447 - try {
154.448 - return ResourceBundle.getBundle(name, locale, loader);
154.449 - } catch (Exception e) {
154.450 - logger().log(Level.FINE,
154.451 - "Could not load ResourceBundle " + name, e);
154.452 - return null;
154.453 - }
154.454 - }
154.455 -
154.456 - private Logger logger() {
154.457 - return Logger.getLogger("javax.management.locale");
154.458 - }
154.459 - }
154.460 }
155.1 --- a/src/share/classes/javax/management/MBeanOperationInfo.java Mon Nov 23 10:04:47 2009 +0000
155.2 +++ b/src/share/classes/javax/management/MBeanOperationInfo.java Wed Nov 25 11:08:25 2009 -0800
155.3 @@ -48,28 +48,24 @@
155.4 /**
155.5 * Indicates that the operation is read-like:
155.6 * it returns information but does not change any state.
155.7 - * @see Impact#INFO
155.8 */
155.9 public static final int INFO = 0;
155.10
155.11 /**
155.12 * Indicates that the operation is write-like: it has an effect but does
155.13 * not return any information from the MBean.
155.14 - * @see Impact#ACTION
155.15 */
155.16 public static final int ACTION = 1;
155.17
155.18 /**
155.19 * Indicates that the operation is both read-like and write-like:
155.20 * it has an effect, and it also returns information from the MBean.
155.21 - * @see Impact#ACTION_INFO
155.22 */
155.23 public static final int ACTION_INFO = 2;
155.24
155.25 /**
155.26 * Indicates that the impact of the operation is unknown or cannot be
155.27 * expressed using one of the other values.
155.28 - * @see Impact#UNKNOWN
155.29 */
155.30 public static final int UNKNOWN = 3;
155.31
155.32 @@ -113,7 +109,7 @@
155.33 methodSignature(method),
155.34 method.getReturnType().getName(),
155.35 UNKNOWN,
155.36 - Introspector.descriptorForElement(method, false));
155.37 + Introspector.descriptorForElement(method));
155.38 }
155.39
155.40 /**
155.41 @@ -185,6 +181,7 @@
155.42 * <p>Since this class is immutable, cloning is chiefly of interest
155.43 * to subclasses.</p>
155.44 */
155.45 + @Override
155.46 public Object clone () {
155.47 try {
155.48 return super.clone() ;
155.49 @@ -257,6 +254,7 @@
155.50 return impact;
155.51 }
155.52
155.53 + @Override
155.54 public String toString() {
155.55 String impactString;
155.56 switch (getImpact()) {
155.57 @@ -288,6 +286,7 @@
155.58 * to those of this MBeanConstructorInfo. Two signature arrays
155.59 * are equal if their elements are pairwise equal.
155.60 */
155.61 + @Override
155.62 public boolean equals(Object o) {
155.63 if (o == this)
155.64 return true;
155.65 @@ -327,14 +326,9 @@
155.66
155.67 for (int i = 0; i < classes.length; i++) {
155.68 Descriptor d = Introspector.descriptorForAnnotations(annots[i]);
155.69 - String description = Introspector.descriptionForParameter(annots[i]);
155.70 - if (description == null)
155.71 - description = "";
155.72 - String name = Introspector.nameForParameter(annots[i]);
155.73 - if (name == null)
155.74 - name = "p" + (i + 1);
155.75 - params[i] = new MBeanParameterInfo(
155.76 - name, classes[i].getName(), description, d);
155.77 + final String pn = "p" + (i + 1);
155.78 + params[i] =
155.79 + new MBeanParameterInfo(pn, classes[i].getName(), "", d);
155.80 }
155.81
155.82 return params;
156.1 --- a/src/share/classes/javax/management/MBeanPermission.java Mon Nov 23 10:04:47 2009 +0000
156.2 +++ b/src/share/classes/javax/management/MBeanPermission.java Wed Nov 25 11:08:25 2009 -0800
156.3 @@ -25,7 +25,6 @@
156.4
156.5 package javax.management;
156.6
156.7 -import com.sun.jmx.mbeanserver.Util;
156.8 import java.io.IOException;
156.9 import java.io.ObjectInputStream;
156.10 import java.security.Permission;
156.11 @@ -46,7 +45,7 @@
156.12 * allowed if the permissions you have {@linkplain #implies imply} the
156.13 * permission you need.</p>
156.14 *
156.15 - * <p>An MBeanPermission contains five items of information:</p>
156.16 + * <p>An MBeanPermission contains four items of information:</p>
156.17 *
156.18 * <ul>
156.19 *
156.20 @@ -58,23 +57,6 @@
156.21 *
156.22 * <p>The action is returned by {@link #getActions()}.</p>
156.23 *
156.24 - * <li id="MBeanServerName"><p>The <em>MBean Server name</em>.</p>
156.25 - *
156.26 - * <p>For a permission you need, this is the {@linkplain
156.27 - * javax.management.MBeanServerFactory#getMBeanServerName
156.28 - * name of the MBeanServer}
156.29 - * containing the <a href="#MBeanName">MBean</a> for which the MBean
156.30 - * permission is checked.</p>
156.31 - *
156.32 - * <p>For a permission you have, this is either the {@linkplain
156.33 - * javax.management.MBeanServerFactory#getMBeanServerName
156.34 - * name of the MBeanServer} in which the <a href="#MBeanName">MBean</a>
156.35 - * you have this permission for must be registered,
156.36 - * or a pattern against which that MBean Server name will be matched.<br>
156.37 - * An {@code mbeanServerName} pattern can also be empty or the single
156.38 - * character {@code "*"}, both of which will match any {@code MBeanServer} name.
156.39 - * </p>
156.40 - *
156.41 * <li><p>The <em>class name</em>.</p>
156.42 *
156.43 * <p>For a permission you need, this is the class name of an MBean
156.44 @@ -121,15 +103,15 @@
156.45 * </ul>
156.46 *
156.47 * <p>If you have an MBeanPermission, it allows operations only if all
156.48 - * five of the items match.</p>
156.49 + * four of the items match.</p>
156.50 *
156.51 - * <p>The MBean Server name, class name, member, and object name can be written
156.52 - * together as a single string, which is the <em>name</em> of this permission.
156.53 + * <p>The class name, member, and object name can be written together
156.54 + * as a single string, which is the <em>name</em> of this permission.
156.55 * The name of the permission is the string returned by {@link
156.56 * Permission#getName() getName()}. The format of the string is:</p>
156.57 *
156.58 * <blockquote>
156.59 - * <code>mbeanServerName::className#member[objectName]</code>
156.60 + * <code>className#member[objectName]</code>
156.61 * </blockquote>
156.62 *
156.63 * <p>The object name is written using the usual syntax for {@link
156.64 @@ -137,18 +119,15 @@
156.65 * <code>]</code>. It is terminated by a <code>]</code> character
156.66 * that is the last character in the string.</p>
156.67 *
156.68 - * <p>One or more of the <code>mbeanServerName</code>, <code>className</code>,
156.69 - * <code>member</code>, or <code>objectName</code> may be omitted. If the
156.70 - * <code>mbeanServerName</code> is omitted, the <code>::</code> may be too (but
156.71 - * does not have to be).
156.72 - * If the <code>member</code> is omitted, the <code>#</code> may be too (but
156.73 + * <p>One or more of the <code>className</code>, <code>member</code>,
156.74 + * or <code>objectName</code> may be omitted. If the
156.75 + * <code>member</code> is omitted, the <code>#</code> may be too (but
156.76 * does not have to be). If the <code>objectName</code> is omitted,
156.77 * the <code>[]</code> may be too (but does not have to be). It is
156.78 - * not legal to omit all four items, that is to have a <em>name</em>
156.79 + * not legal to omit all three items, that is to have a <em>name</em>
156.80 * that is the empty string.</p>
156.81 *
156.82 - * <p>One or more of the <code>mbeanServerName</code>, <code>className</code>,
156.83 - * <code>member</code>,
156.84 + * <p>One or more of the <code>className</code>, <code>member</code>,
156.85 * or <code>objectName</code> may be the character "<code>-</code>",
156.86 * which is equivalent to a null value. A null value is implied by
156.87 * any value (including another null value) but does not imply any
156.88 @@ -268,13 +247,6 @@
156.89 private transient ObjectName objectName;
156.90
156.91 /**
156.92 - * The name of the MBeanServer in which this permission is checked, or
156.93 - * granted. If null, is implied by any MBean Server name
156.94 - * but does not imply any non-null MBean Server name.
156.95 - */
156.96 - private transient String mbeanServerName;
156.97 -
156.98 - /**
156.99 * Parse <code>actions</code> parameter.
156.100 */
156.101 private void parseActions() {
156.102 @@ -311,13 +283,6 @@
156.103 throw new IllegalArgumentException("MBeanPermission name " +
156.104 "cannot be empty");
156.105
156.106 - final int sepIndex = name.indexOf("::");
156.107 - if (sepIndex < 0) {
156.108 - setMBeanServerName("*");
156.109 - } else {
156.110 - setMBeanServerName(name.substring(0,sepIndex));
156.111 - }
156.112 -
156.113 /* The name looks like "class#member[objectname]". We subtract
156.114 elements from the right as we parse, so after parsing the
156.115 objectname we have "class#member" and after parsing the
156.116 @@ -325,14 +290,11 @@
156.117
156.118 // Parse ObjectName
156.119
156.120 -
156.121 - final int start = (sepIndex<0)?0:sepIndex+2;
156.122 - int openingBracket = name.indexOf("[",start);
156.123 + int openingBracket = name.indexOf("[");
156.124 if (openingBracket == -1) {
156.125 // If "[on]" missing then ObjectName("*:*")
156.126 //
156.127 objectName = ObjectName.WILDCARD;
156.128 - name = name.substring(start);
156.129 } else {
156.130 if (!name.endsWith("]")) {
156.131 throw new IllegalArgumentException("MBeanPermission: " +
156.132 @@ -343,11 +305,11 @@
156.133 } else {
156.134 // Create ObjectName
156.135 //
156.136 - String on = name.substring(openingBracket + 1,
156.137 - name.length() - 1);
156.138 try {
156.139 // If "[]" then ObjectName("*:*")
156.140 //
156.141 + String on = name.substring(openingBracket + 1,
156.142 + name.length() - 1);
156.143 if (on.equals(""))
156.144 objectName = ObjectName.WILDCARD;
156.145 else if (on.equals("-"))
156.146 @@ -362,7 +324,7 @@
156.147 }
156.148 }
156.149
156.150 - name = name.substring(start, openingBracket);
156.151 + name = name.substring(0, openingBracket);
156.152 }
156.153
156.154 // Parse member
156.155 @@ -386,9 +348,8 @@
156.156 * Assign fields based on className, member, and objectName
156.157 * parameters.
156.158 */
156.159 - private void initName(String mbeanServerName, String className,
156.160 - String member, ObjectName objectName) {
156.161 - setMBeanServerName(mbeanServerName);
156.162 + private void initName(String className, String member,
156.163 + ObjectName objectName) {
156.164 setClassName(className);
156.165 setMember(member);
156.166 this.objectName = objectName;
156.167 @@ -420,30 +381,19 @@
156.168 this.member = member;
156.169 }
156.170
156.171 - private void setMBeanServerName(String mbeanServerName) {
156.172 - if (mbeanServerName == null || mbeanServerName.equals("-")) {
156.173 - this.mbeanServerName = null;
156.174 - } else if (mbeanServerName.equals("")) {
156.175 - this.mbeanServerName = "*";
156.176 - } else {
156.177 - this.mbeanServerName = mbeanServerName;
156.178 - }
156.179 - }
156.180 -
156.181 -
156.182 /**
156.183 * <p>Create a new MBeanPermission object with the specified target name
156.184 * and actions.</p>
156.185 *
156.186 * <p>The target name is of the form
156.187 - * "<code>mbeanServerName::className#member[objectName]</code>" where
156.188 - * each part is optional. It must not be empty or null.</p>
156.189 + * "<code>className#member[objectName]</code>" where each part is
156.190 + * optional. It must not be empty or null.</p>
156.191 *
156.192 * <p>The actions parameter contains a comma-separated list of the
156.193 * desired actions granted on the target name. It must not be
156.194 * empty or null.</p>
156.195 *
156.196 - * @param name the quadruplet "mbeanServerName::className#member[objectName]".
156.197 + * @param name the triplet "className#member[objectName]".
156.198 * @param actions the action string.
156.199 *
156.200 * @exception IllegalArgumentException if the <code>name</code> or
156.201 @@ -468,12 +418,6 @@
156.202 * optional. This will be the result of {@link #getName()} on the
156.203 * resultant MBeanPermission.</p>
156.204 *
156.205 - * <p>This corresponds to a permission granted for all
156.206 - * MBean servers present in the JVM and is equivalent to
156.207 - * {@link #MBeanPermission(String,String,String,ObjectName,String)
156.208 - * MBeanPermission("*",className,member,objectName,actions)}.
156.209 - * </p>
156.210 - *
156.211 * <p>The actions parameter contains a comma-separated list of the
156.212 * desired actions granted on the target name. It must not be
156.213 * empty or null.</p>
156.214 @@ -495,67 +439,17 @@
156.215 String member,
156.216 ObjectName objectName,
156.217 String actions) {
156.218 - this("*",className,member,objectName,actions);
156.219 - }
156.220
156.221 - /**
156.222 - * <p>Create a new MBeanPermission object with the specified target name
156.223 - * (MBean Server name, class name, member, object name) and actions.</p>
156.224 - *
156.225 - * <p>The MBean Server name, class name, member and object name
156.226 - * parameters define a target name of the form
156.227 - * "<code>mbeanServerName::className#member[objectName]</code>" where each
156.228 - * part is optional. This will be the result of {@link #getName()} on the
156.229 - * resultant MBeanPermission.
156.230 - * If the <code>mbeanServerName</code> is empty or exactly {@code "*"}, then
156.231 - * "{@code mbeanServerName::}" is omitted in that result.
156.232 - * </p>
156.233 - *
156.234 - * <p>The actions parameter contains a comma-separated list of the
156.235 - * desired actions granted on the target name. It must not be
156.236 - * empty or null.</p>
156.237 - *
156.238 - * @param mbeanServerName the name of the {@code MBeanServer} to which this
156.239 - * permission applies.
156.240 - * May be null or <code>"-"</code>, which represents an MBeanServer name
156.241 - * that is implied by any MBeanServer name but does not imply any other
156.242 - * MBeanServer name.
156.243 - * @param className the class name to which this permission applies.
156.244 - * May be null or <code>"-"</code>, which represents a class name
156.245 - * that is implied by any class name but does not imply any other
156.246 - * class name.
156.247 - * @param member the member to which this permission applies. May
156.248 - * be null or <code>"-"</code>, which represents a member that is
156.249 - * implied by any member but does not imply any other member.
156.250 - * @param objectName the object name to which this permission
156.251 - * applies. May be null, which represents an object name that is
156.252 - * implied by any object name but does not imply any other object
156.253 - * name.
156.254 - * @param actions the action string.
156.255 - *
156.256 - * @since 1.7
156.257 - */
156.258 - public MBeanPermission(String mbeanServerName,
156.259 - String className,
156.260 - String member,
156.261 - ObjectName objectName,
156.262 - String actions) {
156.263 -
156.264 - super(makeName(mbeanServerName,className, member, objectName));
156.265 - initName(mbeanServerName,className, member, objectName);
156.266 + super(makeName(className, member, objectName));
156.267 + initName(className, member, objectName);
156.268
156.269 this.actions = actions;
156.270 parseActions();
156.271 }
156.272
156.273 - private static String makeName(String mbeanServerName, String className,
156.274 - String member,
156.275 + private static String makeName(String className, String member,
156.276 ObjectName objectName) {
156.277 final StringBuilder name = new StringBuilder();
156.278 - if (mbeanServerName == null)
156.279 - mbeanServerName = "-";
156.280 - if (!mbeanServerName.equals("") && !mbeanServerName.equals("*"))
156.281 - name.append(mbeanServerName).append("::");
156.282 if (className == null)
156.283 className = "-";
156.284 name.append(className);
156.285 @@ -1097,9 +991,6 @@
156.286 *
156.287 * <li> <i>p</i> is an instance of MBeanPermission; and</li>
156.288 *
156.289 - * <li> <i>p</i> has a null mbeanServerName or <i>p</i>'s mbeanServerName
156.290 - * matches this object's mbeanServerName; and</li>
156.291 - *
156.292 * <li> <i>p</i> has a null className or <i>p</i>'s className
156.293 * matches this object's className; and</li>
156.294 *
156.295 @@ -1113,13 +1004,6 @@
156.296 *
156.297 * </ul>
156.298 *
156.299 - * <p>If this object's mbeanServerName is a pattern, then <i>p</i>'s
156.300 - * mbeanServerName is matched against that pattern. An empty
156.301 - * mbeanServerName is equivalent to "{@code *}". A null
156.302 - * mbeanServerName is equivalent to "{@code -}".</p>
156.303 - * <p>If this object's mbeanServerName is "<code>*</code>" or is
156.304 - * empty, <i>p</i>'s mbeanServerName always matches it.</p>
156.305 - *
156.306 * <p>If this object's className is "<code>*</code>", <i>p</i>'s
156.307 * className always matches it. If it is "<code>a.*</code>", <i>p</i>'s
156.308 * className matches it if it begins with "<code>a.</code>".</p>
156.309 @@ -1166,12 +1050,6 @@
156.310
156.311 // Target name
156.312 //
156.313 - // The 'mbeanServerName' check is true iff:
156.314 - // 1) the mbeanServerName in 'this' permission is omitted or "*", or
156.315 - // 2) the mbeanServerName in 'that' permission is omitted or "*", or
156.316 - // 3) the mbeanServerName in 'this' permission does pattern
156.317 - // matching with the mbeanServerName in 'that' permission.
156.318 - //
156.319 // The 'className' check is true iff:
156.320 // 1) the className in 'this' permission is omitted or "*", or
156.321 // 2) the className in 'that' permission is omitted or "*", or
156.322 @@ -1198,17 +1076,6 @@
156.323 expect that "that" contains a wildcard, since it is a
156.324 needed permission. So we assume that.classNameExactMatch. */
156.325
156.326 - if (that.mbeanServerName == null) {
156.327 - // bottom is implied
156.328 - } else if (this.mbeanServerName == null) {
156.329 - // bottom implies nothing but itself
156.330 - return false;
156.331 - } else if (that.mbeanServerName.equals(this.mbeanServerName)) {
156.332 - // exact match
156.333 - } else if (!Util.wildmatch(that.mbeanServerName,this.mbeanServerName)) {
156.334 - return false; // no match
156.335 - }
156.336 -
156.337 if (that.classNamePrefix == null) {
156.338 // bottom is implied
156.339 } else if (this.classNamePrefix == null) {
157.1 --- a/src/share/classes/javax/management/MBeanRegistration.java Mon Nov 23 10:04:47 2009 +0000
157.2 +++ b/src/share/classes/javax/management/MBeanRegistration.java Wed Nov 25 11:08:25 2009 -0800
157.3 @@ -33,99 +33,6 @@
157.4 * to get a reference to the MBean Server and/or its name within that
157.5 * MBean Server.</p>
157.6 *
157.7 - * <h4 id="injection">Resource injection</h4>
157.8 - *
157.9 - * <p>As an alternative to implementing {@code MBeanRegistration}, if all that
157.10 - * is needed is the MBean Server or ObjectName then an MBean can use
157.11 - * <em>resource injection</em>.</p>
157.12 - *
157.13 - * <p>If a field in the MBean object has type {@link ObjectName} and has
157.14 - * the {@link javax.annotation.Resource @Resource} annotation,
157.15 - * then the {@code ObjectName} under which the MBean is registered is
157.16 - * assigned to that field during registration. Likewise, if a field has type
157.17 - * {@link MBeanServer} and the <code>@Resource</code> annotation, then it will
157.18 - * be set to the {@code MBeanServer} in which the MBean is registered.</p>
157.19 - *
157.20 - * <p>For example:</p>
157.21 - *
157.22 - * <pre>
157.23 - * public Configuration implements ConfigurationMBean {
157.24 - * @Resource
157.25 - * private volatile MBeanServer mbeanServer;
157.26 - * @Resource
157.27 - * private volatile ObjectName objectName;
157.28 - * ...
157.29 - * void unregisterSelf() throws Exception {
157.30 - * mbeanServer.unregisterMBean(objectName);
157.31 - * }
157.32 - * }
157.33 - * </pre>
157.34 - *
157.35 - * <p>Resource injection can also be used on fields of type
157.36 - * {@link SendNotification} to simplify notification sending. Such a field
157.37 - * will get a reference to an object of type {@code SendNotification} when
157.38 - * the MBean is registered, and it can use this reference to send notifications.
157.39 - * For example:</p>
157.40 - *
157.41 - * <pre>
157.42 - * public Configuration implements ConfigurationMBean {
157.43 - * @Resource
157.44 - * private volatile SendNotification sender;
157.45 - * ...
157.46 - * private void updated() {
157.47 - * Notification n = new Notification(...);
157.48 - * sender.sendNotification(n);
157.49 - * }
157.50 - * }
157.51 - * </pre>
157.52 - *
157.53 - * <p>(Listeners may be invoked in the same thread as the caller of
157.54 - * {@code sender.sendNotification}.)</p>
157.55 - *
157.56 - * <p>A field to be injected must not be static. It is recommended that
157.57 - * such fields be declared {@code volatile}.</p>
157.58 - *
157.59 - * <p>It is also possible to use the <code>@Resource</code> annotation on
157.60 - * methods. Such a method must have a {@code void} return type and a single
157.61 - * argument of the appropriate type, for example {@code ObjectName}.</p>
157.62 - *
157.63 - * <p>Any number of fields and methods may have the <code>@Resource</code>
157.64 - * annotation. All fields and methods with type {@code ObjectName}
157.65 - * (for example) will receive the same {@code ObjectName} value.</p>
157.66 - *
157.67 - * <p>Resource injection is available for all types of MBeans, not just
157.68 - * Standard MBeans.</p>
157.69 - *
157.70 - * <p>If an MBean implements the {@link DynamicWrapperMBean} interface then
157.71 - * resource injection happens on the object returned by that interface's
157.72 - * {@link DynamicWrapperMBean#getWrappedObject() getWrappedObject()} method
157.73 - * rather than on the MBean object itself.
157.74 - *
157.75 - * <p>Resource injection happens after the {@link #preRegister preRegister}
157.76 - * method is called (if any), and before the MBean is actually registered
157.77 - * in the MBean Server. If a <code>@Resource</code> method throws
157.78 - * an exception, the effect is the same as if {@code preRegister} had
157.79 - * thrown the exception. In particular it will prevent the MBean from being
157.80 - * registered.</p>
157.81 - *
157.82 - * <p>Resource injection can be used on a field or method where the type
157.83 - * is a parent of the injected type, if the injected type is explicitly
157.84 - * specified in the <code>@Resource</code> annotation. For example:</p>
157.85 - *
157.86 - * <pre>
157.87 - * @Resource(type = MBeanServer.class)
157.88 - * private volatile MBeanServerConnection mbsc;
157.89 - * </pre>
157.90 - *
157.91 - * <p>Formally, suppose <em>R</em> is the type in the <code>@Resource</code>
157.92 - * annotation and <em>T</em> is the type of the method parameter or field.
157.93 - * Then one of <em>R</em> and <em>T</em> must be a subtype of the other
157.94 - * (or they must be the same type). Injection happens if this subtype
157.95 - * is {@code MBeanServer}, {@code ObjectName}, or {@code SendNotification}.
157.96 - * Otherwise the <code>@Resource</code> annotation is ignored.</p>
157.97 - *
157.98 - * <p>Resource injection in MBeans is new in version 2.0 of the JMX API.</p>
157.99 - *
157.100 * @since 1.5
157.101 */
157.102 public interface MBeanRegistration {
157.103 @@ -196,7 +103,7 @@
157.104 * <p>If the implementation of this method throws a {@link RuntimeException}
157.105 * or an {@link Error}, the MBean Server will rethrow those inside
157.106 * a {@link RuntimeMBeanException} or {@link RuntimeErrorException},
157.107 - * respectively. However, throwing an excepption in {@code postDeregister}
157.108 + * respectively. However, throwing an exception in {@code postDeregister}
157.109 * will not change the state of the MBean:
157.110 * the MBean was already successfully deregistered and will remain so. </p>
157.111 * <p>This might be confusing for the code calling
158.1 --- a/src/share/classes/javax/management/MBeanServer.java Mon Nov 23 10:04:47 2009 +0000
158.2 +++ b/src/share/classes/javax/management/MBeanServer.java Wed Nov 25 11:08:25 2009 -0800
158.3 @@ -61,13 +61,9 @@
158.4 * <CODE>ObjectName</CODE> is: <BR>
158.5 * <CODE>JMImplementation:type=MBeanServerDelegate</CODE>.</p>
158.6 *
158.7 - * <p id="security">An object obtained from the {@link
158.8 - * MBeanServerFactory#createMBeanServer(String) createMBeanServer}, {@link
158.9 - * MBeanServerFactory#createNamedMBeanServer(String,String) createNamedMBeanServer},
158.10 - * {@link
158.11 - * MBeanServerFactory#newMBeanServer(String) newMBeanServer}, or
158.12 - * {@link
158.13 - * MBeanServerFactory#newNamedMBeanServer(String,String) newNamedMBeanServer}
158.14 + * <p>An object obtained from the {@link
158.15 + * MBeanServerFactory#createMBeanServer(String) createMBeanServer} or
158.16 + * {@link MBeanServerFactory#newMBeanServer(String) newMBeanServer}
158.17 * methods of the {@link MBeanServerFactory} class applies security
158.18 * checks to its methods, as follows.</p>
158.19 *
158.20 @@ -77,26 +73,10 @@
158.21 *
158.22 * <p>Assuming that there is a security manager, or that the
158.23 * implementation chooses to make checks anyway, the checks are made
158.24 - * as detailed below.
158.25 - * In what follows, and unless otherwise specified:
158.26 - * </p>
158.27 - * <ul><li><code>className</code> is the
158.28 + * as detailed below. In what follows, and unless otherwise specified,
158.29 + * {@code className} is the
158.30 * string returned by {@link MBeanInfo#getClassName()} for the target
158.31 - * MBean,</li>
158.32 - * <li>{@code mbeanServerName} is the
158.33 - * {@linkplain MBeanServerFactory#getMBeanServerName name of the
158.34 - * MBean Server} in which the target MBean is registered. This is the
158.35 - * value returned by {@link MBeanServerFactory#getMBeanServerName
158.36 - * MBeanServerFactory.getMBeanServerName(MBeanServer)}, and
158.37 - * is usually the {@code mbeanServerName} parameter that was supplied
158.38 - * to the {@link
158.39 - * MBeanServerFactory#createNamedMBeanServer(String,String)
158.40 - * createNamedMBeanServer} or {@link
158.41 - * MBeanServerFactory#newNamedMBeanServer(String,String) newNamedMBeanServer}
158.42 - * methods of the {@link MBeanServerFactory} when the MBeanServer was created,
158.43 - * or {@value javax.management.MBeanServerFactory#DEFAULT_MBEANSERVER_NAME} if
158.44 - * no name was supplied.
158.45 - * </li></ul>
158.46 + * MBean.</p>
158.47 *
158.48 * <p>If a security check fails, the method throws {@link
158.49 * SecurityException}.</p>
158.50 @@ -110,87 +90,79 @@
158.51 *
158.52 * <li><p>For the {@link #invoke invoke} method, the caller's
158.53 * permissions must imply {@link
158.54 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.55 - * MBeanPermission(mbeanServerName, className, operationName, name, "invoke")}.
158.56 - * </p>
158.57 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.58 + * MBeanPermission(className, operationName, name, "invoke")}.</p>
158.59 *
158.60 * <li><p>For the {@link #getAttribute getAttribute} method, the
158.61 * caller's permissions must imply {@link
158.62 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.63 - * MBeanPermission(mbeanServerName, className, attribute, name,
158.64 - * "getAttribute")}.</p>
158.65 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.66 + * MBeanPermission(className, attribute, name, "getAttribute")}.</p>
158.67 *
158.68 * <li><p>For the {@link #getAttributes getAttributes} method, the
158.69 * caller's permissions must imply {@link
158.70 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.71 - * MBeanPermission(mbeanServerName,className, null, name, "getAttribute")}.
158.72 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.73 + * MBeanPermission(className, null, name, "getAttribute")}.
158.74 * Additionally, for each attribute <em>a</em> in the {@link
158.75 * AttributeList}, if the caller's permissions do not imply {@link
158.76 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.77 - * MBeanPermission(mbeanServerName, className, <em>a</em>, name,
158.78 - * "getAttribute")}, the
158.79 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.80 + * MBeanPermission(className, <em>a</em>, name, "getAttribute")}, the
158.81 * MBean server will behave as if that attribute had not been in the
158.82 * supplied list.</p>
158.83 *
158.84 * <li><p>For the {@link #setAttribute setAttribute} method, the
158.85 * caller's permissions must imply {@link
158.86 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.87 - * MBeanPermission(mbeanServerName, className, attrName, name,
158.88 - * "setAttribute")}, where
158.89 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.90 + * MBeanPermission(className, attrName, name, "setAttribute")}, where
158.91 * <code>attrName</code> is {@link Attribute#getName()
158.92 * attribute.getName()}.</p>
158.93 *
158.94 * <li><p>For the {@link #setAttributes setAttributes} method, the
158.95 * caller's permissions must imply {@link
158.96 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.97 - * MBeanPermission(mbeanServerName, className, null, name, "setAttribute")}.
158.98 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.99 + * MBeanPermission(className, null, name, "setAttribute")}.
158.100 * Additionally, for each attribute <em>a</em> in the {@link
158.101 * AttributeList}, if the caller's permissions do not imply {@link
158.102 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.103 - * MBeanPermission(mbeanServerName, className, <em>a</em>, name,
158.104 - * "setAttribute")}, the
158.105 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.106 + * MBeanPermission(className, <em>a</em>, name, "setAttribute")}, the
158.107 * MBean server will behave as if that attribute had not been in the
158.108 * supplied list.</p>
158.109 *
158.110 * <li><p>For the <code>addNotificationListener</code> methods,
158.111 * the caller's permissions must imply {@link
158.112 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.113 - * MBeanPermission(mbeanServerName, className, null, name,
158.114 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.115 + * MBeanPermission(className, null, name,
158.116 * "addNotificationListener")}.</p>
158.117 *
158.118 * <li><p>For the <code>removeNotificationListener</code> methods,
158.119 * the caller's permissions must imply {@link
158.120 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.121 - * MBeanPermission(mbeanServerName, className, null, name,
158.122 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.123 + * MBeanPermission(className, null, name,
158.124 * "removeNotificationListener")}.</p>
158.125 *
158.126 * <li><p>For the {@link #getMBeanInfo getMBeanInfo} method, the
158.127 * caller's permissions must imply {@link
158.128 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.129 - * MBeanPermission(mbeanServerName, className, null, name, "getMBeanInfo")}.
158.130 - * </p>
158.131 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.132 + * MBeanPermission(className, null, name, "getMBeanInfo")}.</p>
158.133 *
158.134 * <li><p>For the {@link #getObjectInstance getObjectInstance} method,
158.135 * the caller's permissions must imply {@link
158.136 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.137 - * MBeanPermission(mbeanServerName, className, null, name,
158.138 - * "getObjectInstance")}.</p>
158.139 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.140 + * MBeanPermission(className, null, name, "getObjectInstance")}.</p>
158.141 *
158.142 * <li><p>For the {@link #isInstanceOf isInstanceOf} method, the
158.143 * caller's permissions must imply {@link
158.144 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.145 - * MBeanPermission(mbeanServerName, className, null, name, "isInstanceOf")}.
158.146 - * </p>
158.147 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.148 + * MBeanPermission(className, null, name, "isInstanceOf")}.</p>
158.149 *
158.150 * <li><p>For the {@link #queryMBeans queryMBeans} method, the
158.151 * caller's permissions must imply {@link
158.152 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.153 - * MBeanPermission(mbeanServerName, null, null, null, "queryMBeans")}.
158.154 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.155 + * MBeanPermission(null, null, null, "queryMBeans")}.
158.156 * Additionally, for each MBean <em>n</em> that matches <code>name</code>,
158.157 * if the caller's permissions do not imply {@link
158.158 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.159 - * MBeanPermission(mbeanServerName, className, null, <em>n</em>, "queryMBeans")},
158.160 - * the MBean server will behave as if that MBean did not exist.</p>
158.161 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.162 + * MBeanPermission(className, null, <em>n</em>, "queryMBeans")}, the
158.163 + * MBean server will behave as if that MBean did not exist.</p>
158.164 *
158.165 * <p>Certain query elements perform operations on the MBean server.
158.166 * If the caller does not have the required permissions for a given
158.167 @@ -208,10 +180,10 @@
158.168 *
158.169 * <li><p>For the {@link #getDomains getDomains} method, the caller's
158.170 * permissions must imply {@link
158.171 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.172 - * MBeanPermission(mbeanServerName, null, null, null, "getDomains")}.
158.173 - * Additionally, for each domain <var>d</var> in the returned array, if the
158.174 - * caller's permissions do not imply {@link
158.175 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.176 + * MBeanPermission(null, null, null, "getDomains")}. Additionally,
158.177 + * for each domain <var>d</var> in the returned array, if the caller's
158.178 + * permissions do not imply {@link
158.179 * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.180 * MBeanPermission(null, null, new ObjectName("<var>d</var>:x=x"),
158.181 * "getDomains")}, the domain is eliminated from the array. Here,
158.182 @@ -220,22 +192,21 @@
158.183 *
158.184 * <li><p>For the {@link #getClassLoader getClassLoader} method, the
158.185 * caller's permissions must imply {@link
158.186 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.187 - * MBeanPermission(mbeanServerName, className, null, loaderName,
158.188 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.189 + * MBeanPermission(className, null, loaderName,
158.190 * "getClassLoader")}.</p>
158.191 *
158.192 * <li><p>For the {@link #getClassLoaderFor getClassLoaderFor} method,
158.193 * the caller's permissions must imply {@link
158.194 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.195 - * MBeanPermission(mbeanServerName, className, null, mbeanName,
158.196 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.197 + * MBeanPermission(className, null, mbeanName,
158.198 * "getClassLoaderFor")}.</p>
158.199 *
158.200 * <li><p>For the {@link #getClassLoaderRepository
158.201 * getClassLoaderRepository} method, the caller's permissions must
158.202 * imply {@link
158.203 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.204 - * MBeanPermission(mbeanServerName, null, null, null,
158.205 - * "getClassLoaderRepository")}.</p>
158.206 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.207 + * MBeanPermission(null, null, null, "getClassLoaderRepository")}.</p>
158.208 *
158.209 * <li><p>For the deprecated <code>deserialize</code> methods, the
158.210 * required permissions are the same as for the methods that replace
158.211 @@ -243,15 +214,15 @@
158.212 *
158.213 * <li><p>For the <code>instantiate</code> methods, the caller's
158.214 * permissions must imply {@link
158.215 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.216 - * MBeanPermission(mbeanServerName, className, null, null, "instantiate")},
158.217 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.218 + * MBeanPermission(className, null, null, "instantiate")},
158.219 * where {@code className} is the name of the class which is to
158.220 * be instantiated.</p>
158.221 *
158.222 * <li><p>For the {@link #registerMBean registerMBean} method, the
158.223 * caller's permissions must imply {@link
158.224 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.225 - * MBeanPermission(mbeanServerName, className, null, name, "registerMBean")}.
158.226 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.227 + * MBeanPermission(className, null, name, "registerMBean")}.
158.228 *
158.229 * <p>If the <code>MBeanPermission</code> check succeeds, the MBean's
158.230 * class is validated by checking that its {@link
158.231 @@ -271,8 +242,8 @@
158.232 *
158.233 * <li><p>For the {@link #unregisterMBean unregisterMBean} method,
158.234 * the caller's permissions must imply {@link
158.235 - * MBeanPermission#MBeanPermission(String,String,String,ObjectName,String)
158.236 - * MBeanPermission(mbeanServerName, className, null, name, "unregisterMBean")}.
158.237 + * MBeanPermission#MBeanPermission(String,String,ObjectName,String)
158.238 + * MBeanPermission(className, null, name, "unregisterMBean")}.</p>
158.239 * </p>
158.240 *
158.241 * </ul>
158.242 @@ -351,14 +322,11 @@
158.243
158.244 /**
158.245 * <p>Registers a pre-existing object as an MBean with the MBean
158.246 - * server. If the object name given is null, the
158.247 - * MBean must provide its own name in one or both of two ways: by implementing the {@link
158.248 + * server. If the object name given is null, the MBean must
158.249 + * provide its own name by implementing the {@link
158.250 * javax.management.MBeanRegistration MBeanRegistration} interface
158.251 * and returning the name from the {@link
158.252 - * MBeanRegistration#preRegister preRegister} method; or by defining
158.253 - * an {@code objectNameTemplate} field in its {@link Descriptor},
158.254 - * typically using the {@link ObjectNameTemplate @ObjectNameTemplate}
158.255 - * annotation.</p>
158.256 + * MBeanRegistration#preRegister preRegister} method.
158.257 *
158.258 * <p>If this method successfully registers an MBean, a notification
158.259 * is sent as described <a href="#notif">above</a>.</p>
158.260 @@ -764,16 +732,13 @@
158.261 ReflectionException;
158.262
158.263 /**
158.264 - * <p>Return the {@link java.lang.ClassLoader} that was used for loading
158.265 - * the class of the named MBean. If the MBean implements the {@link
158.266 - * DynamicWrapperMBean} interface, then the returned value is the
158.267 - * result of the {@link DynamicWrapperMBean#getWrappedClassLoader()}
158.268 - * method.</p>
158.269 + * <p>Return the {@link java.lang.ClassLoader} that was used for
158.270 + * loading the class of the named MBean.</p>
158.271 *
158.272 * @param mbeanName The ObjectName of the MBean.
158.273 *
158.274 * @return The ClassLoader used for that MBean. If <var>l</var>
158.275 - * is the value specified by the rules above, and <var>r</var> is the
158.276 + * is the MBean's actual ClassLoader, and <var>r</var> is the
158.277 * returned value, then either:
158.278 *
158.279 * <ul>
159.1 --- a/src/share/classes/javax/management/MBeanServerConnection.java Mon Nov 23 10:04:47 2009 +0000
159.2 +++ b/src/share/classes/javax/management/MBeanServerConnection.java Wed Nov 25 11:08:25 2009 -0800
159.3 @@ -29,7 +29,6 @@
159.4 // java import
159.5 import java.io.IOException;
159.6 import java.util.Set;
159.7 -import javax.management.event.NotificationManager;
159.8
159.9
159.10 /**
159.11 @@ -40,20 +39,17 @@
159.12 *
159.13 * @since 1.5
159.14 */
159.15 -public interface MBeanServerConnection extends NotificationManager {
159.16 +public interface MBeanServerConnection {
159.17 /**
159.18 * <p>Instantiates and registers an MBean in the MBean server. The
159.19 * MBean server will use its {@link
159.20 * javax.management.loading.ClassLoaderRepository Default Loader
159.21 * Repository} to load the class of the MBean. An object name is
159.22 * associated with the MBean. If the object name given is null, the
159.23 - * MBean must provide its own name in one or both of two ways: by implementing the {@link
159.24 + * MBean must provide its own name by implementing the {@link
159.25 * javax.management.MBeanRegistration MBeanRegistration} interface
159.26 * and returning the name from the {@link
159.27 - * MBeanRegistration#preRegister preRegister} method; or by defining
159.28 - * an {@code objectNameTemplate} field in its {@link Descriptor},
159.29 - * typically using the {@link ObjectNameTemplate @ObjectNameTemplate}
159.30 - * annotation.</p>
159.31 + * MBeanRegistration#preRegister preRegister} method.</p>
159.32 *
159.33 * <p>This method is equivalent to {@link
159.34 * #createMBean(String,ObjectName,Object[],String[])
159.35 @@ -122,14 +118,11 @@
159.36 * class loader to be used is identified by its object name. An
159.37 * object name is associated with the MBean. If the object name of
159.38 * the loader is null, the ClassLoader that loaded the MBean
159.39 - * server will be used. If the object name given is null, the
159.40 - * MBean must provide its own name in one or both of two ways: by implementing the {@link
159.41 + * server will be used. If the MBean's object name given is null,
159.42 + * the MBean must provide its own name by implementing the {@link
159.43 * javax.management.MBeanRegistration MBeanRegistration} interface
159.44 * and returning the name from the {@link
159.45 - * MBeanRegistration#preRegister preRegister} method; or by defining
159.46 - * an {@code objectNameTemplate} field in its {@link Descriptor},
159.47 - * typically using the {@link ObjectNameTemplate @ObjectNameTemplate}
159.48 - * annotation.</p>
159.49 + * MBeanRegistration#preRegister preRegister} method.</p>
159.50 *
159.51 * <p>This method is equivalent to {@link
159.52 * #createMBean(String,ObjectName,ObjectName,Object[],String[])
159.53 @@ -205,13 +198,10 @@
159.54 * javax.management.loading.ClassLoaderRepository Default Loader
159.55 * Repository} to load the class of the MBean. An object name is
159.56 * associated with the MBean. If the object name given is null, the
159.57 - * MBean must provide its own name in one or both of two ways: by implementing the {@link
159.58 + * MBean must provide its own name by implementing the {@link
159.59 * javax.management.MBeanRegistration MBeanRegistration} interface
159.60 * and returning the name from the {@link
159.61 - * MBeanRegistration#preRegister preRegister} method; or by defining
159.62 - * an {@code objectNameTemplate} field in its {@link Descriptor},
159.63 - * typically using the {@link ObjectNameTemplate @ObjectNameTemplate}
159.64 - * annotation.</p>
159.65 + * MBeanRegistration#preRegister preRegister} method.
159.66 *
159.67 * @param className The class name of the MBean to be instantiated.
159.68 * @param name The object name of the MBean. May be null.
159.69 @@ -280,14 +270,11 @@
159.70 * class loader to be used is identified by its object name. An
159.71 * object name is associated with the MBean. If the object name of
159.72 * the loader is not specified, the ClassLoader that loaded the
159.73 - * MBean server will be used. If the object name given is null, the
159.74 - * MBean must provide its own name in one or both of two ways: by implementing the {@link
159.75 - * javax.management.MBeanRegistration MBeanRegistration} interface
159.76 - * and returning the name from the {@link
159.77 - * MBeanRegistration#preRegister preRegister} method; or by defining
159.78 - * an {@code objectNameTemplate} field in its {@link Descriptor},
159.79 - * typically using the {@link ObjectNameTemplate @ObjectNameTemplate}
159.80 - * annotation.</p>
159.81 + * MBean server will be used. If the MBean object name given is
159.82 + * null, the MBean must provide its own name by implementing the
159.83 + * {@link javax.management.MBeanRegistration MBeanRegistration}
159.84 + * interface and returning the name from the {@link
159.85 + * MBeanRegistration#preRegister preRegister} method.
159.86 *
159.87 * @param className The class name of the MBean to be instantiated.
159.88 * @param name The object name of the MBean. May be null.
159.89 @@ -436,17 +423,7 @@
159.90 * specified, all the MBeans registered will be retrieved.
159.91 * @param query The query expression to be applied for selecting
159.92 * MBeans. If null no query expression will be applied for
159.93 - * selecting MBeans. ObjectName patterns that may be contained in the
159.94 - * query expression will be
159.95 - * <a href="namespace/package-summary.html#NamespaceAndQueries"><!--
159.96 - * -->evaluated</a> in the context of the
159.97 - * {@link javax.management.namespace namespace}
159.98 - * in which the MBeans selected by {@code name} are registered.
159.99 - * Thus, in the {@code query} parameter, no ObjectName pattern containing a
159.100 - * namespace path can match any of the MBean names selected by {@code name}.
159.101 - * See the
159.102 - * <a href="namespace/package-summary.html#RejectedNamespacePatterns"><!--
159.103 - * -->namespaces documentation</a> for more details.
159.104 + * selecting MBeans.
159.105 *
159.106 * @return A set containing the <CODE>ObjectInstance</CODE>
159.107 * objects for the selected MBeans. If no MBean satisfies the
159.108 @@ -454,11 +431,6 @@
159.109 *
159.110 * @exception IOException A communication problem occurred when
159.111 * talking to the MBean server.
159.112 - * @exception RuntimeOperationsException Wraps a
159.113 - * <CODE>java.lang.IllegalArgumentException</CODE>: The <em>name</em>
159.114 - * parameter contains an invalid pattern. See the
159.115 - * <a href="namespace/package-summary.html#RejectedNamespacePatterns"><!--
159.116 - * -->namespaces documentation</a> for more details.
159.117 */
159.118 public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query)
159.119 throws IOException;
159.120 @@ -479,17 +451,7 @@
159.121 * specified, the name of all registered MBeans will be retrieved.
159.122 * @param query The query expression to be applied for selecting
159.123 * MBeans. If null no query expression will be applied for
159.124 - * selecting MBeans. ObjectName patterns that may be contained in the
159.125 - * query expression will be
159.126 - * <a href="namespace/package-summary.html#NamespaceAndQueries"><!--
159.127 - * -->evaluated</a> in the context of the
159.128 - * {@link javax.management.namespace namespace}
159.129 - * in which the MBeans slected by {@code name} are registered.
159.130 - * Thus, in the {@code query} parameter, no ObjectName pattern containing a
159.131 - * namespace path can match any of the MBean names selected by {@code name}.
159.132 - * See the
159.133 - * <a href="namespace/package-summary.html#RejectedNamespacePatterns"><!--
159.134 - * -->namespaces documentation</a> for more details.
159.135 + * selecting MBeans.
159.136 *
159.137 * @return A set containing the ObjectNames for the MBeans
159.138 * selected. If no MBean satisfies the query, an empty list is
159.139 @@ -497,11 +459,6 @@
159.140 *
159.141 * @exception IOException A communication problem occurred when
159.142 * talking to the MBean server.
159.143 - * @exception RuntimeOperationsException Wraps a
159.144 - * <CODE>java.lang.IllegalArgumentException</CODE>: The <em>name</em>
159.145 - * parameter contains an invalid pattern. See the
159.146 - * <a href="namespace/package-summary.html#RejectedNamespacePatterns"><!--
159.147 - * -->namespaces documentation</a> for more details.
159.148 */
159.149 public Set<ObjectName> queryNames(ObjectName name, QueryExp query)
159.150 throws IOException;
159.151 @@ -594,7 +551,8 @@
159.152 * else {
159.153 * {@code List<String>} missing = new {@code ArrayList<String>}(<!--
159.154 * -->{@link java.util.Arrays#asList Arrays.asList}(attrNames));
159.155 - * missing.removeAll(list.toMap().keySet());
159.156 + * for (Attribute a : list.asList())
159.157 + * missing.remove(a.getName());
159.158 * System.out.println("Did not retrieve: " + missing);
159.159 * }
159.160 * </pre>
159.161 @@ -681,9 +639,11 @@
159.162 * if (inputAttrs.size() == outputAttrs.size())
159.163 * System.out.println("All attributes were set successfully");
159.164 * else {
159.165 - * {@code List<String>} missing = new {@code ArrayList<String>}(<!--
159.166 - * -->inputAttrs.toMap().keySet());
159.167 - * missing.removeAll(outputAttrs.toMap().keySet());
159.168 + * {@code List<String>} missing = new {@code ArrayList<String>}();
159.169 + * for (Attribute a : inputAttrs.asList())
159.170 + * missing.add(a.getName());
159.171 + * for (Attribute a : outputAttrs.asList())
159.172 + * missing.remove(a.getName());
159.173 * System.out.println("Did not set: " + missing);
159.174 * }
159.175 * </pre>
159.176 @@ -809,7 +769,28 @@
159.177 public String[] getDomains()
159.178 throws IOException;
159.179
159.180 - // doc inherited from NotificationManager
159.181 + /**
159.182 + * <p>Adds a listener to a registered MBean.
159.183 + * Notifications emitted by the MBean will be forwarded to the listener.</p>
159.184 + *
159.185 + * @param name The name of the MBean on which the listener should
159.186 + * be added.
159.187 + * @param listener The listener object which will handle the
159.188 + * notifications emitted by the registered MBean.
159.189 + * @param filter The filter object. If filter is null, no
159.190 + * filtering will be performed before handling notifications.
159.191 + * @param handback The context to be sent to the listener when a
159.192 + * notification is emitted.
159.193 + *
159.194 + * @exception InstanceNotFoundException The MBean name provided
159.195 + * does not match any of the registered MBeans.
159.196 + * @exception IOException A communication problem occurred when
159.197 + * talking to the MBean server.
159.198 + *
159.199 + * @see #removeNotificationListener(ObjectName, NotificationListener)
159.200 + * @see #removeNotificationListener(ObjectName, NotificationListener,
159.201 + * NotificationFilter, Object)
159.202 + */
159.203 public void addNotificationListener(ObjectName name,
159.204 NotificationListener listener,
159.205 NotificationFilter filter,
159.206 @@ -926,13 +907,65 @@
159.207 throws InstanceNotFoundException, ListenerNotFoundException,
159.208 IOException;
159.209
159.210 - // doc inherited from NotificationManager
159.211 +
159.212 + /**
159.213 + * <p>Removes a listener from a registered MBean.</p>
159.214 + *
159.215 + * <P> If the listener is registered more than once, perhaps with
159.216 + * different filters or callbacks, this method will remove all
159.217 + * those registrations.
159.218 + *
159.219 + * @param name The name of the MBean on which the listener should
159.220 + * be removed.
159.221 + * @param listener The listener to be removed.
159.222 + *
159.223 + * @exception InstanceNotFoundException The MBean name provided
159.224 + * does not match any of the registered MBeans.
159.225 + * @exception ListenerNotFoundException The listener is not
159.226 + * registered in the MBean.
159.227 + * @exception IOException A communication problem occurred when
159.228 + * talking to the MBean server.
159.229 + *
159.230 + * @see #addNotificationListener(ObjectName, NotificationListener,
159.231 + * NotificationFilter, Object)
159.232 + */
159.233 public void removeNotificationListener(ObjectName name,
159.234 NotificationListener listener)
159.235 throws InstanceNotFoundException, ListenerNotFoundException,
159.236 IOException;
159.237
159.238 - // doc inherited from NotificationManager
159.239 + /**
159.240 + * <p>Removes a listener from a registered MBean.</p>
159.241 + *
159.242 + * <p>The MBean must have a listener that exactly matches the
159.243 + * given <code>listener</code>, <code>filter</code>, and
159.244 + * <code>handback</code> parameters. If there is more than one
159.245 + * such listener, only one is removed.</p>
159.246 + *
159.247 + * <p>The <code>filter</code> and <code>handback</code> parameters
159.248 + * may be null if and only if they are null in a listener to be
159.249 + * removed.</p>
159.250 + *
159.251 + * @param name The name of the MBean on which the listener should
159.252 + * be removed.
159.253 + * @param listener The listener to be removed.
159.254 + * @param filter The filter that was specified when the listener
159.255 + * was added.
159.256 + * @param handback The handback that was specified when the
159.257 + * listener was added.
159.258 + *
159.259 + * @exception InstanceNotFoundException The MBean name provided
159.260 + * does not match any of the registered MBeans.
159.261 + * @exception ListenerNotFoundException The listener is not
159.262 + * registered in the MBean, or it is not registered with the given
159.263 + * filter and handback.
159.264 + * @exception IOException A communication problem occurred when
159.265 + * talking to the MBean server.
159.266 + *
159.267 + * @see #addNotificationListener(ObjectName, NotificationListener,
159.268 + * NotificationFilter, Object)
159.269 + *
159.270 + */
159.271 public void removeNotificationListener(ObjectName name,
159.272 NotificationListener listener,
159.273 NotificationFilter filter,
159.274 @@ -986,12 +1019,6 @@
159.275 *
159.276 * <p>Otherwise, the result is false.</p>
159.277 *
159.278 - * <p>If the MBean implements the {@link DynamicWrapperMBean}
159.279 - * interface, then in the above rules X is the result of the MBean's {@link
159.280 - * DynamicWrapperMBean#getWrappedObject() getWrappedObject()} method and L
159.281 - * is the result of its {@link DynamicWrapperMBean#getWrappedClassLoader()
159.282 - * getWrappedClassLoader()} method.
159.283 - *
159.284 * @param name The <CODE>ObjectName</CODE> of the MBean.
159.285 * @param className The name of the class.
159.286 *
160.1 --- a/src/share/classes/javax/management/MBeanServerDelegate.java Mon Nov 23 10:04:47 2009 +0000
160.2 +++ b/src/share/classes/javax/management/MBeanServerDelegate.java Wed Nov 25 11:08:25 2009 -0800
160.3 @@ -41,7 +41,6 @@
160.4
160.5 /** The MBean server agent identification.*/
160.6 private String mbeanServerId ;
160.7 - private String mbeanServerName;
160.8
160.9 /** The NotificationBroadcasterSupport object that sends the
160.10 notifications */
160.11 @@ -71,7 +70,6 @@
160.12 public MBeanServerDelegate () {
160.13 stamp = getStamp();
160.14 broadcaster = new NotificationBroadcasterSupport() ;
160.15 - mbeanServerName=null;
160.16 }
160.17
160.18
160.19 @@ -90,99 +88,12 @@
160.20 "using \"localhost\" instead. Cause is: "+e);
160.21 localHost = "localhost";
160.22 }
160.23 - mbeanServerId =
160.24 - Util.insertMBeanServerName(localHost + "_" + stamp,
160.25 - mbeanServerName);
160.26 + mbeanServerId = localHost + "_" + stamp;
160.27 }
160.28 return mbeanServerId;
160.29 }
160.30
160.31 /**
160.32 - * The name of the MBeanServer.
160.33 - * @return The name of the MBeanServer, or {@value
160.34 - * javax.management.MBeanServerFactory#DEFAULT_MBEANSERVER_NAME} if no
160.35 - * name was specified.
160.36 - *
160.37 - * @since 1.7
160.38 - * @see #setMBeanServerName
160.39 - */
160.40 - public synchronized String getMBeanServerName() {
160.41 - if (Util.isMBeanServerNameUndefined(mbeanServerName))
160.42 - return MBeanServerFactory.DEFAULT_MBEANSERVER_NAME;
160.43 - return mbeanServerName;
160.44 - }
160.45 -
160.46 - /**
160.47 - * Sets the name of the MBeanServer. The name will be embedded into the
160.48 - * {@link #getMBeanServerId MBeanServerId} using the following format:<br>
160.49 - * {@code mbeanServerId: <mbeanServerId>;mbeanServerName=<mbeanServerName>}
160.50 - * <p>The characters {@code ':'} (colon), {@code ';'} (semicolon ),
160.51 - * {@code '*'} (star) and {@code '?'} (question mark) are not legal in an
160.52 - * MBean Server name.</p>
160.53 - * <p>For instance, if the {@code mbeanServerName} provided is
160.54 - * {@code "com.mycompany.myapp.server1"}, and the original
160.55 - * {@code MBeanServerId} was {@code "myhost_1213353064145"},
160.56 - * then {@code mbeanServerName} will be
160.57 - * embedded in the {@code MBeanServerId} - and the new value of the
160.58 - * {@code MBeanServerId} will be:
160.59 - * </p>
160.60 - * <pre>
160.61 - * "myhost_1213353064145;mbeanServerName=com.mycompany.myapp.server1"
160.62 - * </pre>
160.63 - * <p>Note: The {@code mbeanServerName} is usually set by the
160.64 - * {@code MBeanServerFactory}. It is set only once, before the
160.65 - * MBean Server is returned by the factory. Once the MBean Server name is
160.66 - * set, it is not possible to change it.
160.67 - * </p>
160.68 - * @param mbeanServerName The MBeanServer name.
160.69 - * @throws IllegalArgumentException if the MBeanServerName is already set
160.70 - * to a different value, or if the provided name contains
160.71 - * illegal characters, or if the provided name is {@code ""}
160.72 - * (the empty string) or "-" (dash).
160.73 - * @throws UnsupportedOperationException if this object is of a legacy
160.74 - * subclass of MBeanServerDelegate which overrides {@link
160.75 - * #getMBeanServerId()}
160.76 - * in a way that doesn't support setting an MBeanServer name.
160.77 - * @see MBeanServerFactory#getMBeanServerName
160.78 - * @since 1.7
160.79 - */
160.80 - public synchronized void setMBeanServerName(String mbeanServerName) {
160.81 - // Sets the name on the delegate. For complex backward
160.82 - // compatibility reasons it is not possible to give the
160.83 - // name to the MBeanServerDelegate constructor.
160.84 - //
160.85 - // The method setMBeanServerName() will call getMBeanServerId()
160.86 - // to check that the name is accurately set in the MBeanServerId.
160.87 - // If not (which could happen if a custom MBeanServerDelegate
160.88 - // implementation overrides getMBeanServerId() and was not updated
160.89 - // with respect to JMX 2.0 spec), this method will throw an
160.90 - // IllegalStateException...
160.91 -
160.92 - // will fail if mbeanServerName is illegal
160.93 - final String name = Util.checkServerName(mbeanServerName);
160.94 -
160.95 - // can only set mbeanServerDelegate once.
160.96 - if (this.mbeanServerName != null && !this.mbeanServerName.equals(name))
160.97 - throw new IllegalArgumentException(
160.98 - "MBeanServerName already set to a different value");
160.99 -
160.100 - this.mbeanServerName = name;
160.101 -
160.102 - // will fail if mbeanServerId already has a different mbeanServerName
160.103 - mbeanServerId =
160.104 - Util.insertMBeanServerName(getMBeanServerId(),name);
160.105 -
160.106 - // check that we don't have a subclass which overrides
160.107 - // getMBeanServerId() without setting mbeanServerName
160.108 - if (!name.equals(
160.109 - Util.extractMBeanServerName(getMBeanServerId())))
160.110 - throw new UnsupportedOperationException(
160.111 - "Can't set MBeanServerName in MBeanServerId - " +
160.112 - "unsupported by "+this.getClass().getName()+"?");
160.113 - // OK: at this point we know that we have correctly set mbeanServerName.
160.114 - }
160.115 -
160.116 - /**
160.117 * Returns the full name of the JMX specification implemented
160.118 * by this product.
160.119 *
160.120 @@ -304,7 +215,7 @@
160.121 * @since 1.6
160.122 */
160.123 public static final ObjectName DELEGATE_NAME =
160.124 - ObjectName.valueOf("JMImplementation:type=MBeanServerDelegate");
160.125 + Util.newObjectName("JMImplementation:type=MBeanServerDelegate");
160.126
160.127 /* Return a timestamp that is monotonically increasing even if
160.128 System.currentTimeMillis() isn't (for example, if you call this
161.1 --- a/src/share/classes/javax/management/MBeanServerFactory.java Mon Nov 23 10:04:47 2009 +0000
161.2 +++ b/src/share/classes/javax/management/MBeanServerFactory.java Wed Nov 25 11:08:25 2009 -0800
161.3 @@ -29,11 +29,9 @@
161.4 import static com.sun.jmx.defaults.JmxProperties.JMX_INITIAL_BUILDER;
161.5 import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
161.6 import com.sun.jmx.mbeanserver.GetPropertyAction;
161.7 -import com.sun.jmx.mbeanserver.Util;
161.8 import java.security.AccessController;
161.9 import java.security.Permission;
161.10 import java.util.ArrayList;
161.11 -import java.util.List;
161.12 import java.util.logging.Level;
161.13 import javax.management.loading.ClassLoaderRepository;
161.14
161.15 @@ -83,53 +81,10 @@
161.16 * returned by the default MBeanServerBuilder implementation, for the purpose
161.17 * of e.g. adding an additional security layer.</p>
161.18 *
161.19 - * <p id="MBeanServerName">Since version 2.0 of the JMX API, when creating
161.20 - * an MBeanServer,
161.21 - * it is possible to specify an {@linkplain #getMBeanServerName
161.22 - * MBean Server name}.
161.23 - * To create an MBean Server with a name, the MBeanServerFactory provides two
161.24 - * new methods:</p>
161.25 - * <ul><li>{@link #createNamedMBeanServer
161.26 - * createNamedMBeanServer(mbeanServerName, defaultDomain)}: creates a named
161.27 - * MBeanServer and keeps an internal reference to the created object. The
161.28 - * MBeanServer can be later retrieved using {@link #findMBeanServer
161.29 - * findMBeanServer(mbeanServerId)} or
161.30 - * {@link #findMBeanServerByName findMBeanServerByName(mbeanServerName)}, and
161.31 - * can be released through {@link
161.32 - * #releaseMBeanServer releaseMBeanServer(mbeanServer)}.</li>
161.33 - * <li>{@link #newNamedMBeanServer
161.34 - * newNamedMBeanServer(mbeanServerName, defaultDomain)}:
161.35 - * creates a named MBeanServer without keeping any internal reference to the
161.36 - * named server.</li>
161.37 - * </ul>
161.38 - * <p>The name of the MBeanServer is stored in the
161.39 - * {@linkplain MBeanServerDelegate MBean Server delegate MBean}
161.40 - * and is embedded in its {@link MBeanServerDelegate#getMBeanServerId
161.41 - * MBeanServerId} attribute.</p>
161.42 - * <p>The name of the MBeanServer is particularly useful when
161.43 - * <a href="MBeanServer.html#security">MBean permissions</a> are checked:
161.44 - * it makes it
161.45 - * possible to distinguish between an MBean named "X" in MBeanServer named
161.46 - * "M1", and another MBean of the same name "X" in another MBeanServer named
161.47 - * "M2".</p>
161.48 - * <p>When naming MBean servers it is recommended to use a name that starts
161.49 - * with a Java package name. It is also recommended that the default domain and
161.50 - * the MBeanServer name be the same.</p>
161.51 - *
161.52 * @since 1.5
161.53 */
161.54 public class MBeanServerFactory {
161.55
161.56 - /**
161.57 - * The <a href="#MBeanServerName">MBean Server name</a> that will be
161.58 - * checked by a <a href="MBeanServer.html#security">permission you need</a>
161.59 - * when checking access to an MBean registered in an MBeanServer for
161.60 - * which no MBeanServer name was specified.
161.61 - *
161.62 - * @since 1.7
161.63 - */
161.64 - public final static String DEFAULT_MBEANSERVER_NAME = "default";
161.65 -
161.66 /*
161.67 * There are no instances of this class so don't generate the
161.68 * default public constructor.
161.69 @@ -268,78 +223,13 @@
161.70 * <code>javax.management.builder.initial</code> exists and can be
161.71 * instantiated but is not assignment compatible with {@link
161.72 * MBeanServerBuilder}.
161.73 - *
161.74 - * @see #createNamedMBeanServer
161.75 */
161.76 public static MBeanServer createMBeanServer(String domain) {
161.77 - return createMBeanServer(null,domain);
161.78 - }
161.79 + checkPermission("createMBeanServer");
161.80
161.81 - /**
161.82 - * <p>Return a new object implementing the {@link MBeanServer}
161.83 - * interface with the specified
161.84 - * <a href="#MBeanServerName">MBean Server name</a>
161.85 - * and default domain name. The given MBean server name
161.86 - * is used in <a href="MBeanServer.html#security">security checks</a>, and
161.87 - * can also be used to {@linkplain #findMBeanServerByName(java.lang.String)
161.88 - * find an MBeanServer by name}. The given
161.89 - * domain name is used as the domain part in the ObjectName of
161.90 - * MBeans when the domain is specified by the user is null.</p>
161.91 - *
161.92 - * <p>The MBeanServer reference is internally kept. This will
161.93 - * allow <CODE>findMBeanServer</CODE> to return a reference to
161.94 - * this MBeanServer object.</p>
161.95 - *
161.96 - * @param mbeanServerName the name for the created
161.97 - * MBeanServer. This is the name that will be included in the
161.98 - * {@linkplain MBeanPermission permission you need} when checking
161.99 - * <a href="MBeanServer.html#security">MBean Permissions</a> for accessing
161.100 - * an MBean registered in the returned MBeanServer. The characters
161.101 - * {@code ':'} (colon), {@code ';'} (semicolon), {@code '*'} (star)
161.102 - * and {@code '?'} are not legal.
161.103 - * It is recommended that the {@code mbeanServerName}
161.104 - * be unique in the context of a JVM, and in the form of a java package
161.105 - * identifier. If {@code mbeanServerName} is {@code null} then the created
161.106 - * MBean Server has no name - and {@value #DEFAULT_MBEANSERVER_NAME} is used.
161.107 - * Calling {@code createNamedMBeanServer(null,domain)} is equivalent
161.108 - * to calling {@link #createMBeanServer(String) createMBeanServer(domain)}.
161.109 - *
161.110 - * @param domain the default domain name for the created
161.111 - * MBeanServer. This is the value that will be returned by {@link
161.112 - * MBeanServer#getDefaultDomain}. If a non null mbeanServerName is given,
161.113 - * it is recommended to pass the same value as default domain.
161.114 - *
161.115 - * @return the newly created MBeanServer.
161.116 - *
161.117 - * @exception SecurityException if there is a SecurityManager and
161.118 - * the caller's permissions do not include or imply <code>{@link
161.119 - * MBeanServerPermission}("createMBeanServer")</code>.
161.120 - *
161.121 - * @exception JMRuntimeException if the property
161.122 - * <code>javax.management.builder.initial</code> exists but the
161.123 - * class it names cannot be instantiated through a public
161.124 - * no-argument constructor; or if the instantiated builder returns
161.125 - * null from its {@link MBeanServerBuilder#newMBeanServerDelegate
161.126 - * newMBeanServerDelegate} or {@link
161.127 - * MBeanServerBuilder#newMBeanServer newMBeanServer} methods.
161.128 - *
161.129 - * @exception ClassCastException if the property
161.130 - * <code>javax.management.builder.initial</code> exists and can be
161.131 - * instantiated but is not assignment compatible with {@link
161.132 - * MBeanServerBuilder}.
161.133 - *
161.134 - * @exception IllegalArgumentException if the specified
161.135 - * {@code mbeanServerName} is empty, or is {@code "-"}, or contains a
161.136 - * character which is not legal.
161.137 - *
161.138 - * @exception UnsupportedOperationException if the specified
161.139 - * {@code mbeanServerName} cannot be set.
161.140 - *
161.141 - * @since 1.7
161.142 - */
161.143 - public static MBeanServer createNamedMBeanServer(String mbeanServerName,
161.144 - String domain) {
161.145 - return createMBeanServer(mbeanServerName, domain);
161.146 + final MBeanServer mBeanServer = newMBeanServer(domain);
161.147 + addMBeanServer(mBeanServer);
161.148 + return mBeanServer;
161.149 }
161.150
161.151 /**
161.152 @@ -418,88 +308,6 @@
161.153 * MBeanServerBuilder}.
161.154 */
161.155 public static MBeanServer newMBeanServer(String domain) {
161.156 - return newMBeanServer(null,domain);
161.157 - }
161.158 -
161.159 - /**
161.160 - * <p>Return a new object implementing the MBeanServer interface
161.161 - * with the specified <a href="#MBeanServerName">MBean server name</a>
161.162 - * and default domain name, without keeping an
161.163 - * internal reference to this new object. The given MBean server name
161.164 - * is used in <a href="MBeanServer.html#security">security checks</a>.
161.165 - * The given domain name
161.166 - * is used as the domain part in the ObjectName of MBeans when the
161.167 - * domain is specified by the user is null.</p>
161.168 - *
161.169 - * <p>No reference is kept. <CODE>findMBeanServer</CODE> and
161.170 - * <CODE>findMBeanServerByName</CODE> will not
161.171 - * be able to return a reference to this MBeanServer object, but
161.172 - * the garbage collector will be able to remove the MBeanServer
161.173 - * object when it is no longer referenced.</p>
161.174 - *
161.175 - * @param mbeanServerName the name for the created
161.176 - * MBeanServer. This is the name that will be included in the
161.177 - * {@linkplain MBeanPermission permission you need} when checking
161.178 - * <a href="MBeanServer.html#security">MBean Permissions</a> for accessing
161.179 - * an MBean registered in the returned MBeanServer. The characters
161.180 - * {@code ':'} (colon), {@code ';'} (semicolon), {@code '*'} (star)
161.181 - * and {@code '?'} are not legal.
161.182 - * It is recommended that the mbeanServerName
161.183 - * be unique in the context of a JVM, and in the form of a java package
161.184 - * identifier. If {@code mbeanServerName} is {@code null} then the created
161.185 - * MBean Server has no name - and {@value #DEFAULT_MBEANSERVER_NAME} is used.
161.186 - * Calling {@code newNamedMBeanServer(null,domain)} is equivalent
161.187 - * to calling {@link #newMBeanServer(String) newMBeanServer(domain)}.
161.188 - *
161.189 - * @param domain the default domain name for the created
161.190 - * MBeanServer. This is the value that will be returned by {@link
161.191 - * MBeanServer#getDefaultDomain}.
161.192 - *
161.193 - * @return the newly created MBeanServer.
161.194 - *
161.195 - * @exception SecurityException if there is a SecurityManager and the
161.196 - * caller's permissions do not include or imply <code>{@link
161.197 - * MBeanServerPermission}("newMBeanServer")</code>.
161.198 - *
161.199 - * @exception JMRuntimeException if the property
161.200 - * <code>javax.management.builder.initial</code> exists but the
161.201 - * class it names cannot be instantiated through a public
161.202 - * no-argument constructor; or if the instantiated builder returns
161.203 - * null from its {@link MBeanServerBuilder#newMBeanServerDelegate
161.204 - * newMBeanServerDelegate} or {@link
161.205 - * MBeanServerBuilder#newMBeanServer newMBeanServer} methods.
161.206 - *
161.207 - * @exception ClassCastException if the property
161.208 - * <code>javax.management.builder.initial</code> exists and can be
161.209 - * instantiated but is not assignment compatible with {@link
161.210 - * MBeanServerBuilder}.
161.211 - *
161.212 - * @exception IllegalArgumentException if the specified
161.213 - * {@code mbeanServerName} is empty, or is {@code "-"},
161.214 - * or contains a character which is not legal.
161.215 - *
161.216 - * @exception UnsupportedOperationException if the specified
161.217 - * {@code mbeanServerName} cannot be set.
161.218 - *
161.219 - * @since 1.7
161.220 - */
161.221 - public static MBeanServer newNamedMBeanServer(String mbeanServerName,
161.222 - String domain) {
161.223 - return newMBeanServer(mbeanServerName, domain);
161.224 - }
161.225 -
161.226 - private static MBeanServer createMBeanServer(String mbeanServerName,
161.227 - String domain) {
161.228 - checkPermission("createMBeanServer");
161.229 -
161.230 - final MBeanServer mBeanServer =
161.231 - newMBeanServer(mbeanServerName,domain);
161.232 - addMBeanServer(mBeanServer);
161.233 - return mBeanServer;
161.234 - }
161.235 -
161.236 - private static MBeanServer newMBeanServer(String mbeanServerName,
161.237 - String domain) {
161.238 checkPermission("newMBeanServer");
161.239
161.240 // Get the builder. Creates a new one if necessary.
161.241 @@ -516,22 +324,6 @@
161.242 "returned null";
161.243 throw new JMRuntimeException(msg);
161.244 }
161.245 -
161.246 - // Sets the name on the delegate. For complex backward
161.247 - // compatibility reasons it is not possible to give the
161.248 - // name to the MBeanServerDelegate constructor.
161.249 - //
161.250 - // The method setMBeanServerName() will call getMBeanServerId()
161.251 - // to check that the name is accurately set in the MBeanServerId.
161.252 - // If not (which could happen if a custom MBeanServerDelegate
161.253 - // implementation overrides getMBeanServerId() and was not updated
161.254 - // with respect to JMX 2.0 spec, this method will throw an
161.255 - // IllegalStateException...
161.256 - //
161.257 - if (!Util.isMBeanServerNameUndefined(mbeanServerName)) {
161.258 - delegate.setMBeanServerName(mbeanServerName);
161.259 - }
161.260 -
161.261 final MBeanServer mbeanServer =
161.262 mbsBuilder.newMBeanServer(domain,null,delegate);
161.263 if (mbeanServer == null) {
161.264 @@ -539,20 +331,6 @@
161.265 "MBeanServerBuilder.newMBeanServer() returned null";
161.266 throw new JMRuntimeException(msg);
161.267 }
161.268 -
161.269 - // double check that the MBeanServer name is correctly set.
161.270 - // "*" might mean that the caller doesn't have the permission
161.271 - // to see the MBeanServer name.
161.272 - //
161.273 - final String mbsName = Util.getMBeanServerSecurityName(mbeanServer);
161.274 - if (!mbsName.equals(Util.checkServerName(mbeanServerName))
161.275 - && !mbsName.equals("*")) {
161.276 - throw new UnsupportedOperationException(
161.277 - "can't create MBeanServer with name \""+
161.278 - mbeanServerName+"\" using "+
161.279 - builder.getClass().getName());
161.280 - }
161.281 -
161.282 return mbeanServer;
161.283 }
161.284 }
161.285 @@ -594,96 +372,6 @@
161.286 }
161.287
161.288 /**
161.289 - * <p>Returns a list of registered MBeanServer objects with the given name. A
161.290 - * registered MBeanServer object is one that was created by one of
161.291 - * the <code>createMBeanServer</code> or <code>createNamedMBeanServer</code>
161.292 - * methods and not subsequently released with <code>releaseMBeanServer</code>.</p>
161.293 - * <p>See the section about <a href="#MBeanServerName">MBean Server names</a>
161.294 - * above.</p>
161.295 - *
161.296 - * @param mbeanServerName The name of the MBeanServer to
161.297 - * retrieve. If this parameter is null, all registered MBeanServers
161.298 - * in this JVM are returned.
161.299 - * Otherwise, only those MBeanServers that have a name
161.300 - * matching <code>mbeanServerName</code> are returned: this
161.301 - * parameter can be a pattern, where {@code '*'} matches any
161.302 - * sequence of characters and {@code '?'} matches any character.<br>
161.303 - * The name of an MBeanServer, if specified, is embedded in the
161.304 - * <code>MBeanServerId</code> attribute of its delegate MBean:
161.305 - * this method will parse the <code>MBeanServerId</code> to get the
161.306 - * MBeanServer name. If this parameter is equal to {@code "*"} then
161.307 - * all registered MBeanServers in this JVM are returned, whether they have
161.308 - * a name or not: {@code findMBeanServerByName(null)},
161.309 - * {@code findMBeanServerByName("*")} and {@code findMBeanServer(null)},
161.310 - * are equivalent. It is also possible to get all MBeanServers for which
161.311 - * no name was specified by calling <code>findMBeanServerByName({@value
161.312 - * #DEFAULT_MBEANSERVER_NAME})</code>.
161.313 - *
161.314 - * @return A list of MBeanServer objects.
161.315 - *
161.316 - * @exception SecurityException if there is a SecurityManager and the
161.317 - * caller's permissions do not include or imply <code>{@link
161.318 - * MBeanServerPermission}("findMBeanServer")</code>.
161.319 - *
161.320 - * @see #getMBeanServerName(MBeanServer)
161.321 - * @since 1.7
161.322 - */
161.323 - public synchronized static
161.324 - List<MBeanServer> findMBeanServerByName(String mbeanServerName) {
161.325 -
161.326 - checkPermission("findMBeanServer");
161.327 -
161.328 - if (mbeanServerName==null || "*".equals(mbeanServerName))
161.329 - return new ArrayList<MBeanServer>(mBeanServerList);
161.330 -
161.331 - // noname=true iff we are looking for MBeanServers for which no name
161.332 - // were specified.
161.333 - ArrayList<MBeanServer> result = new ArrayList<MBeanServer>();
161.334 - for (MBeanServer mbs : mBeanServerList) {
161.335 - final String name = Util.getMBeanServerSecurityName(mbs);
161.336 - if (Util.wildmatch(name, mbeanServerName)) result.add(mbs);
161.337 - }
161.338 - return result;
161.339 - }
161.340 -
161.341 - /**
161.342 - * Returns the name of the MBeanServer embedded in the MBeanServerId of
161.343 - * the given {@code server}. If the given MBeanServerId doesn't contain
161.344 - * any name, {@value #DEFAULT_MBEANSERVER_NAME} is returned.
161.345 - * The MBeanServerId is expected to be of the form:
161.346 - * {@code *[;mbeanServerName=<mbeanServerName>[;*]]}
161.347 - * <br>where {@code *} denotes any sequence of characters, and {@code [ ]}
161.348 - * indicate optional parts.
161.349 - * </p>
161.350 - * <p>For instance, if an MBeanServer is created using {@link
161.351 - * #createNamedMBeanServer(java.lang.String, java.lang.String)
161.352 - * server =
161.353 - * MBeanServerFactory.createNamedMBeanServer("com.mycompany.myapp.server1",
161.354 - * null)} then {@code MBeanServerFactory.getMBeanServerName(server)}
161.355 - * will return {@code "com.mycompany.myapp.server1"} and
161.356 - * <code>server.getAttribute({@link
161.357 - * javax.management.MBeanServerDelegate#DELEGATE_NAME
161.358 - * MBeanServerDelegate.DELEGATE_NAME}, "MBeanServerId")</code> will return
161.359 - * something like
161.360 - * {@code "myhost_1213353064145;mbeanServerName=com.mycompany.myapp.server1"}.
161.361 - * </p>
161.362 - * <p>See the section about <a href="#MBeanServerName">MBean Server names</a>
161.363 - * above.</p>
161.364 - * @param server A named (or unnamed) MBeanServer.
161.365 - * @return the name of the MBeanServer if found, or
161.366 - * {@value #DEFAULT_MBEANSERVER_NAME} if no name is
161.367 - * present in its MBeanServerId, or "*" if its
161.368 - * MBeanServerId couldn't be obtained. Returning "*" means that
161.369 - * only {@link MBeanPermission}s that allow all MBean Server names
161.370 - * will apply to this MBean Server.
161.371 - * @see MBeanServerDelegate
161.372 - * @since 1.7
161.373 - */
161.374 - public static String getMBeanServerName(MBeanServer server) {
161.375 - return Util.getMBeanServerSecurityName(server);
161.376 - }
161.377 -
161.378 - /**
161.379 * Return the ClassLoaderRepository used by the given MBeanServer.
161.380 * This method is equivalent to {@link
161.381 * MBeanServer#getClassLoaderRepository() server.getClassLoaderRepository()}.
162.1 --- a/src/share/classes/javax/management/MBeanServerInvocationHandler.java Mon Nov 23 10:04:47 2009 +0000
162.2 +++ b/src/share/classes/javax/management/MBeanServerInvocationHandler.java Wed Nov 25 11:08:25 2009 -0800
162.3 @@ -33,9 +33,6 @@
162.4 import java.lang.reflect.Proxy;
162.5 import java.util.Arrays;
162.6 import java.util.WeakHashMap;
162.7 -import javax.management.openmbean.MXBeanMappingFactory;
162.8 -
162.9 -import static javax.management.JMX.MBeanOptions;
162.10
162.11 /**
162.12 * <p>{@link InvocationHandler} that forwards methods in an MBean's
162.13 @@ -114,7 +111,7 @@
162.14 public MBeanServerInvocationHandler(MBeanServerConnection connection,
162.15 ObjectName objectName) {
162.16
162.17 - this(connection, objectName, null);
162.18 + this(connection, objectName, false);
162.19 }
162.20
162.21 /**
162.22 @@ -141,14 +138,6 @@
162.23 public MBeanServerInvocationHandler(MBeanServerConnection connection,
162.24 ObjectName objectName,
162.25 boolean isMXBean) {
162.26 - this(connection, objectName, isMXBean ? MBeanOptions.MXBEAN : null);
162.27 - }
162.28 -
162.29 - public MBeanServerInvocationHandler(MBeanServerConnection connection,
162.30 - ObjectName objectName,
162.31 - MBeanOptions options) {
162.32 - if (options == null)
162.33 - options = new MBeanOptions();
162.34 if (connection == null) {
162.35 throw new IllegalArgumentException("Null connection");
162.36 }
162.37 @@ -157,7 +146,7 @@
162.38 }
162.39 this.connection = connection;
162.40 this.objectName = objectName;
162.41 - this.options = options.canonical();
162.42 + this.isMXBean = isMXBean;
162.43 }
162.44
162.45 /**
162.46 @@ -193,16 +182,7 @@
162.47 * @since 1.6
162.48 */
162.49 public boolean isMXBean() {
162.50 - return options.isMXBean();
162.51 - }
162.52 -
162.53 - /**
162.54 - * <p>Return the {@link MBeanOptions} used for this proxy.</p>
162.55 - *
162.56 - * @return the MBeanOptions.
162.57 - */
162.58 - public MBeanOptions getMBeanOptions() {
162.59 - return options.uncanonical();
162.60 + return isMXBean;
162.61 }
162.62
162.63 /**
162.64 @@ -346,40 +326,30 @@
162.65 */
162.66 }
162.67
162.68 - private MXBeanProxy findMXBeanProxy(Class<?> mxbeanInterface) {
162.69 - MXBeanMappingFactory mappingFactory = options.getMXBeanMappingFactory();
162.70 + private static MXBeanProxy findMXBeanProxy(Class<?> mxbeanInterface) {
162.71 synchronized (mxbeanProxies) {
162.72 - ClassToProxy classToProxy = mxbeanProxies.get(mappingFactory);
162.73 - if (classToProxy == null) {
162.74 - classToProxy = new ClassToProxy();
162.75 - mxbeanProxies.put(mappingFactory, classToProxy);
162.76 + WeakReference<MXBeanProxy> proxyRef =
162.77 + mxbeanProxies.get(mxbeanInterface);
162.78 + MXBeanProxy p = (proxyRef == null) ? null : proxyRef.get();
162.79 + if (p == null) {
162.80 + try {
162.81 + p = new MXBeanProxy(mxbeanInterface);
162.82 + } catch (IllegalArgumentException e) {
162.83 + String msg = "Cannot make MXBean proxy for " +
162.84 + mxbeanInterface.getName() + ": " + e.getMessage();
162.85 + IllegalArgumentException iae =
162.86 + new IllegalArgumentException(msg, e.getCause());
162.87 + iae.setStackTrace(e.getStackTrace());
162.88 + throw iae;
162.89 + }
162.90 + mxbeanProxies.put(mxbeanInterface,
162.91 + new WeakReference<MXBeanProxy>(p));
162.92 }
162.93 - WeakReference<MXBeanProxy> wr = classToProxy.get(mxbeanInterface);
162.94 - MXBeanProxy p;
162.95 - if (wr != null) {
162.96 - p = wr.get();
162.97 - if (p != null)
162.98 - return p;
162.99 - }
162.100 - try {
162.101 - p = new MXBeanProxy(mxbeanInterface, mappingFactory);
162.102 - } catch (IllegalArgumentException e) {
162.103 - String msg = "Cannot make MXBean proxy for " +
162.104 - mxbeanInterface.getName() + ": " + e.getMessage();
162.105 - throw new IllegalArgumentException(msg, e.getCause());
162.106 - }
162.107 - classToProxy.put(mxbeanInterface, new WeakReference<MXBeanProxy>(p));
162.108 return p;
162.109 }
162.110 }
162.111 - private static final WeakHashMap<MXBeanMappingFactory, ClassToProxy>
162.112 - mxbeanProxies = newWeakHashMap();
162.113 - private static class ClassToProxy
162.114 - extends WeakHashMap<Class<?>, WeakReference<MXBeanProxy>> {}
162.115 -
162.116 - private static <K, V> WeakHashMap<K, V> newWeakHashMap() {
162.117 - return new WeakHashMap<K, V>();
162.118 - }
162.119 + private static final WeakHashMap<Class<?>, WeakReference<MXBeanProxy>>
162.120 + mxbeanProxies = new WeakHashMap<Class<?>, WeakReference<MXBeanProxy>>();
162.121
162.122 private Object invokeBroadcasterMethod(Object proxy, Method method,
162.123 Object[] args) throws Exception {
162.124 @@ -523,5 +493,5 @@
162.125
162.126 private final MBeanServerConnection connection;
162.127 private final ObjectName objectName;
162.128 - private final MBeanOptions options;
162.129 + private final boolean isMXBean;
162.130 }
163.1 --- a/src/share/classes/javax/management/MBeanServerNotification.java Mon Nov 23 10:04:47 2009 +0000
163.2 +++ b/src/share/classes/javax/management/MBeanServerNotification.java Wed Nov 25 11:08:25 2009 -0800
163.3 @@ -64,13 +64,13 @@
163.4 * mbeanServer.addNotificationListener(
163.5 * MBeanServerDelegate.DELEGATE_NAME, printListener, null, null);
163.6 * </pre>
163.7 + *
163.8 * <p id="group">
163.9 * An MBean which is not an {@link MBeanServerDelegate} may also emit
163.10 - * MBeanServerNotifications. In particular, a custom subclass of the
163.11 - * {@link javax.management.namespace.JMXDomain JMXDomain} MBean or a custom
163.12 - * subclass of the {@link javax.management.namespace.JMXNamespace JMXNamespace}
163.13 - * MBean may emit an MBeanServerNotification for a group of MBeans.<br>
163.14 - * An MBeanServerNotification emitted to denote the registration or
163.15 + * MBeanServerNotifications. In particular, there is a convention for
163.16 + * MBeans to emit an MBeanServerNotification for a group of MBeans.</p>
163.17 + *
163.18 + * <p>An MBeanServerNotification emitted to denote the registration or
163.19 * unregistration of a group of MBeans has the following characteristics:
163.20 * <ul><li>Its {@linkplain Notification#getType() notification type} is
163.21 * {@code "JMX.mbean.registered.group"} or
163.22 @@ -92,58 +92,6 @@
163.23 * declare them in their {@link MBeanInfo#getNotifications()
163.24 * MBeanNotificationInfo}.
163.25 * </p>
163.26 - * <P>
163.27 - * To receive a group MBeanServerNotification, you need to register a listener
163.28 - * with the MBean that emits it. For instance, assuming that the {@link
163.29 - * javax.management.namespace.JMXNamespace JMXNamespace} MBean handling
163.30 - * namespace {@code "foo"} has declared that it emits such a notification,
163.31 - * you will need to register your notification listener with that MBean, which
163.32 - * will be named {@link
163.33 - * javax.management.namespace.JMXNamespaces#getNamespaceObjectName(java.lang.String)
163.34 - * foo//:type=JMXNamespace}.
163.35 - * </p>
163.36 - * <p>The following code prints a message every time a group of MBean is
163.37 - * registered or unregistered in the namespace {@code "foo"}, assumimg its
163.38 - * {@link javax.management.namespace.JMXNamespace handler} supports
163.39 - * group MBeanServerNotifications:</p>
163.40 - *
163.41 - * <pre>
163.42 - * private static final NotificationListener printListener = new NotificationListener() {
163.43 - * public void handleNotification(Notification n, Object handback) {
163.44 - * if (!(n instanceof MBeanServerNotification)) {
163.45 - * System.out.println("Ignored notification of class " + n.getClass().getName());
163.46 - * return;
163.47 - * }
163.48 - * MBeanServerNotification mbsn = (MBeanServerNotification) n;
163.49 - * String what;
163.50 - * ObjectName[] names = null;
163.51 - * if (n.getType().equals(MBeanServerNotification.REGISTRATION_NOTIFICATION)) {
163.52 - * what = "MBean registered";
163.53 - * } else if (n.getType().equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION)) {
163.54 - * what = "MBean unregistered";
163.55 - * } else if (n.getType().equals(MBeanServerNotification.REGISTRATION_NOTIFICATION+".group")) {
163.56 - * what = "Group of MBeans registered matching";
163.57 - * if (mbsn.getUserData() instanceof ObjectName[])
163.58 - * names = (ObjectName[]) mbsn.getUserData();
163.59 - * } else if (n.getType().equals(MBeanServerNotification.UNREGISTRATION_NOTIFICATION+".group")) {
163.60 - * what = "Group of MBeans unregistered matching";
163.61 - * if (mbsn.getUserData() instanceof ObjectName[])
163.62 - * names = (ObjectName[]) mbsn.getUserData();
163.63 - * } else
163.64 - * what = "Unknown type " + n.getType();
163.65 - * System.out.println("Received MBean Server notification: " + what + ": " +
163.66 - * mbsn.getMBeanName());
163.67 - * if (names != null) {
163.68 - * for (ObjectName mb : names)
163.69 - * System.out.println("\t"+mb);
163.70 - * }
163.71 - * }
163.72 - * };
163.73 - *
163.74 - * ...
163.75 - * mbeanServer.addNotificationListener(
163.76 - * JMXNamespaces.getNamespaceObjectName("foo"), printListener, null, null);
163.77 - * </pre>
163.78 *
163.79 * @since 1.5
163.80 */
164.1 --- a/src/share/classes/javax/management/MXBean.java Mon Nov 23 10:04:47 2009 +0000
164.2 +++ b/src/share/classes/javax/management/MXBean.java Wed Nov 25 11:08:25 2009 -0800
164.3 @@ -27,7 +27,6 @@
164.4
164.5 import java.lang.annotation.Documented;
164.6 import java.lang.annotation.ElementType;
164.7 -import java.lang.annotation.Inherited;
164.8 import java.lang.annotation.Retention;
164.9 import java.lang.annotation.RetentionPolicy;
164.10 import java.lang.annotation.Target;
164.11 @@ -44,10 +43,6 @@
164.12 import javax.management.openmbean.CompositeDataSupport;
164.13 import javax.management.openmbean.CompositeDataView;
164.14 import javax.management.openmbean.CompositeType;
164.15 -import javax.management.openmbean.MXBeanMapping;
164.16 -import javax.management.openmbean.MXBeanMappingClass;
164.17 -import javax.management.openmbean.MXBeanMappingFactory;
164.18 -import javax.management.openmbean.MXBeanMappingFactoryClass;
164.19 import javax.management.openmbean.OpenDataException;
164.20 import javax.management.openmbean.OpenMBeanInfo;
164.21 import javax.management.openmbean.OpenType;
164.22 @@ -57,13 +52,11 @@
164.23 import javax.management.openmbean.TabularType;
164.24
164.25 /**
164.26 - <p>Annotation to mark a class or interface explicitly as being an MXBean,
164.27 - or as not being an MXBean. By default, an
164.28 + <p>Annotation to mark an interface explicitly as being an MXBean
164.29 + interface, or as not being an MXBean interface. By default, an
164.30 interface is an MXBean interface if its name ends with {@code
164.31 - MXBean}, as in {@code SomethingMXBean}. A class is never an MXBean by
164.32 - default.</p>
164.33 -
164.34 - <p>The following interfaces are MXBean interfaces:</p>
164.35 + MXBean}, as in {@code SomethingMXBean}. The following interfaces
164.36 + are MXBean interfaces:</p>
164.37
164.38 <pre>
164.39 public interface WhatsitMXBean {}
164.40 @@ -84,12 +77,7 @@
164.41 public interface MisleadingMXBean {}
164.42 </pre>
164.43
164.44 - <p>A class can be annotated with {@code @MXBean} to indicate that it
164.45 - is an MXBean. In this case, its methods should have <code>@{@link
164.46 - ManagedAttribute}</code> or <code>@{@link ManagedOperation}</code>
164.47 - annotations, as described for <code>@{@link MBean}</code>.</p>
164.48 -
164.49 - <h3 id="MXBean-spec">MXBean specification</h3>
164.50 + <h3 id="MXBean-spec">MXBean specification</a></h3>
164.51
164.52 <p>The MXBean concept provides a simple way to code an MBean
164.53 that only references a predefined set of types, the ones defined
164.54 @@ -486,11 +474,7 @@
164.55 from type <em>opendata(J)</em> to type <em>J</em>, a null value is
164.56 mapped to a null value.</p>
164.57
164.58 - <p>In addition to the default type mapping rules, you can specify
164.59 - custom type mappings, as described <a
164.60 - href="#custom">below</a>.</p>
164.61 -
164.62 - <p>The following table summarizes the default type mapping rules.</p>
164.63 + <p>The following table summarizes the type mapping rules.</p>
164.64
164.65 <table border="1" cellpadding="5">
164.66 <tr>
164.67 @@ -1051,77 +1035,6 @@
164.68 }
164.69 </pre>
164.70
164.71 - <p>Alternatively, you can define a custom mapping for your recursive
164.72 - type; see the next section.</p>
164.73 -
164.74 - <h3 id="custom">Custom MXBean type mappings</h3>
164.75 -
164.76 - <p>You can augment or replace the default type mappings described
164.77 - above with custom mappings. An example appears in the
164.78 - documentation for {@link MXBeanMapping}.</p>
164.79 -
164.80 - <p>If an MXBean uses custom mappings, then an MXBean proxy for
164.81 - that MXBean must use the same mappings for correct behavior.
164.82 - This requires more careful synchronization between client and
164.83 - server than is necessary with the default mappings. For example
164.84 - it typically requires the client to have the same implementation
164.85 - of any {@link MXBeanMapping} subclasses as the server. For this
164.86 - reason, custom mappings should be avoided if possible.</p>
164.87 -
164.88 - <p>Every MXBean has an associated {@link MXBeanMappingFactory}.
164.89 - Call this <code><em>f</em></code>. Then every type that appears
164.90 - in that MXBean has an associated {@link MXBeanMapping}
164.91 - determined by <code><em>f</em></code>. If the type is
164.92 - <code><em>J</em></code>, say, then the mapping is {@link
164.93 - MXBeanMappingFactory#mappingForType
164.94 - <em>f</em>.mappingForType}<code>(<em>J</em>,
164.95 - <em>f</em>)</code>.</p>
164.96 -
164.97 - <p>The {@code MXBeanMappingFactory} <code><em>f</em></code> for an
164.98 - MXBean is determined as follows.</p>
164.99 -
164.100 - <ul>
164.101 - <li><p>If a {@link JMX.MBeanOptions} argument is supplied to
164.102 - the {@link StandardMBean} constructor that makes an MXBean,
164.103 - or to the {@link JMX#newMBeanProxy(MBeanServerConnection,
164.104 - ObjectName, Class, JMX.MBeanOptions) JMX.newMBeanProxy}
164.105 - method, and the {@code MBeanOptions} object defines a non-null
164.106 - {@code MXBeanMappingFactory}, then that is the value of
164.107 - <code><em>f</em></code>.</p></li>
164.108 -
164.109 - <li><p>Otherwise, if the MXBean interface has an {@link
164.110 - MXBeanMappingFactoryClass} annotation, then that annotation
164.111 - must identify a subclass of {@code MXBeanMappingFactory}
164.112 - with a no-argument constructor. Then
164.113 - <code><em>f</em></code> is the result of calling this
164.114 - constructor. If the class does not have a no-argument
164.115 - constructor, or if calling the constructor produces an
164.116 - exception, then the MXBean is invalid and an attempt to
164.117 - register it in the MBean Server will produce a {@link
164.118 - NotCompliantMBeanException}.</p>
164.119 -
164.120 - <p>This annotation is not inherited from any parent
164.121 - interfaces. If an MXBean interface has this annotation,
164.122 - then usually any MXBean subinterfaces must repeat the same
164.123 - annotation for correct behavior.</p></li>
164.124 -
164.125 - <li><p>Otherwise, if the package in which the MXBean interface
164.126 - appears has an {@code MXBeanMappingFactoryClass} annotation,
164.127 - then <code><em>f</em></code> is determined as if that
164.128 - annotation appeared on the MXBean interface.</p></li>
164.129 -
164.130 - <li><p>Otherwise, <code><em>f</em></code> is the default mapping
164.131 - factory, {@link MXBeanMappingFactory#DEFAULT}.</p></li>
164.132 - </ul>
164.133 -
164.134 - <p>The default mapping factory recognizes the {@link
164.135 - MXBeanMappingClass} annotation on a class or interface. If
164.136 - <code><em>J</em></code> is a class or interface that has such an
164.137 - annotation, then the {@code MXBeanMapping} for
164.138 - <code><em>J</em></code> produced by the default mapping factory
164.139 - will be determined by the value of the annotation as described
164.140 - in its {@linkplain MXBeanMappingClass documentation}.</p>
164.141 -
164.142 <h3>MBeanInfo contents for an MXBean</h3>
164.143
164.144 <p>An MXBean is a type of Open MBean. However, for compatibility
164.145 @@ -1250,29 +1163,12 @@
164.146 appropriate), or <em>C</em> is true of <em>e</em>.{@link
164.147 Throwable#getCause() getCause()}".</p>
164.148
164.149 - @see MXBeanMapping
164.150 -
164.151 @since 1.6
164.152 */
164.153
164.154 -/*
164.155 - * This annotation is @Inherited because if an MXBean is defined as a
164.156 - * class using annotations, then its subclasses are also MXBeans.
164.157 - * For example:
164.158 - * @MXBean
164.159 - * public class Super {
164.160 - * @ManagedAttribute
164.161 - * public String getName() {...}
164.162 - * }
164.163 - * public class Sub extends Super {}
164.164 - * Here Sub is an MXBean.
164.165 - *
164.166 - * The @Inherited annotation has no effect when applied to an interface.
164.167 - */
164.168 @Documented
164.169 @Retention(RetentionPolicy.RUNTIME)
164.170 @Target(ElementType.TYPE)
164.171 -@Inherited
164.172 public @interface MXBean {
164.173 /**
164.174 True if the annotated interface is an MXBean interface.
165.1 --- a/src/share/classes/javax/management/ManagedAttribute.java Mon Nov 23 10:04:47 2009 +0000
165.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
165.3 @@ -1,64 +0,0 @@
165.4 -/*
165.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
165.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
165.7 - *
165.8 - * This code is free software; you can redistribute it and/or modify it
165.9 - * under the terms of the GNU General Public License version 2 only, as
165.10 - * published by the Free Software Foundation. Sun designates this
165.11 - * particular file as subject to the "Classpath" exception as provided
165.12 - * by Sun in the LICENSE file that accompanied this code.
165.13 - *
165.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
165.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
165.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
165.17 - * version 2 for more details (a copy is included in the LICENSE file that
165.18 - * accompanied this code).
165.19 - *
165.20 - * You should have received a copy of the GNU General Public License version
165.21 - * 2 along with this work; if not, write to the Free Software Foundation,
165.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
165.23 - *
165.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
165.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
165.26 - * have any questions.
165.27 - */
165.28 -
165.29 -package javax.management;
165.30 -
165.31 -import java.lang.annotation.Documented;
165.32 -import java.lang.annotation.ElementType;
165.33 -import java.lang.annotation.Retention;
165.34 -import java.lang.annotation.RetentionPolicy;
165.35 -import java.lang.annotation.Target;
165.36 -
165.37 -/**
165.38 - * <p>Indicates that a method in an MBean class defines an MBean attribute.
165.39 - * This annotation must be applied to a public method of a public class
165.40 - * that is itself annotated with an {@link MBean @MBean} or
165.41 - * {@link MXBean @MXBean} annotation, or inherits such an annotation from
165.42 - * a superclass.</p>
165.43 - *
165.44 - * <p>The annotated method must be a getter or setter. In other words,
165.45 - * it must look like one of the following...</p>
165.46 - *
165.47 - * <pre>
165.48 - * <i>T</i> get<i>Foo</i>()
165.49 - * void set<i>Foo</i>(<i>T</i> param)
165.50 - * </pre>
165.51 - *
165.52 - * <p>...where <i>{@code T}</i> is any type and <i>{@code Foo}</i> is the
165.53 - * name of the attribute. For any attribute <i>{@code Foo}</i>, if only
165.54 - * a {@code get}<i>{@code Foo}</i> method has a {@code ManagedAttribute}
165.55 - * annotation, then <i>{@code Foo}</i> is a read-only attribute. If only
165.56 - * a {@code set}<i>{@code Foo}</i> method has a {@code ManagedAttribute}
165.57 - * annotation, then <i>{@code Foo}</i> is a write-only attribute. If
165.58 - * both {@code get}<i>{@code Foo}</i> and {@code set}<i>{@code Foo}</i>
165.59 - * methods have the annotation, then <i>{@code Foo}</i> is a read-write
165.60 - * attribute. In this last case, the type <i>{@code T}</i> must be the
165.61 - * same in both methods.</p>
165.62 - */
165.63 -@Retention(RetentionPolicy.RUNTIME)
165.64 -@Target(ElementType.METHOD)
165.65 -@Documented
165.66 -public @interface ManagedAttribute {
165.67 -}
166.1 --- a/src/share/classes/javax/management/ManagedOperation.java Mon Nov 23 10:04:47 2009 +0000
166.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
166.3 @@ -1,67 +0,0 @@
166.4 -/*
166.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
166.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
166.7 - *
166.8 - * This code is free software; you can redistribute it and/or modify it
166.9 - * under the terms of the GNU General Public License version 2 only, as
166.10 - * published by the Free Software Foundation. Sun designates this
166.11 - * particular file as subject to the "Classpath" exception as provided
166.12 - * by Sun in the LICENSE file that accompanied this code.
166.13 - *
166.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
166.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
166.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
166.17 - * version 2 for more details (a copy is included in the LICENSE file that
166.18 - * accompanied this code).
166.19 - *
166.20 - * You should have received a copy of the GNU General Public License version
166.21 - * 2 along with this work; if not, write to the Free Software Foundation,
166.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
166.23 - *
166.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
166.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
166.26 - * have any questions.
166.27 - */
166.28 -
166.29 -package javax.management;
166.30 -
166.31 -import java.lang.annotation.Documented;
166.32 -import java.lang.annotation.ElementType;
166.33 -import java.lang.annotation.Retention;
166.34 -import java.lang.annotation.RetentionPolicy;
166.35 -import java.lang.annotation.Target;
166.36 -
166.37 -/**
166.38 - * <p>Indicates that a method in an MBean class defines an MBean operation.
166.39 - * This annotation can be applied to:</p>
166.40 - *
166.41 - * <ul>
166.42 - * <li>A public method of a public class
166.43 - * that is itself annotated with an {@link MBean @MBean} or
166.44 - * {@link MXBean @MXBean} annotation, or inherits such an annotation from
166.45 - * a superclass.</li>
166.46 - * <li>A method of an MBean or MXBean interface.
166.47 - * </ul>
166.48 - *
166.49 - * <p>Every method in an MBean or MXBean interface defines an MBean
166.50 - * operation even without this annotation, but the annotation allows
166.51 - * you to specify the impact of the operation:</p>
166.52 - *
166.53 - * <pre>
166.54 - * public interface ConfigurationMBean {
166.55 - * {@code @ManagedOperation}(impact = {@link Impact#ACTION Impact.ACTION})
166.56 - * public void save();
166.57 - * ...
166.58 - * }
166.59 - * </pre>
166.60 - */
166.61 -@Retention(RetentionPolicy.RUNTIME)
166.62 -@Target(ElementType.METHOD)
166.63 -@Documented
166.64 -public @interface ManagedOperation {
166.65 - /**
166.66 - * <p>The impact of this operation, as shown by
166.67 - * {@link MBeanOperationInfo#getImpact()}.
166.68 - */
166.69 - Impact impact() default Impact.UNKNOWN;
166.70 -}
167.1 --- a/src/share/classes/javax/management/NotQueryExp.java Mon Nov 23 10:04:47 2009 +0000
167.2 +++ b/src/share/classes/javax/management/NotQueryExp.java Wed Nov 25 11:08:25 2009 -0800
167.3 @@ -90,10 +90,4 @@
167.4 public String toString() {
167.5 return "not (" + exp + ")";
167.6 }
167.7 -
167.8 - @Override
167.9 - String toQueryString() {
167.10 - return "not (" + Query.toString(exp) + ")";
167.11 - }
167.12 -
167.13 }
168.1 --- a/src/share/classes/javax/management/Notification.java Mon Nov 23 10:04:47 2009 +0000
168.2 +++ b/src/share/classes/javax/management/Notification.java Wed Nov 25 11:08:25 2009 -0800
168.3 @@ -54,7 +54,7 @@
168.4 * @since 1.5
168.5 */
168.6 @SuppressWarnings("serial") // serialVersionUID is not constant
168.7 -public class Notification extends EventObject implements Cloneable {
168.8 +public class Notification extends EventObject {
168.9
168.10 // Serialization compatibility stuff:
168.11 // Two serial forms are supported in this class. The selected form depends
168.12 @@ -244,26 +244,6 @@
168.13 }
168.14
168.15 /**
168.16 - * <p>Creates and returns a copy of this object. The copy is created as
168.17 - * described for {@link Object#clone()}. This means, first, that the
168.18 - * class of the object will be the same as the class of this object, and,
168.19 - * second, that the copy is a "shallow copy". Fields of this notification
168.20 - * are not themselves copied. In particular, the {@linkplain
168.21 - * #getUserData user data} of the copy is the same object as the
168.22 - * original.</p>
168.23 - *
168.24 - * @return a copy of this object.
168.25 - */
168.26 - @Override
168.27 - public Object clone() {
168.28 - try {
168.29 - return super.clone();
168.30 - } catch (CloneNotSupportedException e) {
168.31 - throw new AssertionError(e);
168.32 - }
168.33 - }
168.34 -
168.35 - /**
168.36 * Sets the source.
168.37 *
168.38 * @param source the new source for this object.
168.39 @@ -341,24 +321,12 @@
168.40 *
168.41 * @return The message string of this notification object.
168.42 *
168.43 - * @see #setMessage
168.44 */
168.45 public String getMessage() {
168.46 return message ;
168.47 }
168.48
168.49 /**
168.50 - * Set the notification message.
168.51 - *
168.52 - * @param message the new notification message.
168.53 - *
168.54 - * @see #getMessage
168.55 - */
168.56 - public void setMessage(String message) {
168.57 - this.message = message;
168.58 - }
168.59 -
168.60 - /**
168.61 * Get the user data.
168.62 *
168.63 * @return The user data object. It is used for whatever data
169.1 --- a/src/share/classes/javax/management/NotificationBroadcasterSupport.java Mon Nov 23 10:04:47 2009 +0000
169.2 +++ b/src/share/classes/javax/management/NotificationBroadcasterSupport.java Wed Nov 25 11:08:25 2009 -0800
169.3 @@ -1,5 +1,5 @@
169.4 /*
169.5 - * Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
169.6 + * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
169.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
169.8 *
169.9 * This code is free software; you can redistribute it and/or modify it
169.10 @@ -58,8 +58,7 @@
169.11 *
169.12 * @since 1.5
169.13 */
169.14 -public class NotificationBroadcasterSupport
169.15 - implements NotificationEmitter, SendNotification {
169.16 +public class NotificationBroadcasterSupport implements NotificationEmitter {
169.17 /**
169.18 * Constructs a NotificationBroadcasterSupport where each listener is invoked by the
169.19 * thread sending the notification. This constructor is equivalent to
169.20 @@ -249,26 +248,6 @@
169.21 }
169.22 }
169.23 }
169.24 - /**
169.25 - * Returns true if there are any listeners.
169.26 - *
169.27 - * @return true if there is at least one listener that has been added with
169.28 - * {@code addNotificationListener} and not subsequently removed with
169.29 - * {@code removeNotificationListener} or {@code removeAllNotificationListeners}.
169.30 - * @since 1.7
169.31 - */
169.32 - public boolean isListenedTo() {
169.33 - return listenerList.size() > 0;
169.34 - }
169.35 -
169.36 - /**
169.37 - * Removes all listeners.
169.38 - *
169.39 - * @since 1.7
169.40 - */
169.41 - public void removeAllNotificationListeners() {
169.42 - listenerList.clear();
169.43 - }
169.44
169.45 /**
169.46 * <p>This method is called by {@link #sendNotification
170.1 --- a/src/share/classes/javax/management/NotificationInfo.java Mon Nov 23 10:04:47 2009 +0000
170.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
170.3 @@ -1,135 +0,0 @@
170.4 -/*
170.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
170.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
170.7 - *
170.8 - * This code is free software; you can redistribute it and/or modify it
170.9 - * under the terms of the GNU General Public License version 2 only, as
170.10 - * published by the Free Software Foundation. Sun designates this
170.11 - * particular file as subject to the "Classpath" exception as provided
170.12 - * by Sun in the LICENSE file that accompanied this code.
170.13 - *
170.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
170.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
170.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
170.17 - * version 2 for more details (a copy is included in the LICENSE file that
170.18 - * accompanied this code).
170.19 - *
170.20 - * You should have received a copy of the GNU General Public License version
170.21 - * 2 along with this work; if not, write to the Free Software Foundation,
170.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
170.23 - *
170.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
170.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
170.26 - * have any questions.
170.27 - */
170.28 -
170.29 -package javax.management;
170.30 -
170.31 -import java.lang.annotation.Documented;
170.32 -import java.lang.annotation.ElementType;
170.33 -import java.lang.annotation.Inherited;
170.34 -import java.lang.annotation.Retention;
170.35 -import java.lang.annotation.RetentionPolicy;
170.36 -import java.lang.annotation.Target;
170.37 -
170.38 -/**
170.39 - * <p>Specifies the kinds of notification an MBean can emit. In both the
170.40 - * following examples, the MBean emits notifications of type
170.41 - * {@code "com.example.notifs.create"} and of type
170.42 - * {@code "com.example.notifs.destroy"}:</p>
170.43 - *
170.44 - * <pre>
170.45 - * // Example one: a Standard MBean
170.46 - * {@code @NotificationInfo}(types={"com.example.notifs.create",
170.47 - * "com.example.notifs.destroy"})
170.48 - * public interface CacheMBean {...}
170.49 - *
170.50 - * public class Cache
170.51 - * extends NotificationBroadcasterSupport implements CacheMBean {
170.52 - * public Cache() {
170.53 - * super(); // do not supply any MBeanNotificationInfo[]
170.54 - * }
170.55 - * ...
170.56 - * }
170.57 - * </pre>
170.58 - *
170.59 - * <pre>
170.60 - * // Example two: an annotated MBean
170.61 - * {@link MBean @MBean}
170.62 - * {@code @NotificationInfo}(types={"com.example.notifs.create",
170.63 - * "com.example.notifs.destroy"})
170.64 - * public class Cache {
170.65 - * <a href="MBeanRegistration.html#injection">{@code @Resource}</a>
170.66 - * private volatile SendNotification sendNotification;
170.67 - * ...
170.68 - * }
170.69 - * </pre>
170.70 - *
170.71 - * <p>Each {@code @NotificationInfo} produces an {@link
170.72 - * MBeanNotificationInfo} inside the {@link MBeanInfo} of each MBean
170.73 - * to which the annotation applies.</p>
170.74 - *
170.75 - * <p>If you need to specify different notification classes, or different
170.76 - * descriptions for different notification types, then you can group
170.77 - * several {@code @NotificationInfo} annotations into a containing
170.78 - * {@link NotificationInfos @NotificationInfos} annotation.
170.79 - *
170.80 - * <p>The {@code @NotificationInfo} and {@code @NotificationInfos} annotations
170.81 - * are ignored on an MBean that is not a {@linkplain JMX#isNotificationSource
170.82 - * notification source} or that implements {@link NotificationBroadcaster} and
170.83 - * returns a non-empty array from its {@link
170.84 - * NotificationBroadcaster#getNotificationInfo() getNotificationInfo()}
170.85 - * method.</p>
170.86 - *
170.87 - * <p>The {@code NotificationInfo} and {@code NotificationInfos}
170.88 - * annotations can be applied to the MBean implementation class, or to
170.89 - * any parent class or interface. These annotations on a class take
170.90 - * precedence over annotations on any superclass or superinterface.
170.91 - * If an MBean does not have these annotations on its class or any
170.92 - * superclass, then superinterfaces are examined. It is an error for
170.93 - * more than one superinterface to have these annotations, unless one
170.94 - * of them is a descendant of all the others; registering such an erroneous
170.95 - * MBean will cause a {@link NotCompliantMBeanException}.</p>
170.96 - */
170.97 -@Documented
170.98 -@Inherited
170.99 -@Target(ElementType.TYPE)
170.100 -@Retention(RetentionPolicy.RUNTIME)
170.101 -public @interface NotificationInfo {
170.102 - /**
170.103 - * <p>The {@linkplain Notification#getType() notification types}
170.104 - * that this MBean can emit.</p>
170.105 - */
170.106 - String[] types();
170.107 -
170.108 - /**
170.109 - * <p>The class that emitted notifications will have. It is recommended
170.110 - * that this be {@link Notification}, or one of its standard subclasses
170.111 - * in the JMX API.</p>
170.112 - */
170.113 - Class<? extends Notification> notificationClass() default Notification.class;
170.114 -
170.115 - /**
170.116 - * <p>The description of this notification. For example:
170.117 - *
170.118 - * <pre>
170.119 - * {@code @NotificationInfo}(
170.120 - * types={"com.example.notifs.create"},
170.121 - * description={@code @Description}("object created"))
170.122 - * </pre>
170.123 - */
170.124 - Description description() default @Description("");
170.125 -
170.126 - /**
170.127 - * <p>Additional descriptor fields for the derived {@code
170.128 - * MBeanNotificationInfo}. They are specified in the same way as
170.129 - * for the {@link DescriptorFields @DescriptorFields} annotation,
170.130 - * for example:</p>
170.131 - * <pre>
170.132 - * {@code @NotificationInfo}(
170.133 - * types={"com.example.notifs.create"},
170.134 - * descriptorFields={"severity=6"})
170.135 - * </pre>
170.136 - */
170.137 - String[] descriptorFields() default {};
170.138 -}
171.1 --- a/src/share/classes/javax/management/NotificationInfos.java Mon Nov 23 10:04:47 2009 +0000
171.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
171.3 @@ -1,72 +0,0 @@
171.4 -/*
171.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
171.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
171.7 - *
171.8 - * This code is free software; you can redistribute it and/or modify it
171.9 - * under the terms of the GNU General Public License version 2 only, as
171.10 - * published by the Free Software Foundation. Sun designates this
171.11 - * particular file as subject to the "Classpath" exception as provided
171.12 - * by Sun in the LICENSE file that accompanied this code.
171.13 - *
171.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
171.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
171.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
171.17 - * version 2 for more details (a copy is included in the LICENSE file that
171.18 - * accompanied this code).
171.19 - *
171.20 - * You should have received a copy of the GNU General Public License version
171.21 - * 2 along with this work; if not, write to the Free Software Foundation,
171.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
171.23 - *
171.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
171.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
171.26 - * have any questions.
171.27 - */
171.28 -
171.29 -package javax.management;
171.30 -
171.31 -import java.lang.annotation.Documented;
171.32 -import java.lang.annotation.ElementType;
171.33 -import java.lang.annotation.Inherited;
171.34 -import java.lang.annotation.Retention;
171.35 -import java.lang.annotation.RetentionPolicy;
171.36 -import java.lang.annotation.Target;
171.37 -
171.38 -import javax.management.remote.JMXConnectionNotification;
171.39 -
171.40 -/**
171.41 - * <p>Specifies the kinds of notification an MBean can emit, when this
171.42 - * cannot be represented by a single {@link NotificationInfo
171.43 - * @NotificationInfo} annotation.</p>
171.44 - *
171.45 - * <p>For example, this annotation specifies that an MBean can emit
171.46 - * {@link AttributeChangeNotification} and {@link
171.47 - * JMXConnectionNotification}:</p>
171.48 - *
171.49 - * <pre>
171.50 - * {@code @NotificationInfos}(
171.51 - * {@code @NotificationInfo}(
171.52 - * types = {{@link AttributeChangeNotification#ATTRIBUTE_CHANGE}},
171.53 - * notificationClass = AttributeChangeNotification.class),
171.54 - * {@code @NotificationInfo}(
171.55 - * types = {{@link JMXConnectionNotification#OPENED},
171.56 - * {@link JMXConnectionNotification#CLOSED}},
171.57 - * notificationClass = JMXConnectionNotification.class)
171.58 - * )
171.59 - * </pre>
171.60 - *
171.61 - * <p>If an MBean has both {@code NotificationInfo} and {@code
171.62 - * NotificationInfos} on the same class or interface, the effect is
171.63 - * the same as if the {@code NotificationInfo} were moved inside the
171.64 - * {@code NotificationInfos}.</p>
171.65 - */
171.66 -@Documented
171.67 -@Inherited
171.68 -@Target(ElementType.TYPE)
171.69 -@Retention(RetentionPolicy.RUNTIME)
171.70 -public @interface NotificationInfos {
171.71 - /**
171.72 - * <p>The {@link NotificationInfo} annotations.</p>
171.73 - */
171.74 - NotificationInfo[] value();
171.75 -}
172.1 --- a/src/share/classes/javax/management/ObjectName.java Mon Nov 23 10:04:47 2009 +0000
172.2 +++ b/src/share/classes/javax/management/ObjectName.java Wed Nov 25 11:08:25 2009 -0800
172.3 @@ -27,8 +27,6 @@
172.4
172.5 import com.sun.jmx.mbeanserver.GetPropertyAction;
172.6 import com.sun.jmx.mbeanserver.Util;
172.7 -import com.sun.jmx.namespace.serial.JMXNamespaceContext;
172.8 -
172.9 import java.io.IOException;
172.10 import java.io.InvalidObjectException;
172.11 import java.io.ObjectInputStream;
172.12 @@ -56,38 +54,14 @@
172.13 * properties.</p>
172.14 *
172.15 * <p>The <em>domain</em> is a string of characters not including
172.16 - * the character colon (<code>:</code>).</p>
172.17 - * <p>Starting with the version 2.0 of the JMX specification, the
172.18 - * <em>domain</em> can also start with a {@linkplain
172.19 - * javax.management.namespace#NamespacePrefix namespace prefix} identifying
172.20 - * the {@linkplain javax.management.namespace namespace} in which the
172.21 - * MBean is registered. A namespace prefix is a path string where
172.22 - * elements are separated by a double slash (<code>//</code>).
172.23 - * It identifies the {@linkplain javax.management.namespace namespace} in
172.24 - * which the MBean so named is registered.</p>
172.25 - *
172.26 - * <p>For instance the ObjectName <em>bar//baz:k=v</em> identifiies an MBean
172.27 - * named <em>baz:k=v</em> in the namespace <em>bar</em>. Similarly the
172.28 - * ObjectName <em>foo//bar//baz:k=v</em> identifiies an MBean named
172.29 - * <em>baz:k=v</em> in the namespace <em>foo//bar</em>. See the {@linkplain
172.30 - * javax.management.namespace namespace} documentation for more details.</p>
172.31 + * the character colon (<code>:</code>). It is recommended that the domain
172.32 + * should not contain the string "{@code //}", which is reserved for future use.
172.33 *
172.34 * <p>If the domain includes at least one occurrence of the wildcard
172.35 * characters asterisk (<code>*</code>) or question mark
172.36 * (<code>?</code>), then the object name is a pattern. The asterisk
172.37 * matches any sequence of zero or more characters, while the question
172.38 - * mark matches any single character. <br>
172.39 - * A namespace separator <code>//</code> does not match wildcard
172.40 - * characters unless it is at the very end of the domain string.
172.41 - * So <em>foo*bar*:*</em> does not match <em>foo//bar:k=v</em> but it
172.42 - * does match <em>fooxbar//:k=v</em>.
172.43 - * </p>
172.44 - *
172.45 - * <p>When included in a namespace path the special path element
172.46 - * <code>**</code> matches any number of sub namespaces
172.47 - * recursively, but only if used as a complete namespace path element,
172.48 - * as in <code>**//b//c//D:k=v</code> or <code>a//**//c//D:k=v</code>
172.49 - * - see <a href="#metawildcard">below</a>.
172.50 + * mark matches any single character.</p>
172.51 *
172.52 * <p>If the domain is empty, it will be replaced in certain contexts
172.53 * by the <em>default domain</em> of the MBean server in which the
172.54 @@ -195,51 +169,6 @@
172.55 * with {@code \}.</li>
172.56 * </ul>
172.57 *
172.58 - * <p id="metawildcard"><b>Pattern and namespaces:</b></p>
172.59 - * <p>In an object name pattern, a path element
172.60 - * of exactly <code>**</code> corresponds to a meta
172.61 - * wildcard that will match any number of sub namespaces.<br>Hence:</p>
172.62 - * <table border="0" cellpadding="5">
172.63 - * <thead><th>pattern</th><th>matches</th><th>doesn't match</th></thead>
172.64 - * <tbody>
172.65 - * <tr><td><ul><li><code>**//D:k=v</code></li></ul></td>
172.66 - * <td><code>a//D:k=v</code><br>
172.67 - * <code>a//b//D:k=v</code><br>
172.68 - * <code>a//b//c//D:k=v</code></td>
172.69 - * <td><code>D:k=v</code></td></tr>
172.70 - * <tr><td><ul><li><code>a//**//D:k=v</code></li></ul></td>
172.71 - * <td><code>a//b//D:k=v</code><br>
172.72 - * <code>a//b//c//D:k=v</code></td>
172.73 - * <td><code>b//b//c//D:k=v</code><br>
172.74 - * <code>a//D:k=v</code><br>
172.75 - * <code>D:k=v</code></td></tr>
172.76 - * <tr><td><ul><li><code>a//**//e//D:k=v</code></li></ul></td>
172.77 - * <td><code>a//b//e//D:k=v</code><br>
172.78 - * <code>a//b//c//e//D:k=v</code></td>
172.79 - * <td><code>a//b//c//c//D:k=v</code><br>
172.80 - * <code>b//b//c//e//D:k=v</code><br>
172.81 - * <code>a//e//D:k=v</code><br>
172.82 - * <code>e//D:k=v</code></td></tr>
172.83 - * <tr><td><ul><li><code>a//b**//e//D:k=v</code></li></ul></td>
172.84 - * <td><code>a//b//e//D:k=v</code></td>
172.85 - * <td><code>a//b//c//e//D:k=v</code><br>
172.86 - * because in that case <code>b**</code><br>
172.87 - * is not a meta-wildcard - and <code>b**</code><br>
172.88 - * is thus equivalent to <code>b*</code>.</td></tr>
172.89 - * </tbody>
172.90 - * </table>
172.91 - *</ul>
172.92 - * </p>
172.93 - * <p>
172.94 - * <b>Note:</b> Although ObjectName patterns where the characters
172.95 - * <code>*</code> and <code>?</code> appear in the namespace path are legal,
172.96 - * they are not valid in the {@code name} parameter of the MBean Server's
172.97 - * {@link MBeanServer#queryNames queryNames} and {@link MBeanServer#queryMBeans
172.98 - * queryMBeans} methods. See the
172.99 - * <a href="namespace/package-summary.html#RejectedNamespacePatterns"><!--
172.100 - * -->namespaces documentation</a> for more details.
172.101 - * </p>
172.102 - *
172.103 * <p>An ObjectName can be written as a String with the following
172.104 * elements in order:</p>
172.105 *
172.106 @@ -294,17 +223,6 @@
172.107 public class ObjectName implements Comparable<ObjectName>, QueryExp {
172.108
172.109 /**
172.110 - * The sequence of characters used to separate name spaces in a name space
172.111 - * path.
172.112 - *
172.113 - * @see javax.management.namespace
172.114 - * @since 1.7
172.115 - **/
172.116 - public static final String NAMESPACE_SEPARATOR = "//";
172.117 - private static final int NAMESPACE_SEPARATOR_LENGTH =
172.118 - NAMESPACE_SEPARATOR.length();
172.119 -
172.120 - /**
172.121 * A structure recording property structure and
172.122 * proposing minimal services
172.123 */
172.124 @@ -333,17 +251,16 @@
172.125 /**
172.126 * Returns a key string for receiver key
172.127 */
172.128 - String getKeyString(String name, int offset) {
172.129 - final int start = _key_index+offset;
172.130 - return name.substring(start, start + _key_length);
172.131 + String getKeyString(String name) {
172.132 + return name.substring(_key_index, _key_index + _key_length);
172.133 }
172.134
172.135 /**
172.136 * Returns a value string for receiver key
172.137 */
172.138 - String getValueString(String name, int offset) {
172.139 - final int in_begin = _key_index + offset + _key_length + 1;
172.140 - final int out_end = in_begin + _value_length;
172.141 + String getValueString(String name) {
172.142 + int in_begin = _key_index + _key_length + 1;
172.143 + int out_end = in_begin + _value_length;
172.144 return name.substring(in_begin, out_end);
172.145 }
172.146 }
172.147 @@ -476,40 +393,6 @@
172.148 */
172.149 private transient boolean _property_value_pattern = false;
172.150
172.151 - private ObjectName(String newDomain, ObjectName aname)
172.152 - throws MalformedObjectNameException{
172.153 - copyToOtherDomain(newDomain,aname);
172.154 - }
172.155 -
172.156 - private void copyToOtherDomain(String domain, ObjectName aname)
172.157 - throws MalformedObjectNameException {
172.158 -
172.159 - // The domain cannot be null
172.160 - if (domain == null)
172.161 - throw new NullPointerException("domain cannot be null");
172.162 -
172.163 - // The key property list cannot be null
172.164 - if (aname == null)
172.165 - throw new MalformedObjectNameException(
172.166 - "key property list cannot be empty");
172.167 -
172.168 - // checks domain validity. A side effect of this method is also to
172.169 - // set the _domain_pattern flag.
172.170 - if (!isDomain(domain))
172.171 - throw new MalformedObjectNameException("Invalid domain: " + domain);
172.172 -
172.173 - // init canonicalname
172.174 - _domain_length = domain.length();
172.175 -
172.176 - _canonicalName = (domain +
172.177 - aname._canonicalName.substring(aname._domain_length)).intern();
172.178 - _kp_array = aname._kp_array;
172.179 - _ca_array = aname._ca_array;
172.180 - _propertyList = aname._propertyList;
172.181 - _property_list_pattern = aname._property_list_pattern;
172.182 - _property_value_pattern = aname._property_value_pattern;
172.183 - }
172.184 -
172.185 // Instance private fields <=======================================
172.186
172.187 // Private fields <========================================
172.188 @@ -754,12 +637,10 @@
172.189
172.190 // we got the key and value part, prepare a property for this
172.191 if (!value_pattern) {
172.192 - prop = new Property(key_index-_domain_length,
172.193 - key_length, value_length);
172.194 + prop = new Property(key_index, key_length, value_length);
172.195 } else {
172.196 _property_value_pattern = true;
172.197 - prop = new PatternProperty(key_index-_domain_length,
172.198 - key_length, value_length);
172.199 + prop = new PatternProperty(key_index, key_length, value_length);
172.200 }
172.201 key_name = name.substring(key_index, key_index + key_length);
172.202
172.203 @@ -844,12 +725,12 @@
172.204 boolean value_pattern = checkValue(value);
172.205 sb.append(value);
172.206 if (!value_pattern) {
172.207 - prop = new Property(key_index-_domain_length,
172.208 + prop = new Property(key_index,
172.209 key.length(),
172.210 value.length());
172.211 } else {
172.212 _property_value_pattern = true;
172.213 - prop = new PatternProperty(key_index-_domain_length,
172.214 + prop = new PatternProperty(key_index,
172.215 key.length(),
172.216 value.length());
172.217 }
172.218 @@ -929,9 +810,9 @@
172.219 prop = _ca_array[i];
172.220 // length of prop including '=' char
172.221 prop_len = prop._key_length + prop._value_length + 1;
172.222 - System.arraycopy(specified_chars, prop._key_index+_domain_length,
172.223 + System.arraycopy(specified_chars, prop._key_index,
172.224 canonical_chars, prop_index, prop_len);
172.225 - prop.setKeyIndex(prop_index-_domain_length);
172.226 + prop.setKeyIndex(prop_index);
172.227 prop_index += prop_len;
172.228 if (i != last_index) {
172.229 canonical_chars[prop_index] = ',';
172.230 @@ -1268,37 +1149,15 @@
172.231 cn = (String)in.readObject();
172.232 }
172.233
172.234 - final JMXNamespaceContext ctxt =
172.235 - JMXNamespaceContext.getDeserializationContext();
172.236 try {
172.237 - construct(changeContext(ctxt,cn));
172.238 + construct(cn);
172.239 } catch (NullPointerException e) {
172.240 throw new InvalidObjectException(e.toString());
172.241 - } catch (IllegalArgumentException e) {
172.242 - throw new InvalidObjectException(e.toString());
172.243 } catch (MalformedObjectNameException e) {
172.244 throw new InvalidObjectException(e.toString());
172.245 }
172.246 }
172.247
172.248 - private String changeContext(JMXNamespaceContext context, String nameString) {
172.249 - final String old = context.prefixToRemove;
172.250 - final String nw = context.prefixToAdd;
172.251 - final int ol = old.length();
172.252 - if (nameString.startsWith(NAMESPACE_SEPARATOR)) return nameString;
172.253 - if (ol>0) {
172.254 - if (!nameString.startsWith(old) ||
172.255 - !nameString.startsWith(NAMESPACE_SEPARATOR,ol))
172.256 - throw new IllegalArgumentException(
172.257 - "Serialized ObjectName does not start with " + old +
172.258 - ": " + nameString);
172.259 - nameString = nameString.substring(ol+NAMESPACE_SEPARATOR_LENGTH);
172.260 - }
172.261 - if (!nw.equals("")) {
172.262 - nameString = nw + NAMESPACE_SEPARATOR + nameString;
172.263 - }
172.264 - return nameString;
172.265 - }
172.266
172.267 /**
172.268 * Serializes an {@link ObjectName} to an {@link ObjectOutputStream}.
172.269 @@ -1361,22 +1220,15 @@
172.270 private void writeObject(ObjectOutputStream out)
172.271 throws IOException {
172.272
172.273 - final JMXNamespaceContext ctxt =
172.274 - JMXNamespaceContext.getSerializationContext();
172.275 -
172.276 if (compat)
172.277 {
172.278 // Serializes this instance in the old serial form
172.279 // Read CR 6441274 before making any changes to this code
172.280 ObjectOutputStream.PutField fields = out.putFields();
172.281 - final String domain =
172.282 - changeContext(ctxt,_canonicalName.substring(0, _domain_length));
172.283 - final String cn =
172.284 - changeContext(ctxt,_canonicalName);
172.285 - fields.put("domain", domain);
172.286 + fields.put("domain", _canonicalName.substring(0, _domain_length));
172.287 fields.put("propertyList", getKeyPropertyList());
172.288 fields.put("propertyListString", getKeyPropertyListString());
172.289 - fields.put("canonicalName", cn);
172.290 + fields.put("canonicalName", _canonicalName);
172.291 fields.put("pattern", (_domain_pattern || _property_list_pattern));
172.292 fields.put("propertyPattern", _property_list_pattern);
172.293 out.writeFields();
172.294 @@ -1386,8 +1238,7 @@
172.295 // Serializes this instance in the new serial form
172.296 //
172.297 out.defaultWriteObject();
172.298 -
172.299 - out.writeObject(changeContext(ctxt,getSerializedNameString()));
172.300 + out.writeObject(getSerializedNameString());
172.301 }
172.302 }
172.303
172.304 @@ -1416,10 +1267,9 @@
172.305 * @exception NullPointerException The <code>name</code> parameter
172.306 * is null.
172.307 *
172.308 - * @see #valueOf(String)
172.309 */
172.310 public static ObjectName getInstance(String name)
172.311 - throws MalformedObjectNameException {
172.312 + throws MalformedObjectNameException, NullPointerException {
172.313 return new ObjectName(name);
172.314 }
172.315
172.316 @@ -1444,7 +1294,6 @@
172.317 * follow the rules for quoting.
172.318 * @exception NullPointerException One of the parameters is null.
172.319 *
172.320 - * @see #valueOf(String, String, String)
172.321 */
172.322 public static ObjectName getInstance(String domain, String key,
172.323 String value)
172.324 @@ -1476,7 +1325,6 @@
172.325 * quoting.
172.326 * @exception NullPointerException One of the parameters is null.
172.327 *
172.328 - * @see #valueOf(String, Hashtable)
172.329 */
172.330 public static ObjectName getInstance(String domain,
172.331 Hashtable<String,String> table)
172.332 @@ -1516,143 +1364,7 @@
172.333 public static ObjectName getInstance(ObjectName name) {
172.334 if (name.getClass().equals(ObjectName.class))
172.335 return name;
172.336 - return valueOf(name.getSerializedNameString());
172.337 - }
172.338 -
172.339 - /**
172.340 - * <p>Return an instance of ObjectName that can be used anywhere
172.341 - * an object obtained with {@link #ObjectName(String) new
172.342 - * ObjectName(name)} can be used. The returned object may be of
172.343 - * a subclass of ObjectName. Calling this method twice with the
172.344 - * same parameters may return the same object or two equal but
172.345 - * not identical objects.</p>
172.346 - *
172.347 - * <p>This method is equivalent to {@link #getInstance(String)} except that
172.348 - * it does not throw any checked exceptions.</p>
172.349 - *
172.350 - * @param name A string representation of the object name.
172.351 - *
172.352 - * @return an ObjectName corresponding to the given String.
172.353 - *
172.354 - * @exception IllegalArgumentException The string passed as a
172.355 - * parameter does not have the right format. The {@linkplain
172.356 - * Throwable#getCause() cause} of this exception will be a
172.357 - * {@link MalformedObjectNameException}.
172.358 - * @exception NullPointerException The <code>name</code> parameter
172.359 - * is null.
172.360 - *
172.361 - * @since 1.7
172.362 - */
172.363 - public static ObjectName valueOf(String name) {
172.364 - try {
172.365 - return getInstance(name);
172.366 - } catch (MalformedObjectNameException e) {
172.367 - throw new IllegalArgumentException(e.getMessage(), e);
172.368 - // Just plain IllegalArgumentException(e) produces an exception
172.369 - // message "javax.management.MalformedObjectNameException: ..."
172.370 - // which is distracting.
172.371 - }
172.372 - }
172.373 -
172.374 - /**
172.375 - * <p>Return an instance of ObjectName that can be used anywhere
172.376 - * an object obtained with {@link #ObjectName(String, String,
172.377 - * String) new ObjectName(domain, key, value)} can be used. The
172.378 - * returned object may be of a subclass of ObjectName. Calling
172.379 - * this method twice with the same parameters may return the same
172.380 - * object or two equal but not identical objects.</p>
172.381 - *
172.382 - * <p>This method is equivalent to {@link #getInstance(String, String,
172.383 - * String)} except that it does not throw any checked exceptions.</p>
172.384 - *
172.385 - * @param domain The domain part of the object name.
172.386 - * @param key The attribute in the key property of the object name.
172.387 - * @param value The value in the key property of the object name.
172.388 - *
172.389 - * @return an ObjectName corresponding to the given domain,
172.390 - * key, and value.
172.391 - *
172.392 - * @exception IllegalArgumentException The
172.393 - * <code>domain</code>, <code>key</code>, or <code>value</code>
172.394 - * contains an illegal character, or <code>value</code> does not
172.395 - * follow the rules for quoting. The {@linkplain
172.396 - * Throwable#getCause() cause} of this exception will be a
172.397 - * {@link MalformedObjectNameException}.
172.398 - * @exception NullPointerException One of the parameters is null.
172.399 - *
172.400 - * @since 1.7
172.401 - */
172.402 - public static ObjectName valueOf(String domain, String key, String value) {
172.403 - try {
172.404 - return getInstance(domain, key, value);
172.405 - } catch (MalformedObjectNameException e) {
172.406 - throw new IllegalArgumentException(e.getMessage(), e);
172.407 - }
172.408 - }
172.409 -
172.410 - /**
172.411 - * <p>Return an instance of ObjectName that can be used anywhere
172.412 - * an object obtained with {@link #ObjectName(String, Hashtable)
172.413 - * new ObjectName(domain, table)} can be used. The returned
172.414 - * object may be of a subclass of ObjectName. Calling this method
172.415 - * twice with the same parameters may return the same object or
172.416 - * two equal but not identical objects.</p>
172.417 - *
172.418 - * <p>This method is equivalent to {@link #getInstance(String, Hashtable)}
172.419 - * except that it does not throw any checked exceptions.</p>
172.420 - *
172.421 - * @param domain The domain part of the object name.
172.422 - * @param table A hash table containing one or more key
172.423 - * properties. The key of each entry in the table is the key of a
172.424 - * key property in the object name. The associated value in the
172.425 - * table is the associated value in the object name.
172.426 - *
172.427 - * @return an ObjectName corresponding to the given domain and
172.428 - * key mappings.
172.429 - *
172.430 - * @exception IllegalArgumentException The <code>domain</code>
172.431 - * contains an illegal character, or one of the keys or values in
172.432 - * <code>table</code> contains an illegal character, or one of the
172.433 - * values in <code>table</code> does not follow the rules for
172.434 - * quoting. The {@linkplain Throwable#getCause() cause} of this exception
172.435 - * will be a {@link MalformedObjectNameException}.
172.436 - * @exception NullPointerException One of the parameters is null.
172.437 - *
172.438 - * @since 1.7
172.439 - */
172.440 - public static ObjectName valueOf(String domain,
172.441 - Hashtable<String,String> table) {
172.442 - try {
172.443 - return new ObjectName(domain, table);
172.444 - } catch (MalformedObjectNameException e) {
172.445 - throw new IllegalArgumentException(e.getMessage(), e);
172.446 - }
172.447 - }
172.448 -
172.449 - /**
172.450 - * Returns an {@code ObjectName} that is the same as this one but
172.451 - * with the specified domain.
172.452 - * This method preserves the original key order in the new instance.
172.453 - * If the provided name has a key property pattern, it will also be
172.454 - * preserved in the returned instance.
172.455 - *
172.456 - * @param newDomain The new domain for the returned instance;
172.457 - * must not be null.
172.458 - * @return A new {@code ObjectName} that is the same as {@code this}
172.459 - * except the domain is {@code newDomain}.
172.460 - * @throws NullPointerException if {@code newDomain} is null.
172.461 - * @exception IllegalArgumentException The {@code newDomain} passed as a
172.462 - * parameter does not have the right format. The {@linkplain
172.463 - * Throwable#getCause() cause} of this exception will be a
172.464 - * {@link MalformedObjectNameException}.
172.465 - * @since 1.7
172.466 - **/
172.467 - public final ObjectName withDomain(String newDomain) {
172.468 - try {
172.469 - return new ObjectName(newDomain, this);
172.470 - } catch (MalformedObjectNameException x) {
172.471 - throw new IllegalArgumentException(x.getMessage(),x);
172.472 - }
172.473 + return Util.newObjectName(name.getSerializedNameString());
172.474 }
172.475
172.476 /**
172.477 @@ -1664,8 +1376,6 @@
172.478 * parameter does not have the right format.
172.479 * @exception NullPointerException The <code>name</code> parameter
172.480 * is null.
172.481 - *
172.482 - * @see #valueOf(String)
172.483 */
172.484 public ObjectName(String name)
172.485 throws MalformedObjectNameException {
172.486 @@ -1684,8 +1394,6 @@
172.487 * contains an illegal character, or <code>value</code> does not
172.488 * follow the rules for quoting.
172.489 * @exception NullPointerException One of the parameters is null.
172.490 - *
172.491 - * @see #valueOf(String, String, String)
172.492 */
172.493 public ObjectName(String domain, String key, String value)
172.494 throws MalformedObjectNameException {
172.495 @@ -1711,8 +1419,6 @@
172.496 * values in <code>table</code> does not follow the rules for
172.497 * quoting.
172.498 * @exception NullPointerException One of the parameters is null.
172.499 - *
172.500 - * @see #valueOf(String, Hashtable)
172.501 */
172.502 public ObjectName(String domain, Hashtable<String,String> table)
172.503 throws MalformedObjectNameException {
172.504 @@ -1814,7 +1520,7 @@
172.505 throw new NullPointerException("key property can't be null");
172.506 for (int i = 0; i < _ca_array.length; i++) {
172.507 Property prop = _ca_array[i];
172.508 - String key = prop.getKeyString(_canonicalName,_domain_length);
172.509 + String key = prop.getKeyString(_canonicalName);
172.510 if (key.equals(property))
172.511 return (prop instanceof PatternProperty);
172.512 }
172.513 @@ -1894,10 +1600,8 @@
172.514 Property prop;
172.515 for (int i = len - 1; i >= 0; i--) {
172.516 prop = _ca_array[i];
172.517 - _propertyList.put(prop.getKeyString(_canonicalName,
172.518 - _domain_length),
172.519 - prop.getValueString(_canonicalName,
172.520 - _domain_length));
172.521 + _propertyList.put(prop.getKeyString(_canonicalName),
172.522 + prop.getValueString(_canonicalName));
172.523 }
172.524 }
172.525 }
172.526 @@ -1982,8 +1686,7 @@
172.527 }
172.528 }
172.529
172.530 - final String name = new String(dest_chars);
172.531 - return name;
172.532 + return new String(dest_chars);
172.533 }
172.534
172.535 /**
172.536 @@ -2009,7 +1712,7 @@
172.537 for (int i = 0; i < len; i++) {
172.538 final Property prop = _kp_array[i];
172.539 final int prop_len = prop._key_length + prop._value_length + 1;
172.540 - System.arraycopy(value, prop._key_index+_domain_length, dest_chars, index,
172.541 + System.arraycopy(value, prop._key_index, dest_chars, index,
172.542 prop_len);
172.543 index += prop_len;
172.544 if (i < last ) dest_chars[index++] = ',';
172.545 @@ -2054,10 +1757,6 @@
172.546 return getSerializedNameString();
172.547 }
172.548
172.549 - String toQueryString() {
172.550 - return "like " + Query.value(toString());
172.551 - }
172.552 -
172.553 /**
172.554 * Compares the current object name with another object name. Two
172.555 * ObjectName instances are equal if and only if their canonical
172.556 @@ -2218,7 +1917,7 @@
172.557 *
172.558 * @since 1.6
172.559 */
172.560 - public static final ObjectName WILDCARD = valueOf("*:*");
172.561 + public static final ObjectName WILDCARD = Util.newObjectName("*:*");
172.562
172.563 // Category : Utilities <===================================
172.564
172.565 @@ -2264,7 +1963,7 @@
172.566 // wildmatch domains
172.567 // This ObjectName is the pattern
172.568 // The other ObjectName is the string.
172.569 - return Util.wildpathmatch(name.getDomain(),getDomain());
172.570 + return Util.wildmatch(name.getDomain(),getDomain());
172.571 }
172.572 return getDomain().equals(name.getDomain());
172.573 }
172.574 @@ -2290,7 +1989,7 @@
172.575 // index in receiver
172.576 //
172.577 final Property p = props[i];
172.578 - final String k = p.getKeyString(cn,_domain_length);
172.579 + final String k = p.getKeyString(cn);
172.580 final String v = nameProps.get(k);
172.581 // Did we find a value for this key ?
172.582 //
172.583 @@ -2300,12 +1999,12 @@
172.584 if (_property_value_pattern && (p instanceof PatternProperty)) {
172.585 // wildmatch key property values
172.586 // p is the property pattern, v is the string
172.587 - if (Util.wildmatch(v,p.getValueString(cn,_domain_length)))
172.588 + if (Util.wildmatch(v,p.getValueString(cn)))
172.589 continue;
172.590 else
172.591 return false;
172.592 }
172.593 - if (v.equals(p.getValueString(cn,_domain_length))) continue;
172.594 + if (v.equals(p.getValueString(cn))) continue;
172.595 return false;
172.596 }
172.597 return true;
173.1 --- a/src/share/classes/javax/management/ObjectNameTemplate.java Mon Nov 23 10:04:47 2009 +0000
173.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
173.3 @@ -1,131 +0,0 @@
173.4 -/*
173.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
173.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
173.7 - *
173.8 - * This code is free software; you can redistribute it and/or modify it
173.9 - * under the terms of the GNU General Public License version 2 only, as
173.10 - * published by the Free Software Foundation. Sun designates this
173.11 - * particular file as subject to the "Classpath" exception as provided
173.12 - * by Sun in the LICENSE file that accompanied this code.
173.13 - *
173.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
173.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
173.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
173.17 - * version 2 for more details (a copy is included in the LICENSE file that
173.18 - * accompanied this code).
173.19 - *
173.20 - * You should have received a copy of the GNU General Public License version
173.21 - * 2 along with this work; if not, write to the Free Software Foundation,
173.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
173.23 - *
173.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
173.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
173.26 - * have any questions.
173.27 - */
173.28 -package javax.management;
173.29 -
173.30 -import java.lang.annotation.Documented;
173.31 -import java.lang.annotation.ElementType;
173.32 -import java.lang.annotation.Retention;
173.33 -import java.lang.annotation.RetentionPolicy;
173.34 -import java.lang.annotation.Target;
173.35 -
173.36 -/**
173.37 - * Annotation to allow an MBean to provide its name.
173.38 - * This annotation can be used on the following types:
173.39 - * <ul>
173.40 - * <li>MBean or MXBean Java interface.</li>
173.41 - * <li>Java class annotated with {@link javax.management.MBean @MBean}</code>
173.42 - * annotation.</li>
173.43 - * <li>Java class annotated with {@link javax.management.MXBean @MXBean}</code>
173.44 - * annotation.</li>
173.45 - * </ul>
173.46 - *
173.47 - * <p>The value of this annotation is used to build the <code>ObjectName</code>
173.48 - * when instances of the annotated type are registered in
173.49 - * an <code>MBeanServer</code> and no explicit name is given to the
173.50 - * {@code createMBean} or {@code registerMBean} method (the {@code ObjectName}
173.51 - * is {@code null}).</p>
173.52 - *
173.53 - * <p>For Dynamic MBeans, which define their own {@code MBeanInfo}, you can
173.54 - * produce the same effect as this annotation by including a field
173.55 - * <a href="Descriptor.html#objectNameTemplate">{@code objectNameTemplate}</a>
173.56 - * in the {@link Descriptor} for the {@code MBeanInfo} returned by
173.57 - * {@link DynamicMBean#getMBeanInfo()}.</p>
173.58 - *
173.59 - * <p>For Standard MBeans and MXBeans, this annotation automatically produces
173.60 - * an {@code objectNameTemplate} field in the {@code Descriptor}.</p>
173.61 - *
173.62 - * <p>The template can contain variables so that the name of the MBean
173.63 - * depends on the value of one or more of its attributes.
173.64 - * A variable that identifies an MBean attribute is of the form
173.65 - * <code>{<em>attribute name</em>}</code>. For example, to make an MBean name
173.66 - * depend on the <code>Name</code> attribute, use the variable
173.67 - * <code>{Name}</code>. Attribute names are case sensitive.
173.68 - * Naming attributes can be of any type. The <code>String</code> returned by
173.69 - * <code>toString()</code> is included in the constructed name.</p>
173.70 - *
173.71 - * <p>If you need the attribute value to be quoted
173.72 - * by a call to {@link ObjectName#quote(String) ObjectName.quote},
173.73 - * surround the variable with quotes. Quoting only applies to key values.
173.74 - * For example, <code>@ObjectNameTemplate("java.lang:type=MemoryPool,name=\"{Name}\"")</code>,
173.75 - * quotes the <code>Name</code> attribute value. You can notice the "\"
173.76 - * character needed to escape a quote within a <code>String</code>. A name
173.77 - * produced by this template might look like
173.78 - * {@code java.lang:type=MemoryPool,name="Code Cache"}.</p>
173.79 - *
173.80 - * <p>Variables can be used anywhere in the <code>String</code>.
173.81 - * Be sure to make the template derived name comply with
173.82 - * {@link ObjectName ObjectName} syntax.</p>
173.83 - *
173.84 - * <p>If an MBean is registered with a null name and it implements
173.85 - * {@link javax.management.MBeanRegistration MBeanRegistration}, then
173.86 - * the computed name is provided to the <code>preRegister</code> method.
173.87 - * Similarly,
173.88 - * if the MBean uses <a href="MBeanRegistration.html#injection">resource
173.89 - * injection</a> to discover its name, it is the computed name that will
173.90 - * be injected.</p>
173.91 - * <p>All of the above can be used with the {@link StandardMBean} class and
173.92 - * the annotation is effective in that case too.</p>
173.93 - * <p>If any exception occurs (such as unknown attribute, invalid syntax or
173.94 - * exception
173.95 - * thrown by the MBean) when the name is computed it is wrapped in a
173.96 - * <code>NotCompliantMBeanException</code>.</p>
173.97 - * <p>Some ObjectName template examples:
173.98 - * <ul><li>"com.example:type=Memory". Fixed ObjectName. Used to name a
173.99 - * singleton MBean.</li>
173.100 - * <li>"com.example:type=MemoryPool,name={Name}". Variable ObjectName.
173.101 - * <code>Name</code> attribute is retrieved to compose the <code>name</code>
173.102 - * key value.</li>
173.103 - * <li>"com.example:type=SomeType,name={InstanceName},id={InstanceId}".
173.104 - * Variable ObjectName.
173.105 - * <code>InstanceName</code> and <code>InstanceId</code> attributes are
173.106 - * retrieved to compose respectively
173.107 - * the <code>name</code> and <code>id</code> key values.</li>
173.108 - * <li>"com.example:type=OtherType,name=\"{ComplexName}\"". Variable ObjectName.
173.109 - * <code>ComplexName</code> attribute is retrieved to compose the
173.110 - * <code>name</code> key quoted value.</li> </li>
173.111 - * <li>"com.example:{TypeKey}=SomeOtherType". Variable ObjectName.
173.112 - * <code>TypeKey</code> attribute is retrieved to compose the
173.113 - * first key name.</li>
173.114 - * * <li>"{Domain}:type=YetAnotherType". Variable ObjectName.
173.115 - * <code>Domain</code> attribute is retrieved to compose the
173.116 - * management domain.</li>
173.117 - * <li>"{Naming}". Variable ObjectName.
173.118 - * <code>Naming</code> attribute is retrieved to compose the
173.119 - * complete name.</li>
173.120 - * </ul>
173.121 - * </p>
173.122 - */
173.123 -@Documented
173.124 -@Retention(RetentionPolicy.RUNTIME)
173.125 -@Target(ElementType.TYPE)
173.126 -public @interface ObjectNameTemplate {
173.127 -
173.128 - /**
173.129 - * The MBean name template.
173.130 - * @return The MBean name template.
173.131 - */
173.132 - @DescriptorKey("objectNameTemplate")
173.133 - public String value();
173.134 -}
174.1 --- a/src/share/classes/javax/management/OrQueryExp.java Mon Nov 23 10:04:47 2009 +0000
174.2 +++ b/src/share/classes/javax/management/OrQueryExp.java Wed Nov 25 11:08:25 2009 -0800
174.3 @@ -104,24 +104,4 @@
174.4 public String toString() {
174.5 return "(" + exp1 + ") or (" + exp2 + ")";
174.6 }
174.7 -
174.8 - @Override
174.9 - String toQueryString() {
174.10 - return parens(exp1) + " or " + parens(exp2);
174.11 - }
174.12 -
174.13 - // Add parentheses to avoid possible confusion. If we have an expression
174.14 - // such as Query.or(Query.and(a, b), c), then we return
174.15 - // (a and b) or c
174.16 - // rather than just
174.17 - // a and b or c
174.18 - // In fact the precedence rules are such that the parentheses are not
174.19 - // strictly necessary, but omitting them would be confusing.
174.20 - private static String parens(QueryExp exp) {
174.21 - String s = Query.toString(exp);
174.22 - if (exp instanceof AndQueryExp)
174.23 - return "(" + s + ")";
174.24 - else
174.25 - return s;
174.26 - }
174.27 }
175.1 --- a/src/share/classes/javax/management/QualifiedAttributeValueExp.java Mon Nov 23 10:04:47 2009 +0000
175.2 +++ b/src/share/classes/javax/management/QualifiedAttributeValueExp.java Wed Nov 25 11:08:25 2009 -0800
175.3 @@ -113,8 +113,7 @@
175.4 @Override
175.5 public String toString() {
175.6 if (className != null) {
175.7 - return QueryParser.quoteId(className) + "#" +
175.8 - QueryParser.quoteId(super.toString());
175.9 + return className + "." + super.toString();
175.10 } else {
175.11 return super.toString();
175.12 }
176.1 --- a/src/share/classes/javax/management/Query.java Mon Nov 23 10:04:47 2009 +0000
176.2 +++ b/src/share/classes/javax/management/Query.java Wed Nov 25 11:08:25 2009 -0800
176.3 @@ -40,14 +40,6 @@
176.4 * but the methods in this class return only standard classes that are
176.5 * part of the JMX implementation.</p>
176.6 *
176.7 - * <p>There are two ways to create {@code QueryExp} objects using the methods
176.8 - * in this class. The first is to build them by chaining together calls to
176.9 - * the various methods. The second is to use the Query Language described
176.10 - * <a href="#ql">below</a> and produce the {@code QueryExp} by calling
176.11 - * {@link #fromString Query.fromString}. The two ways are equivalent:
176.12 - * every {@code QueryExp} returned by {@code fromString} can also be
176.13 - * constructed by chaining method calls.</p>
176.14 - *
176.15 * <p>As an example, suppose you wanted to find all MBeans where the {@code
176.16 * Enabled} attribute is {@code true} and the {@code Owner} attribute is {@code
176.17 * "Duke"}. Here is how you could construct the appropriate {@code QueryExp} by
176.18 @@ -59,307 +51,6 @@
176.19 * Query.eq(Query.attr("Owner"), Query.value("Duke")));
176.20 * </pre>
176.21 *
176.22 - * <p>Here is how you could construct the same {@code QueryExp} using the
176.23 - * Query Language:</p>
176.24 - *
176.25 - * <pre>
176.26 - * QueryExp query = Query.fromString("Enabled = true and Owner = 'Duke'");
176.27 - * </pre>
176.28 - *
176.29 - * <p>The principal advantage of the method-chaining approach is that the
176.30 - * compiler will check that the query makes sense. The principal advantage
176.31 - * of the Query Language approach is that it is easier to write and especially
176.32 - * read.</p>
176.33 - *
176.34 - *
176.35 - * <h4 id="ql">Query Language</h4>
176.36 - *
176.37 - * <p>The query language is closely modeled on the WHERE clause of
176.38 - * SQL SELECT statements. The formal specification of the language
176.39 - * appears <a href="#formal-ql">below</a>, but it is probably easier to
176.40 - * understand it with examples such as the following.</p>
176.41 - *
176.42 - * <dl>
176.43 - * <dt>{@code Message = 'OK'}
176.44 - * <dd>Selects MBeans that have a {@code Message} attribute whose value
176.45 - * is the string {@code OK}.
176.46 - *
176.47 - * <dt>{@code FreeSpacePercent < 10}
176.48 - * <dd>Selects MBeans that have a {@code FreeSpacePercent} attribute whose
176.49 - * value is a number less than 10.
176.50 - *
176.51 - * <dt>{@code FreeSpacePercent < 10 and WarningSent = false}
176.52 - * <dd>Selects the same MBeans as the previous example, but they must
176.53 - * also have a boolean attribute {@code WarningSent} whose value
176.54 - * is false.
176.55 - *
176.56 - * <dt>{@code SpaceUsed > TotalSpace * (2.0 / 3.0)}
176.57 - * <dd>Selects MBeans that have {@code SpaceUsed} and {@code TotalSpace}
176.58 - * attributes where the first is more than two-thirds the second.
176.59 - *
176.60 - * <dt>{@code not (FreeSpacePercent between 10 and 90)}
176.61 - * <dd>Selects MBeans that have a {@code FreeSpacePercent} attribute whose
176.62 - * value is not between 10 and 90, inclusive.
176.63 - *
176.64 - * <dt>{@code FreeSpacePercent not between 10 and 90}
176.65 - * <dd>Another way of writing the previous query.
176.66 - *
176.67 - * <dt>{@code Status in ('STOPPED', 'STARTING', 'STARTED')}
176.68 - * <dd>Selects MBeans that have a {@code Status} attribute whose value
176.69 - * is one of those three strings.
176.70 - *
176.71 - * <dt>{@code Message like 'OK: *'}
176.72 - * <dd>Selects MBeans that have a {@code Message} attribute whose value
176.73 - * is a string beginning with {@code "OK: "}. <b>Notice that the
176.74 - * wildcard characters are not the ones that SQL uses.</b> In SQL,
176.75 - * {@code %} means "any sequence of characters" and {@code _}
176.76 - * means "any single character". Here, as in the rest of the JMX API,
176.77 - * those are represented by {@code *} and {@code ?} respectively.
176.78 - *
176.79 - * <dt>{@code instanceof 'javax.management.NotificationBroadcaster'}
176.80 - * <dd>Selects MBeans that are instances of
176.81 - * {@link javax.management.NotificationBroadcaster}, as reported by
176.82 - * {@link javax.management.MBeanServer#isInstanceOf MBeanServer.isInstanceOf}.
176.83 - *
176.84 - * <dt>{@code like 'mydomain:*'}
176.85 - * <dd>Selects MBeans whose {@link ObjectName}s have the domain {@code mydomain}.
176.86 - *
176.87 - * </dl>
176.88 - *
176.89 - * <p>The last two examples do not correspond to valid SQL syntax, but all
176.90 - * the others do.</p>
176.91 - *
176.92 - * <p>The remainder of this description is a formal specification of the
176.93 - * query language.</p>
176.94 - *
176.95 - *
176.96 - * <h4 id="formal-ql">Lexical elements</h4>
176.97 - *
176.98 - * <p>Keywords such as <b>and</b>, <b>like</b>, and <b>between</b> are not
176.99 - * case sensitive. You can write <b>between</b>, <b>BETWEEN</b>, or
176.100 - * <b>BeTwEeN</b> with the same effect.</p>
176.101 - *
176.102 - * <p>On the other hand, attribute names <i>are</i> case sensitive. The
176.103 - * attribute {@code Name} is not the same as the attribute {@code name}.</p>
176.104 - *
176.105 - * <p>To access an attribute whose name, ignoring case, is the same as one of
176.106 - * the keywords {@code not}, {@code instanceof}, {@code like}, {@code true},
176.107 - * or {@code false}, you can use double quotes, for example {@code "not"}.
176.108 - * Double quotes can also be used to include non-identifier characters in
176.109 - * the name of an attribute, for example {@code "attribute-name-with-hyphens"}.
176.110 - * To include the double quote character in the attribute name, write it
176.111 - * twice. {@code "foo""bar""baz"} represents the attribute called
176.112 - * {@code foo"bar"baz}.
176.113 - *
176.114 - * <p>String constants are written with single quotes like {@code 'this'}. A
176.115 - * single quote within a string constant must be doubled, for example
176.116 - * {@code 'can''t'}.</p>
176.117 - *
176.118 - * <p>Integer constants are written as a sequence of decimal digits,
176.119 - * optionally preceded by a plus or minus sign. An integer constant must be
176.120 - * a valid input to {@link Long#valueOf(String)}.</p>
176.121 - *
176.122 - * <p>Floating-point constants are written using the Java syntax. A
176.123 - * floating-point constant must be a valid input to
176.124 - * {@link Double#valueOf(String)}.</p>
176.125 - *
176.126 - * <p>A boolean constant is either {@code true} or {@code false}, ignoring
176.127 - * case.</p>
176.128 - *
176.129 - * <p>Spaces cannot appear inside identifiers (unless written with double
176.130 - * quotes) or keywords or multi-character tokens such as {@code <=}. Spaces can
176.131 - * appear anywhere else, but are not required except to separate tokens. For
176.132 - * example, the query {@code a < b and 5 = c} could also be written {@code a<b
176.133 - * and 5=c}, but no further spaces can be removed.</p>
176.134 - *
176.135 - *
176.136 - * <h4 id="grammar-ql">Grammar</h4>
176.137 - *
176.138 - * <dl>
176.139 - * <dt id="query">query:
176.140 - * <dd><a href="#andquery">andquery</a> [<b>OR</b> <a href="#query">query</a>]
176.141 - *
176.142 - * <dt id="andquery">andquery:
176.143 - * <dd><a href="#predicate">predicate</a> [<b>AND</b> <a href="#andquery">andquery</a>]
176.144 - *
176.145 - * <dt id="predicate">predicate:
176.146 - * <dd><b>(</b> <a href="#query">query</a> <b>)</b> |<br>
176.147 - * <b>NOT</b> <a href="#predicate">predicate</a> |<br>
176.148 - * <b>INSTANCEOF</b> <a href="#stringvalue">stringvalue</a> |<br>
176.149 - * <b>LIKE</b> <a href="#objectnamepattern">objectnamepattern</a> |<br>
176.150 - * <a href="#value">value</a> <a href="#predrhs">predrhs</a>
176.151 - *
176.152 - * <dt id="predrhs">predrhs:
176.153 - * <dd><a href="#compare">compare</a> <a href="#value">value</a> |<br>
176.154 - * [<b>NOT</b>] <b>BETWEEN</b> <a href="#value">value</a> <b>AND</b>
176.155 - * <a href="#value">value</a> |<br>
176.156 - * [<b>NOT</b>] <b>IN (</b> <a href="#value">value</a>
176.157 - * <a href="#commavalues">commavalues</a> <b>)</b> |<br>
176.158 - * [<b>NOT</b>] <b>LIKE</b> <a href="#stringvalue">stringvalue</a>
176.159 - *
176.160 - * <dt id="commavalues">commavalues:
176.161 - * <dd>[ <b>,</b> <a href="#value">value</a> <a href="#commavalues">commavalues</a> ]
176.162 - *
176.163 - * <dt id="compare">compare:
176.164 - * <dd><b>=</b> | <b><</b> | <b>></b> |
176.165 - * <b><=</b> | <b>>=</b> | <b><></b> | <b>!=</b>
176.166 - *
176.167 - * <dt id="value">value:
176.168 - * <dd><a href="#factor">factor</a> [<a href="#plusorminus">plusorminus</a>
176.169 - * <a href="#value">value</a>]
176.170 - *
176.171 - * <dt id="plusorminus">plusorminus:
176.172 - * <dd><b>+</b> | <b>-</b>
176.173 - *
176.174 - * <dt id="factor">factor:
176.175 - * <dd><a href="#term">term</a> [<a href="#timesordivide">timesordivide</a>
176.176 - * <a href="#factor">factor</a>]
176.177 - *
176.178 - * <dt id="timesordivide">timesordivide:
176.179 - * <dd><b>*</b> | <b>/</b>
176.180 - *
176.181 - * <dt id="term">term:
176.182 - * <dd><a href="#attr">attr</a> | <a href="#literal">literal</a> |
176.183 - * <b>(</b> <a href="#value">value</a> <b>)</b>
176.184 - *
176.185 - * <dt id="attr">attr:
176.186 - * <dd><a href="#name">name</a> [<b>#</b> <a href="#name">name</a>]
176.187 - *
176.188 - * <dt id="name">name:
176.189 - * <dd><a href="#identifier">identifier</a> [<b>.</b><a href="#name">name</a>]
176.190 - *
176.191 - * <dt id="identifier">identifier:
176.192 - * <dd><i>Java-identifier</i> | <i>double-quoted-identifier</i>
176.193 - *
176.194 - * <dt id="literal">literal:
176.195 - * <dd><a href="#booleanlit">booleanlit</a> | <i>longlit</i> |
176.196 - * <i>doublelit</i> | <i>stringlit</i>
176.197 - *
176.198 - * <dt id="booleanlit">booleanlit:
176.199 - * <dd><b>FALSE</b> | <b>TRUE</b>
176.200 - *
176.201 - * <dt id="stringvalue">stringvalue:
176.202 - * <dd><i>stringlit</i>
176.203 - *
176.204 - * <dt id="objectnamepattern">objectnamepattern:
176.205 - * <dd><i>stringlit</i>
176.206 - *
176.207 - * </dl>
176.208 - *
176.209 - *
176.210 - * <h4>Semantics</h4>
176.211 - *
176.212 - * <p>The meaning of the grammar is described in the table below.
176.213 - * This defines a function <i>q</i> that maps a string to a Java object
176.214 - * such as a {@link QueryExp} or a {@link ValueExp}.</p>
176.215 - *
176.216 - * <table border="1" cellpadding="5">
176.217 - * <tr><th>String <i>s</i></th><th><i>q(s)</th></tr>
176.218 - *
176.219 - * <tr><td><i>query1</i> <b>OR</b> <i>query2</i>
176.220 - * <td>{@link Query#or Query.or}(<i>q(query1)</i>, <i>q(query2)</i>)
176.221 - *
176.222 - * <tr><td><i>query1</i> <b>AND</b> <i>query2</i>
176.223 - * <td>{@link Query#and Query.and}(<i>q(query1)</i>, <i>q(query2)</i>)
176.224 - *
176.225 - * <tr><td><b>(</b> <i>queryOrValue</i> <b>)</b>
176.226 - * <td><i>q(queryOrValue)</i>
176.227 - *
176.228 - * <tr><td><b>NOT</b> <i>query</i>
176.229 - * <td>{@link Query#not Query.not}(<i>q(query)</i>)
176.230 - *
176.231 - * <tr><td><b>INSTANCEOF</b> <i>stringLiteral</i>
176.232 - * <td>{@link Query#isInstanceOf Query.isInstanceOf}(<!--
176.233 - * -->{@link Query#value(String) Query.value}(<i>q(stringLiteral)</i>))
176.234 - *
176.235 - * <tr><td><b>LIKE</b> <i>stringLiteral</i>
176.236 - * <td>{@link ObjectName#ObjectName(String) new ObjectName}(<!--
176.237 - * --><i>q(stringLiteral)</i>)
176.238 - *
176.239 - * <tr><td><i>value1</i> <b>=</b> <i>value2</i>
176.240 - * <td>{@link Query#eq Query.eq}(<i>q(value1)</i>, <i>q(value2)</i>)
176.241 - *
176.242 - * <tr><td><i>value1</i> <b><</b> <i>value2</i>
176.243 - * <td>{@link Query#lt Query.lt}(<i>q(value1)</i>, <i>q(value2)</i>)
176.244 - *
176.245 - * <tr><td><i>value1</i> <b>></b> <i>value2</i>
176.246 - * <td>{@link Query#gt Query.gt}(<i>q(value1)</i>, <i>q(value2)</i>)
176.247 - *
176.248 - * <tr><td><i>value1</i> <b><=</b> <i>value2</i>
176.249 - * <td>{@link Query#leq Query.leq}(<i>q(value1)</i>, <i>q(value2)</i>)
176.250 - *
176.251 - * <tr><td><i>value1</i> <b>>=</b> <i>value2</i>
176.252 - * <td>{@link Query#geq Query.geq}(<i>q(value1)</i>, <i>q(value2)</i>)
176.253 - *
176.254 - * <tr><td><i>value1</i> <b><></b> <i>value2</i>
176.255 - * <td>{@link Query#not Query.not}({@link Query#eq Query.eq}(<!--
176.256 - * --><i>q(value1)</i>, <i>q(value2)</i>))
176.257 - *
176.258 - * <tr><td><i>value1</i> <b>!=</b> <i>value2</i>
176.259 - * <td>{@link Query#not Query.not}({@link Query#eq Query.eq}(<!--
176.260 - * --><i>q(value1)</i>, <i>q(value2)</i>))
176.261 - *
176.262 - * <tr><td><i>value1</i> <b>BETWEEN</b> <i>value2</i> AND <i>value3</i>
176.263 - * <td>{@link Query#between Query.between}(<i>q(value1)</i>,
176.264 - * <i>q(value2)</i>, <i>q(value3)</i>)
176.265 - *
176.266 - * <tr><td><i>value1</i> <b>NOT BETWEEN</b> <i>value2</i> AND <i>value3</i>
176.267 - * <td>{@link Query#not Query.not}({@link Query#between Query.between}(<!--
176.268 - * --><i>q(value1)</i>, <i>q(value2)</i>, <i>q(value3)</i>))
176.269 - *
176.270 - * <tr><td><i>value1</i> <b>IN (</b> <i>value2</i>, <i>value3</i> <b>)</b>
176.271 - * <td>{@link Query#in Query.in}(<i>q(value1)</i>,
176.272 - * <code>new ValueExp[] {</code>
176.273 - * <i>q(value2)</i>, <i>q(value3)</i><code>}</code>)
176.274 - *
176.275 - * <tr><td><i>value1</i> <b>NOT IN (</b> <i>value2</i>, <i>value3</i> <b>)</b>
176.276 - * <td>{@link Query#not Query.not}({@link Query#in Query.in}(<i>q(value1)</i>,
176.277 - * <code>new ValueExp[] {</code>
176.278 - * <i>q(value2)</i>, <i>q(value3)</i><code>}</code>))
176.279 - *
176.280 - * <tr><td><i>value</i> <b>LIKE</b> <i>stringLiteral</i>
176.281 - * <td>{@link Query#match Query.match}(<i>q(value)</i>,
176.282 - * <i>q(stringLiteral)</i>)
176.283 - *
176.284 - * <tr><td><i>value</i> <b>NOT LIKE</b> <i>stringLiteral</i>
176.285 - * <td>{@link Query#not Query.not}({@link Query#match Query.match}(<i>q(value)</i>,
176.286 - * <i>q(stringLiteral)</i>))
176.287 - *
176.288 - * <tr><td><i>value1</i> <b>+</b> <i>value2</i>
176.289 - * <td>{@link Query#plus Query.plus}(<i>q(value1)</i>, <i>q(value2)</i>)
176.290 - *
176.291 - * <tr><td><i>value1</i> <b>-</b> <i>value2</i>
176.292 - * <td>{@link Query#minus Query.minus}(<i>q(value1)</i>, <i>q(value2)</i>)
176.293 - *
176.294 - * <tr><td><i>value1</i> <b>*</b> <i>value2</i>
176.295 - * <td>{@link Query#times Query.times}(<i>q(value1)</i>, <i>q(value2)</i>)
176.296 - *
176.297 - * <tr><td><i>value1</i> <b>/</b> <i>value2</i>
176.298 - * <td>{@link Query#div Query.div}(<i>q(value1)</i>, <i>q(value2)</i>)
176.299 - *
176.300 - * <tr><td><i>name</i>
176.301 - * <td>{@link Query#attr(String) Query.attr}(<i>q(name)</i>)
176.302 - *
176.303 - * <tr><td><i>name1<b>#</b>name2</i>
176.304 - * <td>{@link Query#attr(String,String) Query.attr}(<i>q(name1)</i>,
176.305 - * <i>q(name2)</i>)
176.306 - *
176.307 - * <tr><td><b>FALSE</b>
176.308 - * <td>{@link Query#value(boolean) Query.value}(false)
176.309 - *
176.310 - * <tr><td><b>TRUE</b>
176.311 - * <td>{@link Query#value(boolean) Query.value}(true)
176.312 - *
176.313 - * <tr><td><i>decimalLiteral</i>
176.314 - * <td>{@link Query#value(long) Query.value}(<!--
176.315 - * -->{@link Long#valueOf(String) Long.valueOf}(<i>decimalLiteral</i>))
176.316 - *
176.317 - * <tr><td><i>floatingPointLiteral</i>
176.318 - * <td>{@link Query#value(double) Query.value}(<!--
176.319 - * -->{@link Double#valueOf(String) Double.valueOf}(<!--
176.320 - * --><i>floatingPointLiteral</i>))
176.321 - * </table>
176.322 - *
176.323 * @since 1.5
176.324 */
176.325 public class Query extends Object {
176.326 @@ -600,6 +291,11 @@
176.327 * <p>Returns a new attribute expression. See {@link AttributeValueExp}
176.328 * for a detailed description of the semantics of the expression.</p>
176.329 *
176.330 + * <p>Evaluating this expression for a given
176.331 + * <code>objectName</code> includes performing {@link
176.332 + * MBeanServer#getAttribute MBeanServer.getAttribute(objectName,
176.333 + * name)}.</p>
176.334 + *
176.335 * @param name The name of the attribute.
176.336 *
176.337 * @return An attribute expression for the attribute named {@code name}.
176.338 @@ -944,73 +640,6 @@
176.339 }
176.340
176.341 /**
176.342 - * <p>Return a string representation of the given query. The string
176.343 - * returned by this method can be converted back into an equivalent
176.344 - * query using {@link #fromString fromString}.</p>
176.345 - *
176.346 - * <p>(Two queries are equivalent if they produce the same result in
176.347 - * all cases. Equivalent queries are not necessarily identical:
176.348 - * for example the queries {@code Query.lt(Query.attr("A"), Query.attr("B"))}
176.349 - * and {@code Query.not(Query.ge(Query.attr("A"), Query.attr("B")))} are
176.350 - * equivalent but not identical.)</p>
176.351 - *
176.352 - * <p>The string returned by this method is only guaranteed to be converted
176.353 - * back into an equivalent query if {@code query} was constructed, or
176.354 - * could have been constructed, using the methods of this class.
176.355 - * If you make a custom query {@code myQuery} by implementing
176.356 - * {@link QueryExp} yourself then the result of
176.357 - * {@code Query.toString(myQuery)} is unspecified.</p>
176.358 - *
176.359 - * @param query the query to convert. If it is null, the result will
176.360 - * also be null.
176.361 - * @return the string representation of the query, or null if the
176.362 - * query is null.
176.363 - *
176.364 - * @since 1.7
176.365 - */
176.366 - public static String toString(QueryExp query) {
176.367 - if (query == null)
176.368 - return null;
176.369 -
176.370 - // This is ugly. At one stage we had a non-public class called
176.371 - // ToQueryString with the toQueryString() method, and every class
176.372 - // mentioned here inherited from that class. But that interfered
176.373 - // with serialization of custom subclasses of e.g. QueryEval. Even
176.374 - // though we could make it work by adding a public constructor to this
176.375 - // non-public class, that seemed fragile because according to the
176.376 - // serialization spec it shouldn't work. If only non-public interfaces
176.377 - // could have non-public methods.
176.378 - if (query instanceof ObjectName)
176.379 - return ((ObjectName) query).toQueryString();
176.380 - if (query instanceof QueryEval)
176.381 - return ((QueryEval) query).toQueryString();
176.382 -
176.383 - return query.toString();
176.384 - }
176.385 -
176.386 - /**
176.387 - * <p>Produce a query from the given string. The query returned
176.388 - * by this method can be converted back into a string using
176.389 - * {@link #toString(QueryExp) toString}. The resultant string will
176.390 - * not necessarily be equal to {@code s}.</p>
176.391 - *
176.392 - * @param s the string to convert.
176.393 - *
176.394 - * @return a {@code QueryExp} derived by parsing the string, or
176.395 - * null if the string is null.
176.396 - *
176.397 - * @throws IllegalArgumentException if the string is not a valid
176.398 - * query string.
176.399 - *
176.400 - * @since 1.7
176.401 - */
176.402 - public static QueryExp fromString(String s) {
176.403 - if (s == null)
176.404 - return null;
176.405 - return new QueryParser(s).parseQuery();
176.406 - }
176.407 -
176.408 - /**
176.409 * Utility method to escape strings used with
176.410 * Query.{initial|any|final}SubString() methods.
176.411 */
177.1 --- a/src/share/classes/javax/management/QueryEval.java Mon Nov 23 10:04:47 2009 +0000
177.2 +++ b/src/share/classes/javax/management/QueryEval.java Wed Nov 25 11:08:25 2009 -0800
177.3 @@ -75,10 +75,4 @@
177.4 public static MBeanServer getMBeanServer() {
177.5 return server.get();
177.6 }
177.7 -
177.8 - // Subclasses in this package can override this method to return a different
177.9 - // string.
177.10 - String toQueryString() {
177.11 - return toString();
177.12 - }
177.13 }
178.1 --- a/src/share/classes/javax/management/QueryNotificationFilter.java Mon Nov 23 10:04:47 2009 +0000
178.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
178.3 @@ -1,415 +0,0 @@
178.4 -/*
178.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
178.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
178.7 - *
178.8 - * This code is free software; you can redistribute it and/or modify it
178.9 - * under the terms of the GNU General Public License version 2 only, as
178.10 - * published by the Free Software Foundation. Sun designates this
178.11 - * particular file as subject to the "Classpath" exception as provided
178.12 - * by Sun in the LICENSE file that accompanied this code.
178.13 - *
178.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
178.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
178.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
178.17 - * version 2 for more details (a copy is included in the LICENSE file that
178.18 - * accompanied this code).
178.19 - *
178.20 - * You should have received a copy of the GNU General Public License version
178.21 - * 2 along with this work; if not, write to the Free Software Foundation,
178.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
178.23 - *
178.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
178.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
178.26 - * have any questions.
178.27 - */
178.28 -
178.29 -package javax.management;
178.30 -
178.31 -import com.sun.jmx.mbeanserver.NotificationMBeanSupport;
178.32 -import java.lang.reflect.InvocationHandler;
178.33 -import java.lang.reflect.InvocationTargetException;
178.34 -import java.lang.reflect.Method;
178.35 -import java.lang.reflect.Proxy;
178.36 -import java.util.Collections;
178.37 -import java.util.Set;
178.38 -
178.39 -/**
178.40 - * <p>General-purpose notification filter. This filter can be used to
178.41 - * filter notifications from a possibly-remote MBean. Most filtering
178.42 - * decisions can be coded using this filter, which avoids having to
178.43 - * write a custom implementation of the {@link NotificationFilter}
178.44 - * class. Writing a custom implementation requires you to deploy it
178.45 - * on both the client and the server in the remote case, so using this class
178.46 - * instead is recommended where possible.</p>
178.47 - *
178.48 - * <p>Because this class was introduced in version 2.0 of the JMX API,
178.49 - * it may not be present on a remote JMX agent that is running an earlier
178.50 - * version. The method {@link JMX#getSpecificationVersion
178.51 - * JMX.getSpecificationVersion} can be used to determine the remote version.</p>
178.52 - *
178.53 - * <p>This class uses the {@linkplain Query Query API} to specify the
178.54 - * filtering logic. For example, to select only notifications where the
178.55 - * {@linkplain Notification#getType() type} is {@code "com.example.mytype"},
178.56 - * you could use</p>
178.57 - *
178.58 - * <pre>
178.59 - * NotificationFilter filter =
178.60 - * new QueryNotificationFilter("Type = 'com.example.mytype'");
178.61 - * </pre>
178.62 - *
178.63 - * <p>or equivalently</p>
178.64 - *
178.65 - * <pre>
178.66 - * NotificationFilter filter =
178.67 - * new QueryNotificationFilter(
178.68 - * Query.eq(Query.attr("Type"), Query.value("com.example.mytype")));
178.69 - * </pre>
178.70 - *
178.71 - * <p>(This particular example could also use
178.72 - * {@link NotificationFilterSupport}.)</p>
178.73 - *
178.74 - * <p>Here are some other examples of filters you can specify with this class.</p>
178.75 - *
178.76 - * <dl>
178.77 - *
178.78 - * <dt>{@code QueryNotificationFilter("Type = 'com.example.type1' or
178.79 - * Type = 'com.example.type2'")}
178.80 - * <dd>Notifications where the type is either of the given strings.
178.81 - *
178.82 - * <dt>{@code QueryNotificationFilter("Type in ('com.example.type1',
178.83 - * 'com.example.type2')")}
178.84 - * <dd>Another way to write the previous example.
178.85 - *
178.86 - * <dt>{@code QueryNotificationFilter("SequenceNumber > 1000")}
178.87 - * <dd>Notifications where the {@linkplain Notification#getSequenceNumber()
178.88 - * sequence number} is greater than 1000.
178.89 - *
178.90 - * <dt>{@code QueryNotificationFilter(AttributeChangeNotification.class, null)}
178.91 - * <dd>Notifications where the notification class is
178.92 - * {@link AttributeChangeNotification} or a subclass of it.
178.93 - *
178.94 - * <dt>{@code QueryNotificationFilter(AttributeChangeNotification.class,
178.95 - * "AttributeName = 'Size'")}
178.96 - * <dd>Notifications where the notification class is
178.97 - * {@link AttributeChangeNotification} or a subclass, and where the
178.98 - * {@linkplain AttributeChangeNotification#getAttributeName() name of the
178.99 - * changed attribute} is {@code Size}.
178.100 - *
178.101 - * <dt>{@code QueryNotificationFilter(AttributeChangeNotification.class,
178.102 - * "AttributeName = 'Size' and NewValue - OldValue > 100")}
178.103 - * <dd>As above, but the difference between the
178.104 - * {@linkplain AttributeChangeNotification#getNewValue() new value} and the
178.105 - * {@linkplain AttributeChangeNotification#getOldValue() old value} must be
178.106 - * greater than 100.
178.107 - *
178.108 - * <dt>{@code QueryNotificationFilter("like 'com.example.mydomain:*'")}
178.109 - * <dd>Notifications where the {@linkplain Notification#getSource() source}
178.110 - * is an ObjectName that matches the pattern.
178.111 - *
178.112 - * <dt>{@code QueryNotificationFilter("Source.canonicalName like
178.113 - * 'com.example.mydomain:%'")}
178.114 - * <dd>Another way to write the previous example.
178.115 - *
178.116 - * <dt>{@code QueryNotificationFilter(MBeanServerNotification.class,
178.117 - * "Type = 'JMX.mbean.registered' and MBeanName.canonicalName like
178.118 - * 'com.example.mydomain:%'")}
178.119 - * <dd>Notifications of class {@link MBeanServerNotification} representing
178.120 - * an object registered in the domain {@code com.example.mydomain}.
178.121 - *
178.122 - * </dl>
178.123 - *
178.124 - * <h4>How it works</h4>
178.125 - *
178.126 - * <p>Although the examples above are clear, looking closely at the
178.127 - * Query API reveals a subtlety. A {@link QueryExp} is evaluated on
178.128 - * an {@link ObjectName}, not a {@code Notification}.</p>
178.129 - *
178.130 - * <p>Every time a {@code Notification} is to be filtered by a
178.131 - * {@code QueryNotificationFilter}, a special {@link MBeanServer} is created.
178.132 - * This {@code MBeanServer} contains exactly one MBean, which represents the
178.133 - * {@code Notification}. If the {@linkplain Notification#getSource()
178.134 - * source} of the notification is an {@code ObjectName}, which is
178.135 - * recommended practice, then the name of the MBean representing the
178.136 - * {@code Notification} will be this {@code ObjectName}. Otherwise the
178.137 - * name is unspecified.</p>
178.138 - *
178.139 - * <p>The query specified in the {@code QueryNotificationFilter} constructor
178.140 - * is evaluated against this {@code MBeanServer} and {@code ObjectName},
178.141 - * and the filter returns true if and only if the query does. If the
178.142 - * query throws an exception, then the filter will return false.</p>
178.143 - *
178.144 - * <p>The MBean representing the {@code Notification} has one attribute for
178.145 - * every property of the {@code Notification}. Specifically, for every public
178.146 - * method {@code T getX()} in the {@code NotificationClass}, the MBean will
178.147 - * have an attribute called {@code X} of type {@code T}. For example, if the
178.148 - * {@code Notification} is an {@code AttributeChangeNotification}, then the
178.149 - * MBean will have an attribute called {@code AttributeName} of type
178.150 - * {@code "java.lang.String"}, corresponding to the method {@link
178.151 - * AttributeChangeNotification#getAttributeName}.</p>
178.152 - *
178.153 - * <p>Query evaluation usually involves calls to the methods of {@code
178.154 - * MBeanServer}. The methods have the following behavior:</p>
178.155 - *
178.156 - * <ul>
178.157 - * <li>The {@link MBeanServer#getAttribute getAttribute} method returns the
178.158 - * value of the corresponding property.
178.159 - * <li>The {@link MBeanServer#getObjectInstance getObjectInstance}
178.160 - * method returns an {@link ObjectInstance} where the {@link
178.161 - * ObjectInstance#getObjectName ObjectName} is the name of the MBean and the
178.162 - * {@link ObjectInstance#getClassName ClassName} is the class name of the
178.163 - * {@code Notification}.
178.164 - * <li>The {@link MBeanServer#isInstanceOf isInstanceOf} method returns true
178.165 - * if and only if the {@code Notification}'s {@code ClassLoader} can load the
178.166 - * named class, and the {@code Notification} is an {@linkplain Class#isInstance
178.167 - * instance} of that class.
178.168 - * </ul>
178.169 - *
178.170 - * <p>These are the only {@code MBeanServer} methods that are needed to
178.171 - * evaluate standard queries. The behavior of the other {@code MBeanServer}
178.172 - * methods is unspecified.</p>
178.173 - *
178.174 - * @since 1.7
178.175 - */
178.176 -public class QueryNotificationFilter implements NotificationFilter {
178.177 - private static final long serialVersionUID = -8408613922660635231L;
178.178 -
178.179 - private static final ObjectName DEFAULT_NAME =
178.180 - ObjectName.valueOf(":type=Notification");
178.181 - private static final QueryExp trueQuery;
178.182 - static {
178.183 - ValueExp zero = Query.value(0);
178.184 - trueQuery = Query.eq(zero, zero);
178.185 - }
178.186 -
178.187 - private final QueryExp query;
178.188 -
178.189 - /**
178.190 - * Construct a {@code QueryNotificationFilter} that evaluates the given
178.191 - * {@code QueryExp} to determine whether to accept a notification.
178.192 - *
178.193 - * @param query the {@code QueryExp} to evaluate. Can be null,
178.194 - * in which case all notifications are accepted.
178.195 - */
178.196 - public QueryNotificationFilter(QueryExp query) {
178.197 - if (query == null)
178.198 - this.query = trueQuery;
178.199 - else
178.200 - this.query = query;
178.201 - }
178.202 -
178.203 - /**
178.204 - * Construct a {@code QueryNotificationFilter} that evaluates the query
178.205 - * in the given string to determine whether to accept a notification.
178.206 - * The string is converted into a {@code QueryExp} using
178.207 - * {@link Query#fromString Query.fromString}.
178.208 - *
178.209 - * @param query the string specifying the query to evaluate. Can be null,
178.210 - * in which case all notifications are accepted.
178.211 - *
178.212 - * @throws IllegalArgumentException if the string is not a valid
178.213 - * query string.
178.214 - */
178.215 - public QueryNotificationFilter(String query) {
178.216 - this(Query.fromString(query));
178.217 - }
178.218 -
178.219 - /**
178.220 - * <p>Construct a {@code QueryNotificationFilter} that evaluates the query
178.221 - * in the given string to determine whether to accept a notification,
178.222 - * and where the notification must also be an instance of the given class.
178.223 - * The string is converted into a {@code QueryExp} using
178.224 - * {@link Query#fromString Query.fromString}.</p>
178.225 - *
178.226 - * @param notifClass the class that the notification must be an instance of.
178.227 - * Cannot be null.
178.228 - *
178.229 - * @param query the string specifying the query to evaluate. Can be null,
178.230 - * in which case all notifications are accepted.
178.231 - *
178.232 - * @throws IllegalArgumentException if the string is not a valid
178.233 - * query string, or if {@code notifClass} is null.
178.234 - */
178.235 - public QueryNotificationFilter(
178.236 - Class<? extends Notification> notifClass, String query) {
178.237 - this(Query.and(Query.isInstanceOf(Query.value(notNull(notifClass).getName())),
178.238 - Query.fromString(query)));
178.239 - }
178.240 -
178.241 - private static <T> T notNull(T x) {
178.242 - if (x == null)
178.243 - throw new IllegalArgumentException("Null argument");
178.244 - return x;
178.245 - }
178.246 -
178.247 - /**
178.248 - * Retrieve the query that this notification filter will evaluate for
178.249 - * each notification.
178.250 - *
178.251 - * @return the query.
178.252 - */
178.253 - public QueryExp getQuery() {
178.254 - return query;
178.255 - }
178.256 -
178.257 - public boolean isNotificationEnabled(Notification notification) {
178.258 - ObjectName name;
178.259 -
178.260 - Object source = notification.getSource();
178.261 - if (source instanceof ObjectName)
178.262 - name = (ObjectName) source;
178.263 - else
178.264 - name = DEFAULT_NAME;
178.265 -
178.266 - MBS mbsImpl = new MBS(notification, name);
178.267 - MBeanServer mbs = (MBeanServer) Proxy.newProxyInstance(
178.268 - MBeanServer.class.getClassLoader(),
178.269 - new Class<?>[] {MBeanServer.class},
178.270 - new ForwardIH(mbsImpl));
178.271 - return evalQuery(query, mbs, name);
178.272 - }
178.273 -
178.274 - private static boolean evalQuery(
178.275 - QueryExp query, MBeanServer mbs, ObjectName name) {
178.276 - MBeanServer oldMBS = QueryEval.getMBeanServer();
178.277 - try {
178.278 - if (mbs != null)
178.279 - query.setMBeanServer(mbs);
178.280 - return query.apply(name);
178.281 - } catch (Exception e) {
178.282 - return false;
178.283 - } finally {
178.284 - query.setMBeanServer(oldMBS);
178.285 - }
178.286 - }
178.287 -
178.288 - private static class ForwardIH implements InvocationHandler {
178.289 - private final MBS mbs;
178.290 -
178.291 - ForwardIH(MBS mbs) {
178.292 - this.mbs = mbs;
178.293 - }
178.294 -
178.295 - public Object invoke(Object proxy, Method method, Object[] args)
178.296 - throws Throwable {
178.297 - Method forward;
178.298 - try {
178.299 - forward = MBS.class.getMethod(
178.300 - method.getName(), method.getParameterTypes());
178.301 - } catch (NoSuchMethodException e) {
178.302 - throw new UnsupportedOperationException(method.getName());
178.303 - }
178.304 - try {
178.305 - return forward.invoke(mbs, args);
178.306 - } catch (InvocationTargetException e) {
178.307 - throw e.getCause();
178.308 - }
178.309 - }
178.310 - }
178.311 -
178.312 - private static class MBS {
178.313 - private final Notification notification;
178.314 - private final ObjectName objectName;
178.315 - private final ObjectInstance objectInstance;
178.316 - private volatile DynamicMBean mbean;
178.317 -
178.318 - MBS(Notification n, ObjectName name) {
178.319 - this.notification = n;
178.320 - this.objectName = name;
178.321 - this.objectInstance = new ObjectInstance(name, n.getClass().getName());
178.322 - }
178.323 -
178.324 - private void checkName(ObjectName name) throws InstanceNotFoundException {
178.325 - if (!objectName.equals(name))
178.326 - throw new InstanceNotFoundException(String.valueOf(name));
178.327 - }
178.328 -
178.329 - private DynamicMBean mbean(ObjectName name)
178.330 - throws InstanceNotFoundException, ReflectionException {
178.331 - if (mbean == null) {
178.332 - try {
178.333 - mbean = new NotificationMBeanSupport(notification);
178.334 - } catch (NotCompliantMBeanException e) {
178.335 - throw new ReflectionException(e);
178.336 - }
178.337 - }
178.338 - return mbean;
178.339 - }
178.340 -
178.341 - public ObjectInstance getObjectInstance(ObjectName name)
178.342 - throws InstanceNotFoundException {
178.343 - checkName(name);
178.344 - return objectInstance;
178.345 - }
178.346 -
178.347 - public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
178.348 - Set<ObjectName> names = queryNames(name, query);
178.349 - switch (names.size()) {
178.350 - case 0:
178.351 - return Collections.emptySet();
178.352 - case 1:
178.353 - return Collections.singleton(objectInstance);
178.354 - default:
178.355 - throw new UnsupportedOperationException("Internal error");
178.356 - }
178.357 - }
178.358 -
178.359 - public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
178.360 - if ((name != null && !name.apply(objectName)) ||
178.361 - (query != null && !evalQuery(query, null, name)))
178.362 - return Collections.emptySet();
178.363 - return Collections.singleton(objectName);
178.364 - }
178.365 -
178.366 - public boolean isRegistered(ObjectName name) {
178.367 - return objectName.equals(name);
178.368 - }
178.369 -
178.370 - public Integer getMBeanCount() {
178.371 - return 1;
178.372 - }
178.373 -
178.374 - public Object getAttribute(ObjectName name, String attribute)
178.375 - throws MBeanException, AttributeNotFoundException,
178.376 - InstanceNotFoundException, ReflectionException {
178.377 - return mbean(name).getAttribute(attribute);
178.378 - }
178.379 -
178.380 - public AttributeList getAttributes(ObjectName name, String[] attributes)
178.381 - throws InstanceNotFoundException, ReflectionException {
178.382 - return mbean(name).getAttributes(attributes);
178.383 - }
178.384 -
178.385 - public String getDefaultDomain() {
178.386 - return objectName.getDomain();
178.387 - }
178.388 -
178.389 - public String[] getDomains() {
178.390 - return new String[] {objectName.getDomain()};
178.391 - }
178.392 -
178.393 - public MBeanInfo getMBeanInfo(ObjectName name)
178.394 - throws InstanceNotFoundException, ReflectionException {
178.395 - return mbean(name).getMBeanInfo();
178.396 - }
178.397 -
178.398 - public boolean isInstanceOf(ObjectName name, String className)
178.399 - throws InstanceNotFoundException {
178.400 - try {
178.401 - mbean(name);
178.402 - ClassLoader loader = notification.getClass().getClassLoader();
178.403 - Class<?> c = Class.forName(className, false, loader);
178.404 - return c.isInstance(notification);
178.405 - } catch (ReflectionException e) {
178.406 - return false;
178.407 - } catch (ClassNotFoundException e) {
178.408 - return false;
178.409 - }
178.410 - }
178.411 -
178.412 - public ClassLoader getClassLoaderFor(ObjectName mbeanName)
178.413 - throws InstanceNotFoundException {
178.414 - checkName(mbeanName);
178.415 - return notification.getClass().getClassLoader();
178.416 - }
178.417 - }
178.418 -}
179.1 --- a/src/share/classes/javax/management/QueryParser.java Mon Nov 23 10:04:47 2009 +0000
179.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
179.3 @@ -1,626 +0,0 @@
179.4 -/*
179.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
179.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
179.7 - *
179.8 - * This code is free software; you can redistribute it and/or modify it
179.9 - * under the terms of the GNU General Public License version 2 only, as
179.10 - * published by the Free Software Foundation. Sun designates this
179.11 - * particular file as subject to the "Classpath" exception as provided
179.12 - * by Sun in the LICENSE file that accompanied this code.
179.13 - *
179.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
179.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
179.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
179.17 - * version 2 for more details (a copy is included in the LICENSE file that
179.18 - * accompanied this code).
179.19 - *
179.20 - * You should have received a copy of the GNU General Public License version
179.21 - * 2 along with this work; if not, write to the Free Software Foundation,
179.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
179.23 - *
179.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
179.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
179.26 - * have any questions.
179.27 - */
179.28 -
179.29 -package javax.management;
179.30 -
179.31 -import java.util.ArrayList;
179.32 -import java.util.Formatter;
179.33 -import java.util.List;
179.34 -import java.util.Set;
179.35 -import java.util.TreeSet;
179.36 -
179.37 -/**
179.38 - * <p>Parser for JMX queries represented in an SQL-like language.</p>
179.39 - */
179.40 -/*
179.41 - * Note that if a query starts with ( then we don't know whether it is
179.42 - * a predicate or just a value that is parenthesized. So, inefficiently,
179.43 - * we try to parse a predicate and if that doesn't work we try to parse
179.44 - * a value.
179.45 - */
179.46 -class QueryParser {
179.47 - // LEXER STARTS HERE
179.48 -
179.49 - private static class Token {
179.50 - final String string;
179.51 - Token(String s) {
179.52 - this.string = s;
179.53 - }
179.54 -
179.55 - @Override
179.56 - public String toString() {
179.57 - return string;
179.58 - }
179.59 - }
179.60 -
179.61 - private static final Token
179.62 - END = new Token("<end of string>"),
179.63 - LPAR = new Token("("), RPAR = new Token(")"),
179.64 - COMMA = new Token(","), DOT = new Token("."), SHARP = new Token("#"),
179.65 - PLUS = new Token("+"), MINUS = new Token("-"),
179.66 - TIMES = new Token("*"), DIVIDE = new Token("/"),
179.67 - LT = new Token("<"), GT = new Token(">"),
179.68 - LE = new Token("<="), GE = new Token(">="),
179.69 - NE = new Token("<>"), EQ = new Token("="),
179.70 - NOT = new Id("NOT"), INSTANCEOF = new Id("INSTANCEOF"),
179.71 - FALSE = new Id("FALSE"), TRUE = new Id("TRUE"),
179.72 - BETWEEN = new Id("BETWEEN"), AND = new Id("AND"),
179.73 - OR = new Id("OR"), IN = new Id("IN"),
179.74 - LIKE = new Id("LIKE"), CLASS = new Id("CLASS");
179.75 -
179.76 - // Keywords that can appear where an identifier can appear.
179.77 - // If an attribute is one of these, then it must be quoted when
179.78 - // converting a query into a string.
179.79 - // We use a TreeSet so we can look up case-insensitively.
179.80 - private static final Set<String> idKeywords =
179.81 - new TreeSet<String>(String.CASE_INSENSITIVE_ORDER);
179.82 - static {
179.83 - for (Token t : new Token[] {NOT, INSTANCEOF, FALSE, TRUE, LIKE, CLASS})
179.84 - idKeywords.add(t.string);
179.85 - };
179.86 -
179.87 - public static String quoteId(String id) {
179.88 - if (id.contains("\"") || idKeywords.contains(id))
179.89 - return '"' + id.replace("\"", "\"\"") + '"';
179.90 - else
179.91 - return id;
179.92 - }
179.93 -
179.94 - private static class Id extends Token {
179.95 - Id(String id) {
179.96 - super(id);
179.97 - }
179.98 -
179.99 - // All other tokens use object identity, which means e.g. that one
179.100 - // occurrence of the string constant 'x' is not the same as another.
179.101 - // For identifiers, we ignore case when testing for equality so that
179.102 - // for a keyword such as AND you can also spell it as "And" or "and".
179.103 - // But we keep the original case of the identifier, so if it's not
179.104 - // a keyword we will distinguish between the attribute Foo and the
179.105 - // attribute FOO.
179.106 - @Override
179.107 - public boolean equals(Object o) {
179.108 - return (o instanceof Id && (((Id) o).toString().equalsIgnoreCase(toString())));
179.109 - }
179.110 - }
179.111 -
179.112 - private static class QuotedId extends Token {
179.113 - QuotedId(String id) {
179.114 - super(id);
179.115 - }
179.116 -
179.117 - @Override
179.118 - public String toString() {
179.119 - return '"' + string.replace("\"", "\"\"") + '"';
179.120 - }
179.121 - }
179.122 -
179.123 - private static class StringLit extends Token {
179.124 - StringLit(String s) {
179.125 - super(s);
179.126 - }
179.127 -
179.128 - @Override
179.129 - public String toString() {
179.130 - return '\'' + string.replace("'", "''") + '\'';
179.131 - }
179.132 - }
179.133 -
179.134 - private static class LongLit extends Token {
179.135 - long number;
179.136 -
179.137 - LongLit(long number) {
179.138 - super(Long.toString(number));
179.139 - this.number = number;
179.140 - }
179.141 - }
179.142 -
179.143 - private static class DoubleLit extends Token {
179.144 - double number;
179.145 -
179.146 - DoubleLit(double number) {
179.147 - super(Double.toString(number));
179.148 - this.number = number;
179.149 - }
179.150 - }
179.151 -
179.152 - private static class Tokenizer {
179.153 - private final String s;
179.154 - private final int len;
179.155 - private int i = 0;
179.156 -
179.157 - Tokenizer(String s) {
179.158 - this.s = s;
179.159 - this.len = s.length();
179.160 - }
179.161 -
179.162 - private int thisChar() {
179.163 - if (i == len)
179.164 - return -1;
179.165 - return s.codePointAt(i);
179.166 - }
179.167 -
179.168 - private void advance() {
179.169 - i += Character.charCount(thisChar());
179.170 - }
179.171 -
179.172 - private int thisCharAdvance() {
179.173 - int c = thisChar();
179.174 - advance();
179.175 - return c;
179.176 - }
179.177 -
179.178 - Token nextToken() {
179.179 - // In this method, c is the character we're looking at, and
179.180 - // thisChar() is the character after that. Everything must
179.181 - // preserve these invariants. When we return we then have
179.182 - // thisChar() being the start of the following token, so
179.183 - // the next call to nextToken() will begin from there.
179.184 - int c;
179.185 -
179.186 - // Skip space
179.187 - do {
179.188 - if (i == len)
179.189 - return null;
179.190 - c = thisCharAdvance();
179.191 - } while (Character.isWhitespace(c));
179.192 -
179.193 - // Now c is the first character of the token, and tokenI points
179.194 - // to the character after that.
179.195 - switch (c) {
179.196 - case '(': return LPAR;
179.197 - case ')': return RPAR;
179.198 - case ',': return COMMA;
179.199 - case '.': return DOT;
179.200 - case '#': return SHARP;
179.201 - case '*': return TIMES;
179.202 - case '/': return DIVIDE;
179.203 - case '=': return EQ;
179.204 - case '-': return MINUS;
179.205 - case '+': return PLUS;
179.206 -
179.207 - case '>':
179.208 - if (thisChar() == '=') {
179.209 - advance();
179.210 - return GE;
179.211 - } else
179.212 - return GT;
179.213 -
179.214 - case '<':
179.215 - c = thisChar();
179.216 - switch (c) {
179.217 - case '=': advance(); return LE;
179.218 - case '>': advance(); return NE;
179.219 - default: return LT;
179.220 - }
179.221 -
179.222 - case '!':
179.223 - if (thisCharAdvance() != '=')
179.224 - throw new IllegalArgumentException("'!' must be followed by '='");
179.225 - return NE;
179.226 -
179.227 - case '"':
179.228 - case '\'': {
179.229 - int quote = c;
179.230 - StringBuilder sb = new StringBuilder();
179.231 - while (true) {
179.232 - while ((c = thisChar()) != quote) {
179.233 - if (c < 0) {
179.234 - throw new IllegalArgumentException(
179.235 - "Unterminated string constant");
179.236 - }
179.237 - sb.appendCodePoint(thisCharAdvance());
179.238 - }
179.239 - advance();
179.240 - if (thisChar() == quote) {
179.241 - sb.appendCodePoint(quote);
179.242 - advance();
179.243 - } else
179.244 - break;
179.245 - }
179.246 - if (quote == '\'')
179.247 - return new StringLit(sb.toString());
179.248 - else
179.249 - return new QuotedId(sb.toString());
179.250 - }
179.251 - }
179.252 -
179.253 - // Is it a numeric constant?
179.254 - if (Character.isDigit(c) || c == '.') {
179.255 - StringBuilder sb = new StringBuilder();
179.256 - int lastc = -1;
179.257 - while (true) {
179.258 - sb.appendCodePoint(c);
179.259 - c = Character.toLowerCase(thisChar());
179.260 - if (c == '+' || c == '-') {
179.261 - if (lastc != 'e')
179.262 - break;
179.263 - } else if (!Character.isDigit(c) && c != '.' && c != 'e')
179.264 - break;
179.265 - lastc = c;
179.266 - advance();
179.267 - }
179.268 - String s = sb.toString();
179.269 - if (s.indexOf('.') >= 0 || s.indexOf('e') >= 0) {
179.270 - double d = parseDoubleCheckOverflow(s);
179.271 - return new DoubleLit(d);
179.272 - } else {
179.273 - // Like the Java language, we allow the numeric constant
179.274 - // x where -x = Long.MIN_VALUE, even though x is not
179.275 - // representable as a long (it is Long.MAX_VALUE + 1).
179.276 - // Code in the parser will reject this value if it is
179.277 - // not the operand of unary minus.
179.278 - long l = -Long.parseLong("-" + s);
179.279 - return new LongLit(l);
179.280 - }
179.281 - }
179.282 -
179.283 - // It must be an identifier.
179.284 - if (!Character.isJavaIdentifierStart(c)) {
179.285 - StringBuilder sb = new StringBuilder();
179.286 - Formatter f = new Formatter(sb);
179.287 - f.format("Bad character: %c (%04x)", c, c);
179.288 - throw new IllegalArgumentException(sb.toString());
179.289 - }
179.290 -
179.291 - StringBuilder id = new StringBuilder();
179.292 - while (true) { // identifier
179.293 - id.appendCodePoint(c);
179.294 - c = thisChar();
179.295 - if (!Character.isJavaIdentifierPart(c))
179.296 - break;
179.297 - advance();
179.298 - }
179.299 -
179.300 - return new Id(id.toString());
179.301 - }
179.302 - }
179.303 -
179.304 - /* Parse a double as a Java compiler would do it, throwing an exception
179.305 - * if the input does not fit in a double. We assume that the input
179.306 - * string is not "Infinity" and does not have a leading sign.
179.307 - */
179.308 - private static double parseDoubleCheckOverflow(String s) {
179.309 - double d = Double.parseDouble(s);
179.310 - if (Double.isInfinite(d))
179.311 - throw new NumberFormatException("Overflow: " + s);
179.312 - if (d == 0.0) { // Underflow checking is hard! CR 6604864
179.313 - String ss = s;
179.314 - int e = s.indexOf('e'); // we already forced E to lowercase
179.315 - if (e > 0)
179.316 - ss = s.substring(0, e);
179.317 - ss = ss.replace("0", "").replace(".", "");
179.318 - if (!ss.equals(""))
179.319 - throw new NumberFormatException("Underflow: " + s);
179.320 - }
179.321 - return d;
179.322 - }
179.323 -
179.324 - // PARSER STARTS HERE
179.325 -
179.326 - private final List<Token> tokens;
179.327 - private int tokenI;
179.328 - // The current token is always tokens[tokenI].
179.329 -
179.330 - QueryParser(String s) {
179.331 - // Construct the complete list of tokens immediately and append
179.332 - // a sentinel (END).
179.333 - tokens = new ArrayList<Token>();
179.334 - Tokenizer tokenizer = new Tokenizer(s);
179.335 - Token t;
179.336 - while ((t = tokenizer.nextToken()) != null)
179.337 - tokens.add(t);
179.338 - tokens.add(END);
179.339 - }
179.340 -
179.341 - private Token current() {
179.342 - return tokens.get(tokenI);
179.343 - }
179.344 -
179.345 - // If the current token is t, then skip it and return true.
179.346 - // Otherwise, return false.
179.347 - private boolean skip(Token t) {
179.348 - if (t.equals(current())) {
179.349 - tokenI++;
179.350 - return true;
179.351 - }
179.352 - return false;
179.353 - }
179.354 -
179.355 - // If the current token is one of the ones in 'tokens', then skip it
179.356 - // and return its index in 'tokens'. Otherwise, return -1.
179.357 - private int skipOne(Token... tokens) {
179.358 - for (int i = 0; i < tokens.length; i++) {
179.359 - if (skip(tokens[i]))
179.360 - return i;
179.361 - }
179.362 - return -1;
179.363 - }
179.364 -
179.365 - // If the current token is t, then skip it and return.
179.366 - // Otherwise throw an exception.
179.367 - private void expect(Token t) {
179.368 - if (!skip(t))
179.369 - throw new IllegalArgumentException("Expected " + t + ", found " + current());
179.370 - }
179.371 -
179.372 - private void next() {
179.373 - tokenI++;
179.374 - }
179.375 -
179.376 - QueryExp parseQuery() {
179.377 - QueryExp qe = query();
179.378 - if (current() != END)
179.379 - throw new IllegalArgumentException("Junk at end of query: " + current());
179.380 - return qe;
179.381 - }
179.382 -
179.383 - // The remainder of this class is a classical recursive-descent parser.
179.384 - // We only need to violate the recursive-descent scheme in one place,
179.385 - // where parentheses make the grammar not LL(1).
179.386 -
179.387 - private QueryExp query() {
179.388 - QueryExp lhs = andquery();
179.389 - while (skip(OR))
179.390 - lhs = Query.or(lhs, andquery());
179.391 - return lhs;
179.392 - }
179.393 -
179.394 - private QueryExp andquery() {
179.395 - QueryExp lhs = predicate();
179.396 - while (skip(AND))
179.397 - lhs = Query.and(lhs, predicate());
179.398 - return lhs;
179.399 - }
179.400 -
179.401 - private QueryExp predicate() {
179.402 - // Grammar hack. If we see a paren, it might be (query) or
179.403 - // it might be (value). We try to parse (query), and if that
179.404 - // fails, we parse (value). For example, if the string is
179.405 - // "(2+3)*4 < 5" then we will try to parse the query
179.406 - // "2+3)*4 < 5", which will fail at the ), so we'll back up to
179.407 - // the paren and let value() handle it.
179.408 - if (skip(LPAR)) {
179.409 - int parenIndex = tokenI - 1;
179.410 - try {
179.411 - QueryExp qe = query();
179.412 - expect(RPAR);
179.413 - return qe;
179.414 - } catch (IllegalArgumentException e) {
179.415 - // OK: try parsing a value
179.416 - }
179.417 - tokenI = parenIndex;
179.418 - }
179.419 -
179.420 - if (skip(NOT))
179.421 - return Query.not(predicate());
179.422 -
179.423 - if (skip(INSTANCEOF))
179.424 - return Query.isInstanceOf(stringvalue());
179.425 -
179.426 - if (skip(LIKE)) {
179.427 - StringValueExp sve = stringvalue();
179.428 - String s = sve.getValue();
179.429 - try {
179.430 - return new ObjectName(s);
179.431 - } catch (MalformedObjectNameException e) {
179.432 - throw new IllegalArgumentException(
179.433 - "Bad ObjectName pattern after LIKE: '" + s + "'", e);
179.434 - }
179.435 - }
179.436 -
179.437 - ValueExp lhs = value();
179.438 -
179.439 - return predrhs(lhs);
179.440 - }
179.441 -
179.442 - // The order of elements in the following arrays is important. The code
179.443 - // in predrhs depends on integer indexes. Change with caution.
179.444 - private static final Token[] relations = {
179.445 - EQ, LT, GT, LE, GE, NE,
179.446 - // 0, 1, 2, 3, 4, 5,
179.447 - };
179.448 - private static final Token[] betweenLikeIn = {
179.449 - BETWEEN, LIKE, IN
179.450 - // 0, 1, 2,
179.451 - };
179.452 -
179.453 - private QueryExp predrhs(ValueExp lhs) {
179.454 - Token start = current(); // for errors
179.455 -
179.456 - // Look for < > = etc
179.457 - int i = skipOne(relations);
179.458 - if (i >= 0) {
179.459 - ValueExp rhs = value();
179.460 - switch (i) {
179.461 - case 0: return Query.eq(lhs, rhs);
179.462 - case 1: return Query.lt(lhs, rhs);
179.463 - case 2: return Query.gt(lhs, rhs);
179.464 - case 3: return Query.leq(lhs, rhs);
179.465 - case 4: return Query.geq(lhs, rhs);
179.466 - case 5: return Query.not(Query.eq(lhs, rhs));
179.467 - // There is no Query.ne so <> is shorthand for the above.
179.468 - default:
179.469 - throw new AssertionError();
179.470 - }
179.471 - }
179.472 -
179.473 - // Must be BETWEEN LIKE or IN, optionally preceded by NOT
179.474 - boolean not = skip(NOT);
179.475 - i = skipOne(betweenLikeIn);
179.476 - if (i < 0)
179.477 - throw new IllegalArgumentException("Expected relation at " + start);
179.478 -
179.479 - QueryExp q;
179.480 - switch (i) {
179.481 - case 0: { // BETWEEN
179.482 - ValueExp lower = value();
179.483 - expect(AND);
179.484 - ValueExp upper = value();
179.485 - q = Query.between(lhs, lower, upper);
179.486 - break;
179.487 - }
179.488 -
179.489 - case 1: { // LIKE
179.490 - if (!(lhs instanceof AttributeValueExp)) {
179.491 - throw new IllegalArgumentException(
179.492 - "Left-hand side of LIKE must be an attribute");
179.493 - }
179.494 - AttributeValueExp alhs = (AttributeValueExp) lhs;
179.495 - StringValueExp sve = stringvalue();
179.496 - q = Query.match(alhs, sve);
179.497 - break;
179.498 - }
179.499 -
179.500 - case 2: { // IN
179.501 - expect(LPAR);
179.502 - List<ValueExp> values = new ArrayList<ValueExp>();
179.503 - values.add(value());
179.504 - while (skip(COMMA))
179.505 - values.add(value());
179.506 - expect(RPAR);
179.507 - q = Query.in(lhs, values.toArray(new ValueExp[values.size()]));
179.508 - break;
179.509 - }
179.510 -
179.511 - default:
179.512 - throw new AssertionError();
179.513 - }
179.514 -
179.515 - if (not)
179.516 - q = Query.not(q);
179.517 -
179.518 - return q;
179.519 - }
179.520 -
179.521 - private ValueExp value() {
179.522 - ValueExp lhs = factor();
179.523 - int i;
179.524 - while ((i = skipOne(PLUS, MINUS)) >= 0) {
179.525 - ValueExp rhs = factor();
179.526 - if (i == 0)
179.527 - lhs = Query.plus(lhs, rhs);
179.528 - else
179.529 - lhs = Query.minus(lhs, rhs);
179.530 - }
179.531 - return lhs;
179.532 - }
179.533 -
179.534 - private ValueExp factor() {
179.535 - ValueExp lhs = term();
179.536 - int i;
179.537 - while ((i = skipOne(TIMES, DIVIDE)) >= 0) {
179.538 - ValueExp rhs = term();
179.539 - if (i == 0)
179.540 - lhs = Query.times(lhs, rhs);
179.541 - else
179.542 - lhs = Query.div(lhs, rhs);
179.543 - }
179.544 - return lhs;
179.545 - }
179.546 -
179.547 - private ValueExp term() {
179.548 - boolean signed = false;
179.549 - int sign = +1;
179.550 - if (skip(PLUS))
179.551 - signed = true;
179.552 - else if (skip(MINUS)) {
179.553 - signed = true; sign = -1;
179.554 - }
179.555 -
179.556 - Token t = current();
179.557 - next();
179.558 -
179.559 - if (t instanceof DoubleLit)
179.560 - return Query.value(sign * ((DoubleLit) t).number);
179.561 - if (t instanceof LongLit) {
179.562 - long n = ((LongLit) t).number;
179.563 - if (n == Long.MIN_VALUE && sign != -1)
179.564 - throw new IllegalArgumentException("Illegal positive integer: " + n);
179.565 - return Query.value(sign * n);
179.566 - }
179.567 - if (signed)
179.568 - throw new IllegalArgumentException("Expected number after + or -");
179.569 -
179.570 - if (t == LPAR) {
179.571 - ValueExp v = value();
179.572 - expect(RPAR);
179.573 - return v;
179.574 - }
179.575 - if (t.equals(FALSE) || t.equals(TRUE)) {
179.576 - return Query.value(t.equals(TRUE));
179.577 - }
179.578 - if (t.equals(CLASS))
179.579 - return Query.classattr();
179.580 -
179.581 - if (t instanceof StringLit)
179.582 - return Query.value(t.string); // Not toString(), which would requote '
179.583 -
179.584 - // At this point, all that remains is something that will call Query.attr
179.585 -
179.586 - if (!(t instanceof Id) && !(t instanceof QuotedId))
179.587 - throw new IllegalArgumentException("Unexpected token " + t);
179.588 -
179.589 - String name1 = name(t);
179.590 -
179.591 - if (skip(SHARP)) {
179.592 - Token t2 = current();
179.593 - next();
179.594 - String name2 = name(t2);
179.595 - return Query.attr(name1, name2);
179.596 - }
179.597 - return Query.attr(name1);
179.598 - }
179.599 -
179.600 - // Initially, t is the first token of a supposed name and current()
179.601 - // is the second.
179.602 - private String name(Token t) {
179.603 - StringBuilder sb = new StringBuilder();
179.604 - while (true) {
179.605 - if (!(t instanceof Id) && !(t instanceof QuotedId))
179.606 - throw new IllegalArgumentException("Unexpected token " + t);
179.607 - sb.append(t.string);
179.608 - if (current() != DOT)
179.609 - break;
179.610 - sb.append('.');
179.611 - next();
179.612 - t = current();
179.613 - next();
179.614 - }
179.615 - return sb.toString();
179.616 - }
179.617 -
179.618 - private StringValueExp stringvalue() {
179.619 - // Currently the only way to get a StringValueExp when constructing
179.620 - // a QueryExp is via Query.value(String), so we only recognize
179.621 - // string literals here. But if we expand queries in the future
179.622 - // that might no longer be true.
179.623 - Token t = current();
179.624 - next();
179.625 - if (!(t instanceof StringLit))
179.626 - throw new IllegalArgumentException("Expected string: " + t);
179.627 - return Query.value(t.string);
179.628 - }
179.629 -}
180.1 --- a/src/share/classes/javax/management/SendNotification.java Mon Nov 23 10:04:47 2009 +0000
180.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
180.3 @@ -1,38 +0,0 @@
180.4 -/*
180.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
180.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
180.7 - *
180.8 - * This code is free software; you can redistribute it and/or modify it
180.9 - * under the terms of the GNU General Public License version 2 only, as
180.10 - * published by the Free Software Foundation. Sun designates this
180.11 - * particular file as subject to the "Classpath" exception as provided
180.12 - * by Sun in the LICENSE file that accompanied this code.
180.13 - *
180.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
180.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
180.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
180.17 - * version 2 for more details (a copy is included in the LICENSE file that
180.18 - * accompanied this code).
180.19 - *
180.20 - * You should have received a copy of the GNU General Public License version
180.21 - * 2 along with this work; if not, write to the Free Software Foundation,
180.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
180.23 - *
180.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
180.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
180.26 - * have any questions.
180.27 - */
180.28 -
180.29 -package javax.management;
180.30 -
180.31 -/**
180.32 - * Interface implemented by objects that can be asked to send a notification.
180.33 - */
180.34 -public interface SendNotification {
180.35 - /**
180.36 - * Sends a notification.
180.37 - *
180.38 - * @param notification The notification to send.
180.39 - */
180.40 - public void sendNotification(Notification notification);
180.41 -}
181.1 --- a/src/share/classes/javax/management/StandardEmitterMBean.java Mon Nov 23 10:04:47 2009 +0000
181.2 +++ b/src/share/classes/javax/management/StandardEmitterMBean.java Wed Nov 25 11:08:25 2009 -0800
181.3 @@ -25,10 +25,6 @@
181.4
181.5 package javax.management;
181.6
181.7 -import com.sun.jmx.mbeanserver.MBeanInjector;
181.8 -import com.sun.jmx.mbeanserver.MBeanIntrospector;
181.9 -import static javax.management.JMX.MBeanOptions;
181.10 -
181.11 /**
181.12 * <p>An MBean whose management interface is determined by reflection
181.13 * on a Java interface, and that emits notifications.</p>
181.14 @@ -66,7 +62,7 @@
181.15 * @since 1.6
181.16 */
181.17 public class StandardEmitterMBean extends StandardMBean
181.18 - implements NotificationEmitter, SendNotification {
181.19 + implements NotificationEmitter {
181.20
181.21 private final NotificationEmitter emitter;
181.22 private final MBeanNotificationInfo[] notificationInfo;
181.23 @@ -80,10 +76,9 @@
181.24 * for {@code implementation} and {@code emitter} to be the same object.</p>
181.25 *
181.26 * <p>If {@code emitter} is an instance of {@code
181.27 - * SendNotification} (for example, a {@link NotificationBroadcasterSupport}),
181.28 - * then the MBean's {@link #sendNotification
181.29 + * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification
181.30 * sendNotification} method will call {@code emitter.}{@link
181.31 - * SendNotification#sendNotification sendNotification}.</p>
181.32 + * NotificationBroadcasterSupport#sendNotification sendNotification}.</p>
181.33 *
181.34 * <p>The array returned by {@link #getNotificationInfo()} on the
181.35 * new MBean is a copy of the array returned by
181.36 @@ -95,18 +90,20 @@
181.37 *
181.38 * @param implementation the implementation of the MBean interface.
181.39 * @param mbeanInterface a Standard MBean interface.
181.40 - * @param emitter the object that will handle notifications. If null,
181.41 - * a new {@code NotificationEmitter} will be constructed that also
181.42 - * implements {@link SendNotification}.
181.43 + * @param emitter the object that will handle notifications.
181.44 *
181.45 * @throws IllegalArgumentException if the {@code mbeanInterface}
181.46 * does not follow JMX design patterns for Management Interfaces, or
181.47 * if the given {@code implementation} does not implement the
181.48 - * specified interface.
181.49 + * specified interface, or if {@code emitter} is null.
181.50 */
181.51 public <T> StandardEmitterMBean(T implementation, Class<T> mbeanInterface,
181.52 NotificationEmitter emitter) {
181.53 - this(implementation, mbeanInterface, false, emitter);
181.54 + super(implementation, mbeanInterface, false);
181.55 + if (emitter == null)
181.56 + throw new IllegalArgumentException("Null emitter");
181.57 + this.emitter = emitter;
181.58 + this.notificationInfo = emitter.getNotificationInfo();
181.59 }
181.60
181.61 /**
181.62 @@ -121,10 +118,9 @@
181.63 * same object.</p>
181.64 *
181.65 * <p>If {@code emitter} is an instance of {@code
181.66 - * SendNotification} (for example, a {@link NotificationBroadcasterSupport}),
181.67 - * then the MBean's {@link #sendNotification
181.68 + * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification
181.69 * sendNotification} method will call {@code emitter.}{@link
181.70 - * SendNotification#sendNotification sendNotification}.</p>
181.71 + * NotificationBroadcasterSupport#sendNotification sendNotification}.</p>
181.72 *
181.73 * <p>The array returned by {@link #getNotificationInfo()} on the
181.74 * new MBean is a copy of the array returned by
181.75 @@ -138,71 +134,21 @@
181.76 * @param mbeanInterface a Standard MBean interface.
181.77 * @param isMXBean If true, the {@code mbeanInterface} parameter
181.78 * names an MXBean interface and the resultant MBean is an MXBean.
181.79 - * @param emitter the object that will handle notifications. If null,
181.80 - * a new {@code NotificationEmitter} will be constructed that also
181.81 - * implements {@link SendNotification}.
181.82 + * @param emitter the object that will handle notifications.
181.83 *
181.84 * @throws IllegalArgumentException if the {@code mbeanInterface}
181.85 * does not follow JMX design patterns for Management Interfaces, or
181.86 * if the given {@code implementation} does not implement the
181.87 - * specified interface.
181.88 + * specified interface, or if {@code emitter} is null.
181.89 */
181.90 public <T> StandardEmitterMBean(T implementation, Class<T> mbeanInterface,
181.91 boolean isMXBean,
181.92 NotificationEmitter emitter) {
181.93 - this(implementation, mbeanInterface,
181.94 - isMXBean ? MBeanOptions.MXBEAN : null, emitter);
181.95 - }
181.96 -
181.97 - /**
181.98 - * <p>Make an MBean whose management interface is specified by {@code
181.99 - * mbeanInterface}, with the given implementation and options, and where
181.100 - * notifications are handled by the given {@code NotificationEmitter}.
181.101 - * Options select whether to make a Standard MBean or an MXBean, and
181.102 - * whether the result of {@link #getWrappedObject()} is the {@code
181.103 - * StandardEmitterMBean} object or the given implementation. The resultant
181.104 - * MBean implements the {@code NotificationEmitter} interface by forwarding
181.105 - * its methods to {@code emitter}. It is legal and useful for {@code
181.106 - * implementation} and {@code emitter} to be the same object.</p>
181.107 - *
181.108 - * <p>If {@code emitter} is an instance of {@code
181.109 - * SendNotification} (for example, a {@link NotificationBroadcasterSupport}),
181.110 - * then the MBean's {@link #sendNotification
181.111 - * sendNotification} method will call {@code emitter.}{@link
181.112 - * SendNotification#sendNotification sendNotification}.</p>
181.113 - *
181.114 - * <p>The array returned by {@link #getNotificationInfo()} on the
181.115 - * new MBean is a copy of the array returned by
181.116 - * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo
181.117 - * getNotificationInfo()} at the time of construction. If the array
181.118 - * returned by {@code emitter.getNotificationInfo()} later changes,
181.119 - * that will have no effect on this object's
181.120 - * {@code getNotificationInfo()}.</p>
181.121 - *
181.122 - * @param implementation the implementation of the MBean interface.
181.123 - * @param mbeanInterface a Standard MBean interface.
181.124 - * @param options MBeanOptions that control the operation of the resulting
181.125 - * MBean.
181.126 - * @param emitter the object that will handle notifications. If null,
181.127 - * a new {@code NotificationEmitter} will be constructed that also
181.128 - * implements {@link SendNotification}.
181.129 - *
181.130 - * @throws IllegalArgumentException if the {@code mbeanInterface}
181.131 - * does not follow JMX design patterns for Management Interfaces, or
181.132 - * if the given {@code implementation} does not implement the
181.133 - * specified interface.
181.134 - */
181.135 - public <T> StandardEmitterMBean(T implementation, Class<T> mbeanInterface,
181.136 - MBeanOptions options,
181.137 - NotificationEmitter emitter) {
181.138 - super(implementation, mbeanInterface, options);
181.139 - MBeanNotificationInfo[] defaultMBNIs = defaultMBNIs(implementation);
181.140 + super(implementation, mbeanInterface, isMXBean);
181.141 if (emitter == null)
181.142 - emitter = defaultEmitter(defaultMBNIs);
181.143 + throw new IllegalArgumentException("Null emitter");
181.144 this.emitter = emitter;
181.145 - this.notificationInfo =
181.146 - firstNonEmpty(emitter.getNotificationInfo(), defaultMBNIs);
181.147 - injectEmitter();
181.148 + this.notificationInfo = emitter.getNotificationInfo();
181.149 }
181.150
181.151 /**
181.152 @@ -213,10 +159,9 @@
181.153 * by forwarding its methods to {@code emitter}.</p>
181.154 *
181.155 * <p>If {@code emitter} is an instance of {@code
181.156 - * SendNotification} (for example, a {@link NotificationBroadcasterSupport}),
181.157 - * then the MBean's {@link #sendNotification
181.158 + * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification
181.159 * sendNotification} method will call {@code emitter.}{@link
181.160 - * SendNotification#sendNotification sendNotification}.</p>
181.161 + * NotificationBroadcasterSupport#sendNotification sendNotification}.</p>
181.162 *
181.163 * <p>The array returned by {@link #getNotificationInfo()} on the
181.164 * new MBean is a copy of the array returned by
181.165 @@ -230,17 +175,20 @@
181.166 * the given {@code mbeanInterface}.</p>
181.167 *
181.168 * @param mbeanInterface a StandardMBean interface.
181.169 - * @param emitter the object that will handle notifications. If null,
181.170 - * a new {@code NotificationEmitter} will be constructed that also
181.171 - * implements {@link SendNotification}.
181.172 + * @param emitter the object that will handle notifications.
181.173 *
181.174 * @throws IllegalArgumentException if the {@code mbeanInterface}
181.175 * does not follow JMX design patterns for Management Interfaces, or
181.176 - * if {@code this} does not implement the specified interface.
181.177 + * if {@code this} does not implement the specified interface, or
181.178 + * if {@code emitter} is null.
181.179 */
181.180 protected StandardEmitterMBean(Class<?> mbeanInterface,
181.181 NotificationEmitter emitter) {
181.182 - this(mbeanInterface, false, emitter);
181.183 + super(mbeanInterface, false);
181.184 + if (emitter == null)
181.185 + throw new IllegalArgumentException("Null emitter");
181.186 + this.emitter = emitter;
181.187 + this.notificationInfo = emitter.getNotificationInfo();
181.188 }
181.189
181.190 /**
181.191 @@ -252,10 +200,9 @@
181.192 * forwarding its methods to {@code emitter}.</p>
181.193 *
181.194 * <p>If {@code emitter} is an instance of {@code
181.195 - * SendNotification} (for example, a {@link NotificationBroadcasterSupport}),
181.196 - * then the MBean's {@link #sendNotification
181.197 + * NotificationBroadcasterSupport} then the MBean's {@link #sendNotification
181.198 * sendNotification} method will call {@code emitter.}{@link
181.199 - * SendNotification#sendNotification sendNotification}.</p>
181.200 + * NotificationBroadcasterSupport#sendNotification sendNotification}.</p>
181.201 *
181.202 * <p>The array returned by {@link #getNotificationInfo()} on the
181.203 * new MBean is a copy of the array returned by
181.204 @@ -271,102 +218,20 @@
181.205 * @param mbeanInterface a StandardMBean interface.
181.206 * @param isMXBean If true, the {@code mbeanInterface} parameter
181.207 * names an MXBean interface and the resultant MBean is an MXBean.
181.208 - * @param emitter the object that will handle notifications. If null,
181.209 - * a new {@code NotificationEmitter} will be constructed that also
181.210 - * implements {@link SendNotification}.
181.211 + * @param emitter the object that will handle notifications.
181.212 *
181.213 * @throws IllegalArgumentException if the {@code mbeanInterface}
181.214 * does not follow JMX design patterns for Management Interfaces, or
181.215 - * if {@code this} does not implement the specified interface.
181.216 + * if {@code this} does not implement the specified interface, or
181.217 + * if {@code emitter} is null.
181.218 */
181.219 protected StandardEmitterMBean(Class<?> mbeanInterface, boolean isMXBean,
181.220 NotificationEmitter emitter) {
181.221 - this(mbeanInterface, isMXBean ? MBeanOptions.MXBEAN : null, emitter);
181.222 - }
181.223 -
181.224 - /**
181.225 - * <p>Make an MBean whose management interface is specified by {@code
181.226 - * mbeanInterface}, with the given options, and where notifications are
181.227 - * handled by the given {@code NotificationEmitter}. This constructor can
181.228 - * be used to make either Standard MBeans or MXBeans. The resultant MBean
181.229 - * implements the {@code NotificationEmitter} interface by forwarding its
181.230 - * methods to {@code emitter}.</p>
181.231 - *
181.232 - * <p>If {@code emitter} is an instance of {@code
181.233 - * SendNotification} (for example, a {@link NotificationBroadcasterSupport}),
181.234 - * then the MBean's {@link #sendNotification
181.235 - * sendNotification} method will call {@code emitter.}{@link
181.236 - * SendNotification#sendNotification sendNotification}.</p>
181.237 - *
181.238 - * <p>The array returned by {@link #getNotificationInfo()} on the
181.239 - * new MBean is a copy of the array returned by
181.240 - * {@code emitter.}{@link NotificationBroadcaster#getNotificationInfo
181.241 - * getNotificationInfo()} at the time of construction. If the array
181.242 - * returned by {@code emitter.getNotificationInfo()} later changes,
181.243 - * that will have no effect on this object's
181.244 - * {@code getNotificationInfo()}.</p>
181.245 - *
181.246 - * <p>This constructor must be called from a subclass that implements
181.247 - * the given {@code mbeanInterface}.</p>
181.248 - *
181.249 - * @param mbeanInterface a StandardMBean interface.
181.250 - * @param options MBeanOptions that control the operation of the resulting
181.251 - * MBean.
181.252 - * @param emitter the object that will handle notifications. If null,
181.253 - * a new {@code NotificationEmitter} will be constructed that also
181.254 - * implements {@link SendNotification}.
181.255 - *
181.256 - * @throws IllegalArgumentException if the {@code mbeanInterface}
181.257 - * does not follow JMX design patterns for Management Interfaces, or
181.258 - * if {@code this} does not implement the specified interface.
181.259 - */
181.260 - protected StandardEmitterMBean(Class<?> mbeanInterface, MBeanOptions options,
181.261 - NotificationEmitter emitter) {
181.262 - super(mbeanInterface, options);
181.263 - MBeanNotificationInfo[] defaultMBNIs = defaultMBNIs(this);
181.264 + super(mbeanInterface, isMXBean);
181.265 if (emitter == null)
181.266 - emitter = defaultEmitter(defaultMBNIs);
181.267 + throw new IllegalArgumentException("Null emitter");
181.268 this.emitter = emitter;
181.269 - this.notificationInfo =
181.270 - firstNonEmpty(emitter.getNotificationInfo(), defaultMBNIs);
181.271 - injectEmitter();
181.272 - }
181.273 -
181.274 - private static MBeanNotificationInfo[] defaultMBNIs(Object mbean) {
181.275 - return MBeanIntrospector.findNotificationsFromAnnotations(
181.276 - mbean.getClass());
181.277 - }
181.278 -
181.279 - private NotificationEmitter defaultEmitter(MBeanNotificationInfo[] defaultMBNIs) {
181.280 - MBeanNotificationInfo[] mbnis =
181.281 - firstNonEmpty(getNotificationInfo(), defaultMBNIs);
181.282 - // Will be null unless getNotificationInfo() is overridden,
181.283 - // since the notificationInfo field has not been set at this point.
181.284 - if (mbnis == null)
181.285 - mbnis = getMBeanInfo().getNotifications();
181.286 - return new NotificationBroadcasterSupport(mbnis);
181.287 - }
181.288 -
181.289 - private static <T> T[] firstNonEmpty(T[]... items) {
181.290 - for (T[] t : items) {
181.291 - if (t != null && t.length != 0)
181.292 - return t;
181.293 - }
181.294 - return null;
181.295 - }
181.296 -
181.297 - private void injectEmitter() {
181.298 - if (emitter instanceof SendNotification) {
181.299 - try {
181.300 - Object resource = getImplementation();
181.301 - SendNotification send = (SendNotification) emitter;
181.302 - MBeanInjector.injectSendNotification(resource, send);
181.303 - } catch (RuntimeException e) {
181.304 - throw e;
181.305 - } catch (Exception e) {
181.306 - throw new IllegalArgumentException(e);
181.307 - }
181.308 - }
181.309 + this.notificationInfo = emitter.getNotificationInfo();
181.310 }
181.311
181.312 public void removeNotificationListener(NotificationListener listener)
181.313 @@ -394,10 +259,10 @@
181.314 /**
181.315 * <p>Sends a notification.</p>
181.316 *
181.317 - * <p>If the {@code emitter} parameter to the constructor was
181.318 - * an instance of {@link SendNotification}, such as {@link
181.319 - * NotificationBroadcasterSupport}, then this method will call {@code
181.320 - * emitter.}{@link SendNotification#sendNotification
181.321 + * <p>If the {@code emitter} parameter to the constructor was an
181.322 + * instance of {@code NotificationBroadcasterSupport} then this
181.323 + * method will call {@code emitter.}{@link
181.324 + * NotificationBroadcasterSupport#sendNotification
181.325 * sendNotification}.</p>
181.326 *
181.327 * @param n the notification to send.
181.328 @@ -406,12 +271,13 @@
181.329 * constructor was not a {@code NotificationBroadcasterSupport}.
181.330 */
181.331 public void sendNotification(Notification n) {
181.332 - if (emitter instanceof SendNotification)
181.333 - ((SendNotification) emitter).sendNotification(n);
181.334 + if (emitter instanceof NotificationBroadcasterSupport)
181.335 + ((NotificationBroadcasterSupport) emitter).sendNotification(n);
181.336 else {
181.337 final String msg =
181.338 "Cannot sendNotification when emitter is not an " +
181.339 - "instance of SendNotification: " + emitter.getClass().getName();
181.340 + "instance of NotificationBroadcasterSupport: " +
181.341 + emitter.getClass().getName();
181.342 throw new ClassCastException(msg);
181.343 }
181.344 }
182.1 --- a/src/share/classes/javax/management/StandardMBean.java Mon Nov 23 10:04:47 2009 +0000
182.2 +++ b/src/share/classes/javax/management/StandardMBean.java Wed Nov 25 11:08:25 2009 -0800
182.3 @@ -25,27 +25,20 @@
182.4
182.5 package javax.management;
182.6
182.7 +import static com.sun.jmx.defaults.JmxProperties.MISC_LOGGER;
182.8 import com.sun.jmx.mbeanserver.DescriptorCache;
182.9 import com.sun.jmx.mbeanserver.Introspector;
182.10 -import com.sun.jmx.mbeanserver.MBeanInjector;
182.11 -import com.sun.jmx.mbeanserver.MBeanInstantiator;
182.12 -import com.sun.jmx.mbeanserver.MBeanIntrospector;
182.13 import com.sun.jmx.mbeanserver.MBeanSupport;
182.14 import com.sun.jmx.mbeanserver.MXBeanSupport;
182.15 import com.sun.jmx.mbeanserver.StandardMBeanSupport;
182.16 import com.sun.jmx.mbeanserver.Util;
182.17 -import java.lang.reflect.Method;
182.18 +
182.19 import java.security.AccessController;
182.20 import java.security.PrivilegedAction;
182.21 -import java.util.ArrayList;
182.22 import java.util.HashMap;
182.23 -import java.util.HashSet;
182.24 -import java.util.List;
182.25 import java.util.Map;
182.26 -import java.util.Set;
182.27 import java.util.WeakHashMap;
182.28 import java.util.logging.Level;
182.29 -import javax.management.openmbean.MXBeanMappingFactory;
182.30 import javax.management.openmbean.OpenMBeanAttributeInfo;
182.31 import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
182.32 import javax.management.openmbean.OpenMBeanConstructorInfo;
182.33 @@ -55,9 +48,6 @@
182.34 import javax.management.openmbean.OpenMBeanParameterInfo;
182.35 import javax.management.openmbean.OpenMBeanParameterInfoSupport;
182.36
182.37 -import static com.sun.jmx.defaults.JmxProperties.MISC_LOGGER;
182.38 -import static javax.management.JMX.MBeanOptions;
182.39 -
182.40 /**
182.41 * <p>An MBean whose management interface is determined by reflection
182.42 * on a Java interface.</p>
182.43 @@ -133,121 +123,7 @@
182.44 *
182.45 * @since 1.5
182.46 */
182.47 -public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration {
182.48 -
182.49 - /**
182.50 - * <p>Options controlling the behavior of {@code StandardMBean} instances.</p>
182.51 - */
182.52 - public static class Options extends JMX.MBeanOptions {
182.53 - private static final long serialVersionUID = 5107355471177517164L;
182.54 -
182.55 - private boolean wrappedVisible;
182.56 - private boolean forwardRegistration;
182.57 -
182.58 - /**
182.59 - * <p>Construct an {@code Options} object where all options have
182.60 - * their default values.</p>
182.61 - */
182.62 - public Options() {}
182.63 -
182.64 - @Override
182.65 - public Options clone() {
182.66 - return (Options) super.clone();
182.67 - }
182.68 -
182.69 - /**
182.70 - * <p>Defines whether the {@link StandardMBean#getWrappedObject()
182.71 - * getWrappedObject} method returns the wrapped object.</p>
182.72 - *
182.73 - * <p>If this option is true, then {@code getWrappedObject()} will return
182.74 - * the same object as {@link StandardMBean#getImplementation()
182.75 - * getImplementation}. Otherwise, it will return the
182.76 - * StandardMBean instance itself. The setting of this option
182.77 - * affects the behavior of {@link MBeanServer#getClassLoaderFor
182.78 - * MBeanServer.getClassLoaderFor} and {@link MBeanServer#isInstanceOf
182.79 - * MBeanServer.isInstanceOf}. The default value is false for
182.80 - * compatibility reasons, but true is a better value for most new code.</p>
182.81 - *
182.82 - * @return true if this StandardMBean's {@link
182.83 - * StandardMBean#getWrappedObject getWrappedObject} returns the wrapped
182.84 - * object.
182.85 - */
182.86 - public boolean isWrappedObjectVisible() {
182.87 - return this.wrappedVisible;
182.88 - }
182.89 -
182.90 - /**
182.91 - * <p>Set the {@link #isWrappedObjectVisible WrappedObjectVisible} option
182.92 - * to the given value.</p>
182.93 - * @param visible the new value.
182.94 - */
182.95 - public void setWrappedObjectVisible(boolean visible) {
182.96 - this.wrappedVisible = visible;
182.97 - }
182.98 -
182.99 - /**
182.100 - * <p>Defines whether the {@link MBeanRegistration MBeanRegistration}
182.101 - * callbacks are forwarded to the wrapped object.</p>
182.102 - *
182.103 - * <p>If this option is true, then
182.104 - * {@link #preRegister(MBeanServer, ObjectName) preRegister},
182.105 - * {@link #postRegister(Boolean) postRegister},
182.106 - * {@link #preDeregister preDeregister} and
182.107 - * {@link #postDeregister postDeregister} methods are forwarded
182.108 - * to the wrapped object, in addition to the behaviour specified
182.109 - * for the StandardMBean instance itself.
182.110 - * The default value is false for compatibility reasons, but true
182.111 - * is a better value for most new code.</p>
182.112 - *
182.113 - * @return true if the <code>MBeanRegistration</code> callbacks
182.114 - * are forwarded to the wrapped object.
182.115 - */
182.116 - public boolean isMBeanRegistrationForwarded() {
182.117 - return this.forwardRegistration;
182.118 - }
182.119 -
182.120 - /**
182.121 - * <p>Set the
182.122 - * {@link #isMBeanRegistrationForwarded MBeanRegistrationForwarded}
182.123 - * option to the given value.</p>
182.124 - * @param forward the new value.
182.125 - */
182.126 - public void setMBeanRegistrationForwarded(boolean forward) {
182.127 - this.forwardRegistration = forward;
182.128 - }
182.129 -
182.130 - // Canonical objects for each of
182.131 - // (MXBean,!MXBean) x (WVisible,!WVisible) x (Forward,!Forward)
182.132 - private static final Options[] CANONICALS = {
182.133 - new Options(), new Options(), new Options(), new Options(),
182.134 - new Options(), new Options(), new Options(), new Options(),
182.135 - };
182.136 - static {
182.137 - CANONICALS[1].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT);
182.138 - CANONICALS[2].setWrappedObjectVisible(true);
182.139 - CANONICALS[3].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT);
182.140 - CANONICALS[3].setWrappedObjectVisible(true);
182.141 - CANONICALS[4].setMBeanRegistrationForwarded(true);
182.142 - CANONICALS[5].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT);
182.143 - CANONICALS[5].setMBeanRegistrationForwarded(true);
182.144 - CANONICALS[6].setWrappedObjectVisible(true);
182.145 - CANONICALS[6].setMBeanRegistrationForwarded(true);
182.146 - CANONICALS[7].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT);
182.147 - CANONICALS[7].setWrappedObjectVisible(true);
182.148 - CANONICALS[7].setMBeanRegistrationForwarded(true);
182.149 - }
182.150 - @Override
182.151 - MBeanOptions[] canonicals() {
182.152 - return CANONICALS;
182.153 - }
182.154 -
182.155 - @Override
182.156 - boolean same(MBeanOptions opts) {
182.157 - return (super.same(opts) && opts instanceof Options &&
182.158 - ((Options) opts).wrappedVisible == wrappedVisible &&
182.159 - ((Options) opts).forwardRegistration ==forwardRegistration);
182.160 - }
182.161 - }
182.162 +public class StandardMBean implements DynamicMBean, MBeanRegistration {
182.163
182.164 private final static DescriptorCache descriptors =
182.165 DescriptorCache.getInstance(JMX.proof);
182.166 @@ -263,11 +139,6 @@
182.167 private volatile MBeanInfo cachedMBeanInfo;
182.168
182.169 /**
182.170 - * The MBeanOptions for this StandardMBean.
182.171 - **/
182.172 - private MBeanOptions options;
182.173 -
182.174 - /**
182.175 * Make a DynamicMBean out of <var>implementation</var>, using the
182.176 * specified <var>mbeanInterface</var> class.
182.177 * @param implementation The implementation of this MBean.
182.178 @@ -282,14 +153,12 @@
182.179 * implementation is allowed. If null implementation is allowed,
182.180 * and a null implementation is passed, then the implementation
182.181 * is assumed to be <var>this</var>.
182.182 - * @param options MBeanOptions to apply to this instance.
182.183 * @exception IllegalArgumentException if the given
182.184 * <var>implementation</var> is null, and null is not allowed.
182.185 **/
182.186 - @SuppressWarnings("unchecked") // cast to T
182.187 private <T> void construct(T implementation, Class<T> mbeanInterface,
182.188 boolean nullImplementationAllowed,
182.189 - MBeanOptions options)
182.190 + boolean isMXBean)
182.191 throws NotCompliantMBeanException {
182.192 if (implementation == null) {
182.193 // Have to use (T)this rather than mbeanInterface.cast(this)
182.194 @@ -298,23 +167,20 @@
182.195 implementation = Util.<T>cast(this);
182.196 else throw new IllegalArgumentException("implementation is null");
182.197 }
182.198 - if (options == null)
182.199 - options = new MBeanOptions();
182.200 - MXBeanMappingFactory mappingFactory = options.getMXBeanMappingFactory();
182.201 - boolean mx = (mappingFactory != null);
182.202 - if (mbeanInterface == null) {
182.203 - mbeanInterface = Util.cast(Introspector.getStandardOrMXBeanInterface(
182.204 - implementation.getClass(), mx));
182.205 - }
182.206 - if (mx) {
182.207 - this.mbean =
182.208 - new MXBeanSupport(implementation, mbeanInterface,
182.209 - mappingFactory);
182.210 + if (isMXBean) {
182.211 + if (mbeanInterface == null) {
182.212 + mbeanInterface = Util.cast(Introspector.getMXBeanInterface(
182.213 + implementation.getClass()));
182.214 + }
182.215 + this.mbean = new MXBeanSupport(implementation, mbeanInterface);
182.216 } else {
182.217 + if (mbeanInterface == null) {
182.218 + mbeanInterface = Util.cast(Introspector.getStandardMBeanInterface(
182.219 + implementation.getClass()));
182.220 + }
182.221 this.mbean =
182.222 new StandardMBeanSupport(implementation, mbeanInterface);
182.223 }
182.224 - this.options = options.canonical();
182.225 }
182.226
182.227 /**
182.228 @@ -343,7 +209,7 @@
182.229 **/
182.230 public <T> StandardMBean(T implementation, Class<T> mbeanInterface)
182.231 throws NotCompliantMBeanException {
182.232 - construct(implementation, mbeanInterface, false, null);
182.233 + construct(implementation, mbeanInterface, false, false);
182.234 }
182.235
182.236 /**
182.237 @@ -363,7 +229,7 @@
182.238 **/
182.239 protected StandardMBean(Class<?> mbeanInterface)
182.240 throws NotCompliantMBeanException {
182.241 - construct(null, mbeanInterface, true, null);
182.242 + construct(null, mbeanInterface, true, false);
182.243 }
182.244
182.245 /**
182.246 @@ -400,17 +266,7 @@
182.247 public <T> StandardMBean(T implementation, Class<T> mbeanInterface,
182.248 boolean isMXBean) {
182.249 try {
182.250 - MBeanOptions opts = new MBeanOptions();
182.251 - if (mbeanInterface == null) {
182.252 - mbeanInterface = Util.cast(Introspector.getStandardOrMXBeanInterface(
182.253 - implementation.getClass(), isMXBean));
182.254 - }
182.255 - if (isMXBean) {
182.256 - MXBeanMappingFactory f = MXBeanMappingFactory.forInterface(
182.257 - mbeanInterface);
182.258 - opts.setMXBeanMappingFactory(f);
182.259 - }
182.260 - construct(implementation, mbeanInterface, false, opts);
182.261 + construct(implementation, mbeanInterface, false, isMXBean);
182.262 } catch (NotCompliantMBeanException e) {
182.263 throw new IllegalArgumentException(e);
182.264 }
182.265 @@ -441,77 +297,7 @@
182.266 **/
182.267 protected StandardMBean(Class<?> mbeanInterface, boolean isMXBean) {
182.268 try {
182.269 - MBeanOptions opts = new MBeanOptions();
182.270 - if (mbeanInterface == null) {
182.271 - mbeanInterface = Introspector.getStandardOrMXBeanInterface(
182.272 - getClass(), isMXBean);
182.273 - }
182.274 - if (isMXBean) {
182.275 - MXBeanMappingFactory f = MXBeanMappingFactory.forInterface(
182.276 - mbeanInterface);
182.277 - opts.setMXBeanMappingFactory(f);
182.278 - }
182.279 - construct(null, mbeanInterface, true, opts);
182.280 - } catch (NotCompliantMBeanException e) {
182.281 - throw new IllegalArgumentException(e);
182.282 - }
182.283 - }
182.284 -
182.285 - /**
182.286 - * <p>Make a DynamicMBean out of the object
182.287 - * <var>implementation</var>, using the specified
182.288 - * <var>mbeanInterface</var> class and the specified options.</p>
182.289 - *
182.290 - * @param implementation The implementation of this MBean.
182.291 - * @param mbeanInterface The Management Interface exported by this
182.292 - * MBean's implementation. If <code>null</code>, then this
182.293 - * object will use standard JMX design pattern to determine
182.294 - * the management interface associated with the given
182.295 - * implementation.
182.296 - * @param options MBeanOptions that control the operation of the resulting
182.297 - * MBean.
182.298 - * @param <T> Allows the compiler to check
182.299 - * that {@code implementation} does indeed implement the class
182.300 - * described by {@code mbeanInterface}. The compiler can only
182.301 - * check this if {@code mbeanInterface} is a class literal such
182.302 - * as {@code MyMBean.class}.
182.303 - *
182.304 - * @exception IllegalArgumentException if the given
182.305 - * <var>implementation</var> is null, or if the <var>mbeanInterface</var>
182.306 - * does not follow JMX design patterns for Management Interfaces, or
182.307 - * if the given <var>implementation</var> does not implement the
182.308 - * specified interface.
182.309 - **/
182.310 - public <T> StandardMBean(T implementation,
182.311 - Class<T> mbeanInterface,
182.312 - MBeanOptions options) {
182.313 - try {
182.314 - construct(implementation, mbeanInterface, false, options);
182.315 - } catch (NotCompliantMBeanException e) {
182.316 - throw new IllegalArgumentException(e);
182.317 - }
182.318 - }
182.319 -
182.320 - /**
182.321 - * <p>Make a DynamicMBean out of <var>this</var>, using the specified
182.322 - * <var>mbeanInterface</var> class and the specified options.</p>
182.323 - *
182.324 - * <p>Calls {@link #StandardMBean(Object, Class, JMX.MBeanOptions)
182.325 - * this(this,mbeanInterface,options)}.
182.326 - * This constructor is reserved to subclasses.</p>
182.327 - *
182.328 - * @param mbeanInterface The Management Interface exported by this
182.329 - * MBean.
182.330 - * @param options MBeanOptions that control the operation of the resulting
182.331 - * MBean.
182.332 - *
182.333 - * @exception IllegalArgumentException if the <var>mbeanInterface</var>
182.334 - * does not follow JMX design patterns for Management Interfaces, or
182.335 - * if <var>this</var> does not implement the specified interface.
182.336 - **/
182.337 - protected StandardMBean(Class<?> mbeanInterface, MBeanOptions options) {
182.338 - try {
182.339 - construct(null, mbeanInterface, true, options);
182.340 + construct(null, mbeanInterface, true, isMXBean);
182.341 } catch (NotCompliantMBeanException e) {
182.342 throw new IllegalArgumentException(e);
182.343 }
182.344 @@ -527,9 +313,7 @@
182.345 *
182.346 * @exception IllegalArgumentException if the given
182.347 * <var>implementation</var> is null.
182.348 - * @exception IllegalStateException if the
182.349 - * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded}
182.350 - * option is true.
182.351 + *
182.352 * @exception NotCompliantMBeanException if the given
182.353 * <var>implementation</var> does not implement the
182.354 * Standard MBean (or MXBean) interface that was
182.355 @@ -543,24 +327,12 @@
182.356 if (implementation == null)
182.357 throw new IllegalArgumentException("implementation is null");
182.358
182.359 - if(options instanceof Options &&
182.360 - ((Options) options).isMBeanRegistrationForwarded())
182.361 - throw new IllegalStateException("Implementation can't be changed " +
182.362 - "because MBeanRegistrationForwarded option is true");
182.363 -
182.364 - setImplementation2(implementation);
182.365 - }
182.366 -
182.367 - private <T> void setImplementation2(T implementation)
182.368 - throws NotCompliantMBeanException {
182.369 - Class<? super T> intf = Util.cast(getMBeanInterface());
182.370 -
182.371 - if (this.mbean.isMXBean()) {
182.372 + if (isMXBean()) {
182.373 this.mbean = new MXBeanSupport(implementation,
182.374 - intf,
182.375 - options.getMXBeanMappingFactory());
182.376 + Util.<Class<Object>>cast(getMBeanInterface()));
182.377 } else {
182.378 - this.mbean = new StandardMBeanSupport(implementation, intf);
182.379 + this.mbean = new StandardMBeanSupport(implementation,
182.380 + Util.<Class<Object>>cast(getMBeanInterface()));
182.381 }
182.382 }
182.383
182.384 @@ -571,67 +343,7 @@
182.385 * @see #setImplementation
182.386 **/
182.387 public Object getImplementation() {
182.388 - return mbean.getWrappedObject();
182.389 - }
182.390 -
182.391 - /**
182.392 - * <p>Get the wrapped implementation object or return this object.</p>
182.393 - *
182.394 - * <p>For compatibility reasons, this method only returns the wrapped
182.395 - * implementation object if the {@link Options#isWrappedObjectVisible
182.396 - * WrappedObjectVisible} option was specified when this StandardMBean
182.397 - * was created. Otherwise it returns {@code this}.</p>
182.398 - *
182.399 - * <p>If you want the MBeanServer's {@link MBeanServer#getClassLoaderFor
182.400 - * getClassLoaderFor} and {@link MBeanServer#isInstanceOf
182.401 - * isInstanceOf} methods to refer to the wrapped implementation and
182.402 - * not this StandardMBean object, then you must set the
182.403 - * {@code WrappedObjectVisible} option, for example using:</p>
182.404 - *
182.405 - * <pre>
182.406 - * StandardMBean.Options opts = new StandardMBean.Options();
182.407 - * opts.setWrappedObjectVisible(true);
182.408 - * StandardMBean mbean = new StandardMBean(impl, MyMBean.class, opts);
182.409 - * </pre>
182.410 - *
182.411 - * @return The wrapped implementation object, or this StandardMBean
182.412 - * instance.
182.413 - */
182.414 - public Object getWrappedObject() {
182.415 - if (options instanceof Options &&
182.416 - ((Options) options).isWrappedObjectVisible())
182.417 - return getImplementation();
182.418 - else
182.419 - return this;
182.420 - }
182.421 -
182.422 - /**
182.423 - * <p>Get the ClassLoader of the wrapped implementation object or of this
182.424 - * object.</p>
182.425 - *
182.426 - * <p>For compatibility reasons, this method only returns the ClassLoader
182.427 - * of the wrapped implementation object if the {@link
182.428 - * Options#isWrappedObjectVisible WrappedObjectVisible} option was
182.429 - * specified when this StandardMBean was created. Otherwise it returns
182.430 - * {@code this.getClass().getClassLoader()}.</p>
182.431 - *
182.432 - * <p>If you want the MBeanServer's {@link MBeanServer#getClassLoaderFor
182.433 - * getClassLoaderFor} and {@link MBeanServer#isInstanceOf
182.434 - * isInstanceOf} methods to refer to the wrapped implementation and
182.435 - * not this StandardMBean object, then you must set the
182.436 - * {@code WrappedObjectVisible} option, for example using:</p>
182.437 - *
182.438 - * <pre>
182.439 - * StandardMBean.Options opts = new StandardMBean.Options();
182.440 - * opts.setWrappedObjectVisible(true);
182.441 - * StandardMBean mbean = new StandardMBean(impl, MyMBean.class, opts);
182.442 - * </pre>
182.443 - *
182.444 - * @return The ClassLoader of the wrapped Cimplementation object, or of
182.445 - * this StandardMBean instance.
182.446 - */
182.447 - public ClassLoader getWrappedClassLoader() {
182.448 - return getWrappedObject().getClass().getClassLoader();
182.449 + return mbean.getResource();
182.450 }
182.451
182.452 /**
182.453 @@ -647,20 +359,7 @@
182.454 * @return The class of the implementation of this Standard MBean (or MXBean).
182.455 **/
182.456 public Class<?> getImplementationClass() {
182.457 - return mbean.getWrappedObject().getClass();
182.458 - }
182.459 -
182.460 - /**
182.461 - * Return the MBeanOptions that were specified or implied for this StandardMBean
182.462 - * instance. If an MBeanOptions object was supplied when this StandardMBean
182.463 - * instance was constructed, and if that object has not been modified in the
182.464 - * meantime, then the returned object will be equal to that object, although
182.465 - * it might not be the same object.
182.466 - * @return The MBeanOptions that were specified or implied for this StandardMBean
182.467 - * instance.
182.468 - */
182.469 - public MBeanOptions getOptions() {
182.470 - return options.uncanonical();
182.471 + return mbean.getResource().getClass();
182.472 }
182.473
182.474 // ------------------------------------------------------------------
182.475 @@ -749,7 +448,7 @@
182.476
182.477 MBeanSupport<?> msupport = mbean;
182.478 final MBeanInfo bi = msupport.getMBeanInfo();
182.479 - final Object impl = msupport.getWrappedObject();
182.480 + final Object impl = msupport.getResource();
182.481
182.482 final boolean immutableInfo = immutableInfo(this.getClass());
182.483
182.484 @@ -1027,7 +726,7 @@
182.485 * @return the MBeanNotificationInfo[] for the new MBeanInfo.
182.486 **/
182.487 MBeanNotificationInfo[] getNotifications(MBeanInfo info) {
182.488 - return info.getNotifications();
182.489 + return null;
182.490 }
182.491
182.492 /**
182.493 @@ -1116,6 +815,10 @@
182.494 cachedMBeanInfo = info;
182.495 }
182.496
182.497 + private boolean isMXBean() {
182.498 + return mbean.isMXBean();
182.499 + }
182.500 +
182.501 private static <T> boolean identicalArrays(T[] a, T[] b) {
182.502 if (a == b)
182.503 return true;
182.504 @@ -1323,145 +1026,6 @@
182.505 return natts;
182.506 }
182.507
182.508 - // ------------------------------------------------------------------
182.509 - // Resolve from a type name to a Class.
182.510 - // ------------------------------------------------------------------
182.511 - private static Class<?> resolveClass(MBeanFeatureInfo info, String type,
182.512 - Class<?> mbeanItf)
182.513 - throws ClassNotFoundException {
182.514 - String t = (String) info.getDescriptor().
182.515 - getFieldValue(JMX.ORIGINAL_TYPE_FIELD);
182.516 - if (t == null) {
182.517 - t = type;
182.518 - }
182.519 - Class<?> clazz = MBeanInstantiator.primitiveType(t);
182.520 - if(clazz == null)
182.521 - clazz = Class.forName(t, false, mbeanItf.getClassLoader());
182.522 - return clazz;
182.523 - }
182.524 -
182.525 - // ------------------------------------------------------------------
182.526 - // Return the subset of valid Management methods
182.527 - // ------------------------------------------------------------------
182.528 - private static Method getManagementMethod(final Class<?> mbeanType,
182.529 - String opName, Class<?>... parameters) throws NoSuchMethodException,
182.530 - SecurityException {
182.531 - Method m = mbeanType.getMethod(opName, parameters);
182.532 - if (mbeanType.isInterface()) {
182.533 - return m;
182.534 - }
182.535 - final List<Method> methods = new ArrayList<Method>();
182.536 - try {
182.537 - MBeanIntrospector.getAnnotatedMethods(mbeanType, methods);
182.538 - }catch (SecurityException ex) {
182.539 - throw ex;
182.540 - }catch (NoSuchMethodException ex) {
182.541 - throw ex;
182.542 - }catch (Exception ex) {
182.543 - NoSuchMethodException nsme =
182.544 - new NoSuchMethodException(ex.toString());
182.545 - nsme.initCause(ex);
182.546 - throw nsme;
182.547 - }
182.548 -
182.549 - if(methods.contains(m)) return m;
182.550 -
182.551 - throw new NoSuchMethodException("Operation " + opName +
182.552 - " not found in management interface " + mbeanType.getName());
182.553 - }
182.554 - /**
182.555 - * Retrieve the set of MBean attribute accessor <code>Method</code>s
182.556 - * located in the <code>mbeanInterface</code> MBean interface that
182.557 - * correspond to the <code>attr</code> <code>MBeanAttributeInfo</code>
182.558 - * parameter.
182.559 - * @param mbeanInterface the management interface.
182.560 - * Can be a standard MBean or MXBean interface, or a Java class
182.561 - * annotated with {@link MBean @MBean} or {@link MXBean @MXBean}.
182.562 - * @param attr The attribute we want the accessors for.
182.563 - * @return The set of accessors.
182.564 - * @throws java.lang.NoSuchMethodException if no accessor exists
182.565 - * for the given {@link MBeanAttributeInfo MBeanAttributeInfo}.
182.566 - * @throws java.lang.IllegalArgumentException if at least one
182.567 - * of the two parameters is null.
182.568 - * @throws java.lang.ClassNotFoundException if the class named in the
182.569 - * attribute type is not found.
182.570 - * @throws java.lang.SecurityException if this exception is
182.571 - * encountered while introspecting the MBean interface.
182.572 - */
182.573 - public static Set<Method> findAttributeAccessors(Class<?> mbeanInterface,
182.574 - MBeanAttributeInfo attr)
182.575 - throws NoSuchMethodException,
182.576 - ClassNotFoundException {
182.577 - if (mbeanInterface == null || attr == null) {
182.578 - throw new IllegalArgumentException("mbeanInterface or attr " +
182.579 - "parameter is null");
182.580 - }
182.581 - String attributeName = attr.getName();
182.582 - Set<Method> methods = new HashSet<Method>();
182.583 - Class<?> clazz = resolveClass(attr, attr.getType(), mbeanInterface);
182.584 - if (attr.isReadable()) {
182.585 - String radical = "get";
182.586 - if(attr.isIs()) radical = "is";
182.587 - Method getter = getManagementMethod(mbeanInterface, radical +
182.588 - attributeName);
182.589 - if (getter.getReturnType().equals(clazz)) {
182.590 - methods.add(getter);
182.591 - } else {
182.592 - throw new NoSuchMethodException("Invalid getter return type, " +
182.593 - "should be " + clazz + ", found " +
182.594 - getter.getReturnType());
182.595 - }
182.596 - }
182.597 - if (attr.isWritable()) {
182.598 - Method setter = getManagementMethod(mbeanInterface, "set" +
182.599 - attributeName,
182.600 - clazz);
182.601 - if (setter.getReturnType().equals(Void.TYPE)) {
182.602 - methods.add(setter);
182.603 - } else {
182.604 - throw new NoSuchMethodException("Invalid setter return type, " +
182.605 - "should be void, found " + setter.getReturnType());
182.606 - }
182.607 - }
182.608 - return methods;
182.609 - }
182.610 -
182.611 - /**
182.612 - * Retrieve the MBean operation <code>Method</code>
182.613 - * located in the <code>mbeanInterface</code> MBean interface that
182.614 - * corresponds to the provided <code>op</code>
182.615 - * <code>MBeanOperationInfo</code> parameter.
182.616 - * @param mbeanInterface the management interface.
182.617 - * Can be a standard MBean or MXBean interface, or a Java class
182.618 - * annotated with {@link MBean @MBean} or {@link MXBean @MXBean}.
182.619 - * @param op The operation we want the method for.
182.620 - * @return the method corresponding to the provided MBeanOperationInfo.
182.621 - * @throws java.lang.NoSuchMethodException if no method exists
182.622 - * for the given {@link MBeanOperationInfo MBeanOperationInfo}.
182.623 - * @throws java.lang.IllegalArgumentException if at least one
182.624 - * of the two parameters is null.
182.625 - * @throws java.lang.ClassNotFoundException if one of the
182.626 - * classes named in the operation signature array is not found.
182.627 - * @throws java.lang.SecurityException if this exception is
182.628 - * encountered while introspecting the MBean interface.
182.629 - */
182.630 - public static Method findOperationMethod(Class<?> mbeanInterface,
182.631 - MBeanOperationInfo op)
182.632 - throws ClassNotFoundException, NoSuchMethodException {
182.633 - if (mbeanInterface == null || op == null) {
182.634 - throw new IllegalArgumentException("mbeanInterface or op " +
182.635 - "parameter is null");
182.636 - }
182.637 - List<Class<?>> classes = new ArrayList<Class<?>>();
182.638 - for (MBeanParameterInfo info : op.getSignature()) {
182.639 - Class<?> clazz = resolveClass(info, info.getType(), mbeanInterface);
182.640 - classes.add(clazz);
182.641 - }
182.642 - Class<?>[] signature = new Class<?>[classes.size()];
182.643 - classes.toArray(signature);
182.644 - return getManagementMethod(mbeanInterface, op.getName(), signature);
182.645 - }
182.646 -
182.647 /**
182.648 * <p>Allows the MBean to perform any operations it needs before
182.649 * being registered in the MBean server. If the name of the MBean
182.650 @@ -1470,14 +1034,10 @@
182.651 * registered in the MBean server.</p>
182.652 *
182.653 * <p>The default implementation of this method returns the {@code name}
182.654 - * parameter. If the
182.655 - * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded}
182.656 - * option is set to true, then this method is forwarded to the object
182.657 - * returned by the {@link #getImplementation getImplementation()} method.
182.658 - * The name returned by this call is then returned by this method.
182.659 - * It does nothing else for Standard MBeans. For MXBeans, it records
182.660 - * the {@code MBeanServer} and {@code ObjectName} parameters so they can
182.661 - * be used to translate inter-MXBean references.</p>
182.662 + * parameter. It does nothing else for
182.663 + * Standard MBeans. For MXBeans, it records the {@code MBeanServer}
182.664 + * and {@code ObjectName} parameters so they can be used to translate
182.665 + * inter-MXBean references.</p>
182.666 *
182.667 * <p>It is good practice for a subclass that overrides this method
182.668 * to call the overridden method via {@code super.preRegister(...)}.
182.669 @@ -1512,13 +1072,7 @@
182.670 */
182.671 public ObjectName preRegister(MBeanServer server, ObjectName name)
182.672 throws Exception {
182.673 - // Forward preRegister before to call register and
182.674 - // inject parameters.
182.675 - if(shouldForwardMBeanRegistration())
182.676 - name = ((MBeanRegistration)getImplementation()).
182.677 - preRegister(server, name);
182.678 mbean.register(server, name);
182.679 - MBeanInjector.inject(mbean.getWrappedObject(), server, name);
182.680 return name;
182.681 }
182.682
182.683 @@ -1526,11 +1080,7 @@
182.684 * <p>Allows the MBean to perform any operations needed after having been
182.685 * registered in the MBean server or after the registration has failed.</p>
182.686 *
182.687 - * <p>If the
182.688 - * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded}
182.689 - * option is set to true, then this method is forwarded to the object
182.690 - * returned by the {@link #getImplementation getImplementation()} method.
182.691 - * The default implementation of this method does nothing else for
182.692 + * <p>The default implementation of this method does nothing for
182.693 * Standard MBeans. For MXBeans, it undoes any work done by
182.694 * {@link #preRegister preRegister} if registration fails.</p>
182.695 *
182.696 @@ -1548,21 +1098,13 @@
182.697 public void postRegister(Boolean registrationDone) {
182.698 if (!registrationDone)
182.699 mbean.unregister();
182.700 - if(shouldForwardMBeanRegistration())
182.701 - ((MBeanRegistration)getImplementation()).
182.702 - postRegister(registrationDone);
182.703 }
182.704
182.705 /**
182.706 * <p>Allows the MBean to perform any operations it needs before
182.707 * being unregistered by the MBean server.</p>
182.708 *
182.709 - * <p>If the
182.710 - * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded}
182.711 - * option is set to true, then this method is forwarded to the object
182.712 - * returned by the {@link #getImplementation getImplementation()} method.
182.713 - * Other than that, the default implementation of this method does nothing.
182.714 - * </p>
182.715 + * <p>The default implementation of this method does nothing.</p>
182.716 *
182.717 * <p>It is good practice for a subclass that overrides this method
182.718 * to call the overridden method via {@code super.preDeregister(...)}.</p>
182.719 @@ -1574,19 +1116,13 @@
182.720 * @since 1.6
182.721 */
182.722 public void preDeregister() throws Exception {
182.723 - if(shouldForwardMBeanRegistration())
182.724 - ((MBeanRegistration)getImplementation()).preDeregister();
182.725 }
182.726
182.727 /**
182.728 * <p>Allows the MBean to perform any operations needed after having been
182.729 * unregistered in the MBean server.</p>
182.730 *
182.731 - * <p>If the
182.732 - * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded}
182.733 - * option is set to true, then this method is forwarded to the object
182.734 - * returned by the {@link #getImplementation getImplementation()} method.
182.735 - * The default implementation of this method does nothing else for
182.736 + * <p>The default implementation of this method does nothing for
182.737 * Standard MBeans. For MXBeans, it removes any information that
182.738 * was recorded by the {@link #preRegister preRegister} method.</p>
182.739 *
182.740 @@ -1599,15 +1135,8 @@
182.741 */
182.742 public void postDeregister() {
182.743 mbean.unregister();
182.744 - if(shouldForwardMBeanRegistration())
182.745 - ((MBeanRegistration)getImplementation()).postDeregister();
182.746 }
182.747
182.748 - private boolean shouldForwardMBeanRegistration() {
182.749 - return (getImplementation() instanceof MBeanRegistration) &&
182.750 - (options instanceof Options &&
182.751 - ((Options) options).isMBeanRegistrationForwarded());
182.752 - }
182.753 //
182.754 // MBeanInfo immutability
182.755 //
183.1 --- a/src/share/classes/javax/management/event/EventClient.java Mon Nov 23 10:04:47 2009 +0000
183.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
183.3 @@ -1,1104 +0,0 @@
183.4 -/*
183.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
183.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
183.7 - *
183.8 - * This code is free software; you can redistribute it and/or modify it
183.9 - * under the terms of the GNU General Public License version 2 only, as
183.10 - * published by the Free Software Foundation. Sun designates this
183.11 - * particular file as subject to the "Classpath" exception as provided
183.12 - * by Sun in the LICENSE file that accompanied this code.
183.13 - *
183.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
183.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
183.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
183.17 - * version 2 for more details (a copy is included in the LICENSE file that
183.18 - * accompanied this code).
183.19 - *
183.20 - * You should have received a copy of the GNU General Public License version
183.21 - * 2 along with this work; if not, write to the Free Software Foundation,
183.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
183.23 - *
183.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
183.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
183.26 - * have any questions.
183.27 - */
183.28 -
183.29 -package javax.management.event;
183.30 -
183.31 -import com.sun.jmx.event.DaemonThreadFactory;
183.32 -import com.sun.jmx.event.LeaseRenewer;
183.33 -import com.sun.jmx.event.ReceiverBuffer;
183.34 -import com.sun.jmx.event.RepeatedSingletonJob;
183.35 -import com.sun.jmx.mbeanserver.PerThreadGroupPool;
183.36 -import com.sun.jmx.remote.util.ClassLogger;
183.37 -
183.38 -import java.io.IOException;
183.39 -import java.lang.reflect.Method;
183.40 -import java.util.ArrayList;
183.41 -import java.util.Collection;
183.42 -import java.util.Collections;
183.43 -import java.util.HashMap;
183.44 -import java.util.List;
183.45 -import java.util.Map;
183.46 -import java.util.concurrent.Callable;
183.47 -import java.util.concurrent.Executor;
183.48 -
183.49 -import java.util.concurrent.ScheduledExecutorService;
183.50 -import java.util.concurrent.ScheduledThreadPoolExecutor;
183.51 -import java.util.concurrent.ThreadFactory;
183.52 -import java.util.concurrent.TimeUnit;
183.53 -import java.util.concurrent.atomic.AtomicLong;
183.54 -import javax.management.InstanceNotFoundException;
183.55 -import javax.management.ListenerNotFoundException;
183.56 -import javax.management.MBeanNotificationInfo;
183.57 -import javax.management.MBeanServerConnection;
183.58 -import javax.management.Notification;
183.59 -import javax.management.NotificationBroadcasterSupport;
183.60 -import javax.management.NotificationFilter;
183.61 -import javax.management.NotificationListener;
183.62 -import javax.management.ObjectName;
183.63 -import javax.management.remote.NotificationResult;
183.64 -import javax.management.remote.TargetedNotification;
183.65 -
183.66 -/**
183.67 - * <p>This class is used to manage its notification listeners on the client
183.68 - * side in the same way as on the MBean server side. This class needs to work
183.69 - * with an {@link EventClientDelegateMBean} on the server side.</p>
183.70 - *
183.71 - * <P>A user can specify an {@link EventRelay} object to specify how to receive
183.72 - * notifications forwarded by the {@link EventClientDelegateMBean}. By default,
183.73 - * the class {@link FetchingEventRelay} is used.</p>
183.74 - *
183.75 - * <p>A user can specify an {@link java.util.concurrent.Executor Executor}
183.76 - * to distribute notifications to local listeners. If no executor is
183.77 - * specified, the thread in the {@link EventRelay} which calls {@link
183.78 - * EventReceiver#receive EventReceiver.receive} will be reused to distribute
183.79 - * the notifications (in other words, to call the {@link
183.80 - * NotificationListener#handleNotification handleNotification} method of the
183.81 - * appropriate listeners). It is useful to make a separate thread do this
183.82 - * distribution in some cases. For example, if network communication is slow,
183.83 - * the forwarding thread can concentrate on communication while, locally,
183.84 - * the distributing thread distributes the received notifications. Another
183.85 - * usage is to share a thread pool between many clients, for scalability.
183.86 - * Note, though, that if the {@code Executor} can create more than one thread
183.87 - * then it is possible that listeners will see notifications in a different
183.88 - * order from the order in which they were sent.</p>
183.89 - *
183.90 - * <p>An object of this class sends notifications to listeners added with
183.91 - * {@link #addEventClientListener}. The {@linkplain Notification#getType()
183.92 - * type} of each such notification is one of {@link #FAILED}, {@link #NONFATAL},
183.93 - * or {@link #NOTIFS_LOST}.</p>
183.94 - *
183.95 - * @since JMX 2.0
183.96 - */
183.97 -public class EventClient implements EventConsumer, NotificationManager {
183.98 -
183.99 - /**
183.100 - * <p>A notification string type used by an {@code EventClient} object
183.101 - * to inform a listener added by {@link #addEventClientListener} that
183.102 - * it failed to get notifications from a remote server, and that it is
183.103 - * possible that no more notifications will be delivered.</p>
183.104 - *
183.105 - * @see #addEventClientListener
183.106 - * @see EventReceiver#failed
183.107 - */
183.108 - public static final String FAILED = "jmx.event.service.failed";
183.109 -
183.110 - /**
183.111 - * <p>Reports that an unexpected exception has been received by the {@link
183.112 - * EventRelay} object but that it is non-fatal. For example, a notification
183.113 - * received is not serializable or its class is not found.</p>
183.114 - *
183.115 - * @see #addEventClientListener
183.116 - * @see EventReceiver#nonFatal
183.117 - */
183.118 - public static final String NONFATAL = "jmx.event.service.nonfatal";
183.119 -
183.120 - /**
183.121 - * <p>A notification string type used by an {@code EventClient} object
183.122 - * to inform a listener added by {@link #addEventClientListener
183.123 - * addEventClientListener} that it has detected that notifications have
183.124 - * been lost. The {@link Notification#getUserData() userData} of the
183.125 - * notification is a Long which is an upper bound on the number of lost
183.126 - * notifications that have just been detected.</p>
183.127 - *
183.128 - * @see #addEventClientListener
183.129 - */
183.130 - public static final String NOTIFS_LOST = "jmx.event.service.notifs.lost";
183.131 -
183.132 - /**
183.133 - * The default lease time that EventClient instances will request, in
183.134 - * milliseconds. This value is {@value}.
183.135 - *
183.136 - * @see EventClientDelegateMBean#lease
183.137 - */
183.138 - public static final long DEFAULT_REQUESTED_LEASE_TIME = 300000;
183.139 -
183.140 - /**
183.141 - * <p>Constructs a default {@code EventClient} object.</p>
183.142 - *
183.143 - * <p>This object creates a {@link FetchingEventRelay} object to
183.144 - * receive notifications forwarded by the {@link EventClientDelegateMBean}.
183.145 - * The {@link EventClientDelegateMBean} that it works with is the
183.146 - * one registered with the {@linkplain EventClientDelegate#OBJECT_NAME
183.147 - * default ObjectName}. The thread from the {@link FetchingEventRelay}
183.148 - * object that fetches the notifications is also used to distribute them.
183.149 - *
183.150 - * @param conn An {@link MBeanServerConnection} object used to communicate
183.151 - * with an {@link EventClientDelegateMBean} MBean.
183.152 - *
183.153 - * @throws IllegalArgumentException If {@code conn} is null.
183.154 - * @throws IOException If an I/O error occurs when communicating with the
183.155 - * {@code EventClientDelegateMBean}.
183.156 - */
183.157 - public EventClient(MBeanServerConnection conn) throws IOException {
183.158 - this(EventClientDelegate.getProxy(conn));
183.159 - }
183.160 -
183.161 - /**
183.162 - * Constructs an {@code EventClient} object with a specified
183.163 - * {@link EventClientDelegateMBean}.
183.164 - *
183.165 - * <p>This object creates a {@link FetchingEventRelay} object to receive
183.166 - * notifications forwarded by the {@link EventClientDelegateMBean}. The
183.167 - * thread from the {@link FetchingEventRelay} object that fetches the
183.168 - * notifications is also used to distribute them.
183.169 - *
183.170 - * @param delegate An {@link EventClientDelegateMBean} object to work with.
183.171 - *
183.172 - * @throws IllegalArgumentException If {@code delegate} is null.
183.173 - * @throws IOException If an I/O error occurs when communicating with the
183.174 - * the {@link EventClientDelegateMBean}.
183.175 - */
183.176 - public EventClient(EventClientDelegateMBean delegate)
183.177 - throws IOException {
183.178 - this(delegate, null, null, null, DEFAULT_REQUESTED_LEASE_TIME);
183.179 - }
183.180 -
183.181 - /**
183.182 - * Constructs an {@code EventClient} object with the specified
183.183 - * {@link EventClientDelegateMBean}, {@link EventRelay}
183.184 - * object, and distributing thread.
183.185 - *
183.186 - * @param delegate An {@link EventClientDelegateMBean} object to work with.
183.187 - * Usually, this will be a proxy constructed using
183.188 - * {@link EventClientDelegate#getProxy}.
183.189 - * @param eventRelay An object used to receive notifications
183.190 - * forwarded by the {@link EventClientDelegateMBean}. If {@code null}, a
183.191 - * {@link FetchingEventRelay} object will be used.
183.192 - * @param distributingExecutor Used to distribute notifications to local
183.193 - * listeners. Only one job at a time will be submitted to this Executor.
183.194 - * If {@code distributingExecutor} is {@code null}, the thread that calls
183.195 - * {@link EventReceiver#receive EventReceiver.receive} from the {@link
183.196 - * EventRelay} object is used.
183.197 - * @param leaseScheduler An object that will be used to schedule the
183.198 - * periodic {@linkplain EventClientDelegateMBean#lease lease updates}.
183.199 - * If {@code null}, a default scheduler will be used.
183.200 - * @param requestedLeaseTime The lease time used to keep this client alive
183.201 - * in the {@link EventClientDelegateMBean}. A value of zero is equivalent
183.202 - * to the {@linkplain #DEFAULT_REQUESTED_LEASE_TIME default value}.
183.203 - *
183.204 - * @throws IllegalArgumentException If {@code delegate} is null.
183.205 - * @throws IOException If an I/O error occurs when communicating with the
183.206 - * {@link EventClientDelegateMBean}.
183.207 - */
183.208 - public EventClient(EventClientDelegateMBean delegate,
183.209 - EventRelay eventRelay,
183.210 - Executor distributingExecutor,
183.211 - ScheduledExecutorService leaseScheduler,
183.212 - long requestedLeaseTime)
183.213 - throws IOException {
183.214 - if (delegate == null) {
183.215 - throw new IllegalArgumentException("Null EventClientDelegateMBean");
183.216 - }
183.217 -
183.218 - if (requestedLeaseTime == 0)
183.219 - requestedLeaseTime = DEFAULT_REQUESTED_LEASE_TIME;
183.220 - else if (requestedLeaseTime < 0) {
183.221 - throw new IllegalArgumentException(
183.222 - "Negative lease time: " + requestedLeaseTime);
183.223 - }
183.224 -
183.225 - eventClientDelegate = delegate;
183.226 -
183.227 - if (eventRelay != null) {
183.228 - this.eventRelay = eventRelay;
183.229 - } else {
183.230 - try {
183.231 - this.eventRelay = new FetchingEventRelay(delegate);
183.232 - } catch (IOException ioe) {
183.233 - throw ioe;
183.234 - } catch (Exception e) {
183.235 - // impossible?
183.236 - final IOException ioee = new IOException(e.toString());
183.237 - ioee.initCause(e);
183.238 - throw ioee;
183.239 - }
183.240 - }
183.241 -
183.242 - if (distributingExecutor == null)
183.243 - distributingExecutor = callerExecutor;
183.244 - this.distributingExecutor = distributingExecutor;
183.245 - this.dispatchingJob = new DispatchingJob();
183.246 -
183.247 - clientId = this.eventRelay.getClientId();
183.248 -
183.249 - this.requestedLeaseTime = requestedLeaseTime;
183.250 - if (leaseScheduler == null)
183.251 - leaseScheduler = defaultLeaseScheduler();
183.252 - leaseRenewer = new LeaseRenewer(leaseScheduler, renewLease);
183.253 -
183.254 - if (logger.traceOn()) {
183.255 - logger.trace("init", "New EventClient: "+clientId);
183.256 - }
183.257 - }
183.258 -
183.259 - private static ScheduledExecutorService defaultLeaseScheduler() {
183.260 - // The default lease scheduler uses a ScheduledThreadPoolExecutor
183.261 - // with a maximum of 20 threads. This means that if you have many
183.262 - // EventClient instances and some of them get blocked (because of an
183.263 - // unresponsive network, for example), then even the instances that
183.264 - // are connected to responsive servers may have their leases expire.
183.265 - // XXX check if the above is true and possibly fix.
183.266 - PerThreadGroupPool.Create<ScheduledThreadPoolExecutor> create =
183.267 - new PerThreadGroupPool.Create<ScheduledThreadPoolExecutor>() {
183.268 - public ScheduledThreadPoolExecutor createThreadPool(ThreadGroup group) {
183.269 - ThreadFactory daemonThreadFactory = new DaemonThreadFactory(
183.270 - "JMX EventClient lease renewer %d");
183.271 - ScheduledThreadPoolExecutor executor =
183.272 - new ScheduledThreadPoolExecutor(20, daemonThreadFactory);
183.273 - executor.setKeepAliveTime(1, TimeUnit.SECONDS);
183.274 - executor.allowCoreThreadTimeOut(true);
183.275 - if (setRemoveOnCancelPolicy != null) {
183.276 - try {
183.277 - setRemoveOnCancelPolicy.invoke(executor, true);
183.278 - } catch (Exception e) {
183.279 - logger.trace("setRemoveOnCancelPolicy", e);
183.280 - }
183.281 - }
183.282 - // By default, a ScheduledThreadPoolExecutor will keep jobs
183.283 - // in its queue even after they have been cancelled. They
183.284 - // will only be removed when their scheduled time arrives.
183.285 - // Since the job references the LeaseRenewer which references
183.286 - // this EventClient, this can lead to a moderately large number
183.287 - // of objects remaining referenced until the renewal time
183.288 - // arrives. Hence the above call, which removes the job from
183.289 - // the queue as soon as it is cancelled. Since the call is
183.290 - // new with JDK 7, we invoke it via reflection to make it
183.291 - // easier to use this code on JDK 6.
183.292 - return executor;
183.293 - }
183.294 - };
183.295 - return leaseRenewerThreadPool.getThreadPoolExecutor(create);
183.296 - }
183.297 -
183.298 - private static final Method setRemoveOnCancelPolicy;
183.299 - static {
183.300 - Method m;
183.301 - try {
183.302 - m = ScheduledThreadPoolExecutor.class.getMethod(
183.303 - "setRemoveOnCancelPolicy", boolean.class);
183.304 - } catch (Exception e) {
183.305 - m = null;
183.306 - }
183.307 - setRemoveOnCancelPolicy = m;
183.308 - }
183.309 -
183.310 - /**
183.311 - * <p>Closes this EventClient, removes all listeners and stops receiving
183.312 - * notifications.</p>
183.313 - *
183.314 - * <p>This method calls {@link
183.315 - * EventClientDelegateMBean#removeClient(String)} and {@link
183.316 - * EventRelay#stop}. Both operations occur even if one of them
183.317 - * throws an {@code IOException}.
183.318 - *
183.319 - * @throws IOException if an I/O error occurs when communicating with
183.320 - * {@link EventClientDelegateMBean}, or if {@link EventRelay#stop}
183.321 - * throws an {@code IOException}.
183.322 - */
183.323 - public void close() throws IOException {
183.324 - if (logger.traceOn()) {
183.325 - logger.trace("close", clientId);
183.326 - }
183.327 -
183.328 - synchronized(listenerInfoMap) {
183.329 - if (closed) {
183.330 - return;
183.331 - }
183.332 -
183.333 - closed = true;
183.334 - listenerInfoMap.clear();
183.335 - }
183.336 -
183.337 - if (leaseRenewer != null)
183.338 - leaseRenewer.close();
183.339 -
183.340 - IOException ioe = null;
183.341 - try {
183.342 - eventRelay.stop();
183.343 - } catch (IOException e) {
183.344 - ioe = e;
183.345 - logger.debug("close", "EventRelay.stop", e);
183.346 - }
183.347 -
183.348 - try {
183.349 - eventClientDelegate.removeClient(clientId);
183.350 - } catch (Exception e) {
183.351 - if (e instanceof IOException)
183.352 - ioe = (IOException) e;
183.353 - else
183.354 - ioe = new IOException(e);
183.355 - logger.debug("close",
183.356 - "Got exception when removing "+clientId, e);
183.357 - }
183.358 -
183.359 - if (ioe != null)
183.360 - throw ioe;
183.361 - }
183.362 -
183.363 - /**
183.364 - * <p>Determine if this {@code EventClient} is closed.</p>
183.365 - *
183.366 - * @return True if the {@code EventClient} is closed.
183.367 - */
183.368 - public boolean closed() {
183.369 - return closed;
183.370 - }
183.371 -
183.372 - /**
183.373 - * <p>Return the {@link EventRelay} associated with this
183.374 - * {@code EventClient}.</p>
183.375 - *
183.376 - * @return The {@link EventRelay} object used.
183.377 - */
183.378 - public EventRelay getEventRelay() {
183.379 - return eventRelay;
183.380 - }
183.381 -
183.382 - /**
183.383 - * <p>Return the lease time that this {@code EventClient} requests
183.384 - * on every lease renewal.</p>
183.385 - *
183.386 - * @return The requested lease time.
183.387 - *
183.388 - * @see EventClientDelegateMBean#lease
183.389 - */
183.390 - public long getRequestedLeaseTime() {
183.391 - return requestedLeaseTime;
183.392 - }
183.393 -
183.394 - /**
183.395 - * @see javax.management.MBeanServerConnection#addNotificationListener(
183.396 - * ObjectName, NotificationListener, NotificationFilter, Object).
183.397 - */
183.398 - public void addNotificationListener(ObjectName name,
183.399 - NotificationListener listener,
183.400 - NotificationFilter filter,
183.401 - Object handback)
183.402 - throws InstanceNotFoundException, IOException {
183.403 - if (logger.traceOn()) {
183.404 - logger.trace("addNotificationListener", "");
183.405 - }
183.406 -
183.407 - checkState();
183.408 -
183.409 - Integer listenerId;
183.410 - try {
183.411 - listenerId =
183.412 - eventClientDelegate.addListener(clientId, name, filter);
183.413 - } catch (EventClientNotFoundException ecnfe) {
183.414 - final IOException ioe = new IOException(ecnfe.getMessage());
183.415 - ioe.initCause(ecnfe);
183.416 - throw ioe;
183.417 - }
183.418 -
183.419 - synchronized(listenerInfoMap) {
183.420 - listenerInfoMap.put(listenerId, new ListenerInfo(
183.421 - name,
183.422 - listener,
183.423 - filter,
183.424 - handback,
183.425 - false));
183.426 - }
183.427 -
183.428 - startListening();
183.429 - }
183.430 -
183.431 - /**
183.432 - * @see javax.management.MBeanServerConnection#removeNotificationListener(
183.433 - * ObjectName, NotificationListener).
183.434 - */
183.435 - public void removeNotificationListener(ObjectName name,
183.436 - NotificationListener listener)
183.437 - throws InstanceNotFoundException,
183.438 - ListenerNotFoundException,
183.439 - IOException {
183.440 - if (logger.traceOn()) {
183.441 - logger.trace("removeNotificationListener", "");
183.442 - }
183.443 - checkState();
183.444 -
183.445 - for (Integer id : getListenerInfo(name, listener, false)) {
183.446 - removeListener(id);
183.447 - }
183.448 - }
183.449 -
183.450 - /**
183.451 - * @see javax.management.MBeanServerConnection#removeNotificationListener(
183.452 - * ObjectName, NotificationListener, NotificationFilter, Object).
183.453 - */
183.454 - public void removeNotificationListener(ObjectName name,
183.455 - NotificationListener listener,
183.456 - NotificationFilter filter,
183.457 - Object handback)
183.458 - throws InstanceNotFoundException,
183.459 - ListenerNotFoundException,
183.460 - IOException {
183.461 - if (logger.traceOn()) {
183.462 - logger.trace("removeNotificationListener", "with all arguments.");
183.463 - }
183.464 - checkState();
183.465 - final Integer listenerId =
183.466 - getListenerInfo(name, listener, filter, handback, false);
183.467 -
183.468 - removeListener(listenerId);
183.469 - }
183.470 -
183.471 - /**
183.472 - * @see javax.management.event.EventConsumer#unsubscribe(
183.473 - * ObjectName, NotificationListener).
183.474 - */
183.475 - public void unsubscribe(ObjectName name,
183.476 - NotificationListener listener)
183.477 - throws ListenerNotFoundException, IOException {
183.478 - if (logger.traceOn()) {
183.479 - logger.trace("unsubscribe", "");
183.480 - }
183.481 - checkState();
183.482 - final Integer listenerId =
183.483 - getMatchedListenerInfo(name, listener, true);
183.484 -
183.485 - synchronized(listenerInfoMap) {
183.486 - if (listenerInfoMap.remove(listenerId) == null) {
183.487 - throw new ListenerNotFoundException();
183.488 - }
183.489 - }
183.490 -
183.491 - stopListening();
183.492 -
183.493 - try {
183.494 - eventClientDelegate.removeListenerOrSubscriber(clientId, listenerId);
183.495 - } catch (InstanceNotFoundException e) {
183.496 - logger.trace("unsubscribe", "removeSubscriber", e);
183.497 - } catch (EventClientNotFoundException cnfe) {
183.498 - logger.trace("unsubscribe", "removeSubscriber", cnfe);
183.499 - }
183.500 - }
183.501 -
183.502 - /**
183.503 - * @see javax.management.event.EventConsumer#subscribe(
183.504 - * ObjectName, NotificationListener, NotificationFilter, Object).
183.505 - */
183.506 - public void subscribe(ObjectName name,
183.507 - NotificationListener listener,
183.508 - NotificationFilter filter,
183.509 - Object handback) throws IOException {
183.510 - if (logger.traceOn()) {
183.511 - logger.trace("subscribe", "");
183.512 - }
183.513 -
183.514 - checkState();
183.515 -
183.516 - Integer listenerId;
183.517 - try {
183.518 - listenerId =
183.519 - eventClientDelegate.addSubscriber(clientId, name, filter);
183.520 - } catch (EventClientNotFoundException ecnfe) {
183.521 - final IOException ioe = new IOException(ecnfe.getMessage());
183.522 - ioe.initCause(ecnfe);
183.523 - throw ioe;
183.524 - }
183.525 -
183.526 - synchronized(listenerInfoMap) {
183.527 - listenerInfoMap.put(listenerId, new ListenerInfo(
183.528 - name,
183.529 - listener,
183.530 - filter,
183.531 - handback,
183.532 - true));
183.533 - }
183.534 -
183.535 - startListening();
183.536 - }
183.537 -
183.538 - /**
183.539 - * <p>Adds a set of listeners to the remote MBeanServer. This method can
183.540 - * be used to copy the listeners from one {@code EventClient} to another.</p>
183.541 - *
183.542 - * <p>A listener is represented by a {@link ListenerInfo} object. The listener
183.543 - * is added by calling {@link #subscribe(ObjectName,
183.544 - * NotificationListener, NotificationFilter, Object)} if the method
183.545 - * {@link ListenerInfo#isSubscription() isSubscription}
183.546 - * returns {@code true}; otherwise it is added by calling
183.547 - * {@link #addNotificationListener(ObjectName, NotificationListener,
183.548 - * NotificationFilter, Object)}.</p>
183.549 - *
183.550 - * <P>The method returns the listeners which were added successfully. The
183.551 - * elements in the returned collection are a subset of the elements in
183.552 - * {@code listeners}. If all listeners were added successfully, the two
183.553 - * collections are the same. If no listener was added successfully, the
183.554 - * returned collection is empty.</p>
183.555 - *
183.556 - * @param listeners the listeners to add.
183.557 - *
183.558 - * @return The listeners that were added successfully.
183.559 - *
183.560 - * @throws IOException If an I/O error occurs.
183.561 - *
183.562 - * @see #getListeners()
183.563 - */
183.564 - public Collection<ListenerInfo> addListeners(Collection<ListenerInfo> listeners)
183.565 - throws IOException {
183.566 - if (logger.traceOn()) {
183.567 - logger.trace("addListeners", "");
183.568 - }
183.569 -
183.570 - checkState();
183.571 -
183.572 - if (listeners == null || listeners.isEmpty())
183.573 - return Collections.emptySet();
183.574 -
183.575 - final List<ListenerInfo> list = new ArrayList<ListenerInfo>();
183.576 - for (ListenerInfo l : listeners) {
183.577 - try {
183.578 - if (l.isSubscription()) {
183.579 - subscribe(l.getObjectName(),
183.580 - l.getListener(),
183.581 - l.getFilter(),
183.582 - l.getHandback());
183.583 - } else {
183.584 - addNotificationListener(l.getObjectName(),
183.585 - l.getListener(),
183.586 - l.getFilter(),
183.587 - l.getHandback());
183.588 - }
183.589 -
183.590 - list.add(l);
183.591 - } catch (Exception e) {
183.592 - if (logger.traceOn()) {
183.593 - logger.trace("addListeners", "failed to add: "+l, e);
183.594 - }
183.595 - }
183.596 - }
183.597 -
183.598 - return list;
183.599 - }
183.600 -
183.601 - /**
183.602 - * <p>Returns the collection of listeners that have been added through
183.603 - * this {@code EventClient} and not subsequently removed. The returned
183.604 - * collection contains one entry for every listener added with
183.605 - * {@link #addNotificationListener addNotificationListener} or
183.606 - * {@link #subscribe subscribe} and not subsequently removed with
183.607 - * {@link #removeNotificationListener removeNotificationListener} or
183.608 - * {@link #unsubscribe unsubscribe}, respectively.</p>
183.609 - *
183.610 - * @return A collection of listener information. Empty if there are no
183.611 - * current listeners or if this {@code EventClient} has been {@linkplain
183.612 - * #close closed}.
183.613 - *
183.614 - * @see #addListeners
183.615 - */
183.616 - public Collection<ListenerInfo> getListeners() {
183.617 - if (logger.traceOn()) {
183.618 - logger.trace("getListeners", "");
183.619 - }
183.620 -
183.621 - synchronized(listenerInfoMap) {
183.622 - return Collections.unmodifiableCollection(listenerInfoMap.values());
183.623 - }
183.624 - }
183.625 -
183.626 - /**
183.627 - * Adds a listener to receive the {@code EventClient} notifications specified in
183.628 - * {@link #getEventClientNotificationInfo}.
183.629 - *
183.630 - * @param listener A listener to receive {@code EventClient} notifications.
183.631 - * @param filter A filter to select which notifications are to be delivered
183.632 - * to the listener, or {@code null} if all notifications are to be delivered.
183.633 - * @param handback An object to be given to the listener along with each
183.634 - * notification. Can be null.
183.635 - * @throws NullPointerException If listener is null.
183.636 - * @see #removeEventClientListener
183.637 - */
183.638 - public void addEventClientListener(NotificationListener listener,
183.639 - NotificationFilter filter,
183.640 - Object handback) {
183.641 - if (logger.traceOn()) {
183.642 - logger.trace("addEventClientListener", "");
183.643 - }
183.644 - broadcaster.addNotificationListener(listener, filter, handback);
183.645 - }
183.646 -
183.647 - /**
183.648 - * Removes a listener added to receive {@code EventClient} notifications specified in
183.649 - * {@link #getEventClientNotificationInfo}.
183.650 - *
183.651 - * @param listener A listener to receive {@code EventClient} notifications.
183.652 - * @throws NullPointerException If listener is null.
183.653 - * @throws ListenerNotFoundException If the listener is not added to
183.654 - * this {@code EventClient}.
183.655 - */
183.656 - public void removeEventClientListener(NotificationListener listener)
183.657 - throws ListenerNotFoundException {
183.658 - if (logger.traceOn()) {
183.659 - logger.trace("removeEventClientListener", "");
183.660 - }
183.661 - broadcaster.removeNotificationListener(listener);
183.662 - }
183.663 -
183.664 - /**
183.665 - * <p>Get the types of notification that an {@code EventClient} can send
183.666 - * to listeners added with {@link #addEventClientListener
183.667 - * addEventClientListener}.</p>
183.668 - *
183.669 - * @return Types of notification emitted by this {@code EventClient}.
183.670 - *
183.671 - * @see #FAILED
183.672 - * @see #NONFATAL
183.673 - * @see #NOTIFS_LOST
183.674 - */
183.675 - public MBeanNotificationInfo[] getEventClientNotificationInfo() {
183.676 - return myInfo.clone();
183.677 - }
183.678 -
183.679 - private static boolean match(ListenerInfo li,
183.680 - ObjectName name,
183.681 - NotificationListener listener,
183.682 - boolean subscribed) {
183.683 - return li.getObjectName().equals(name) &&
183.684 - li.getListener() == listener &&
183.685 - li.isSubscription() == subscribed;
183.686 - }
183.687 -
183.688 - private static boolean match(ListenerInfo li,
183.689 - ObjectName name,
183.690 - NotificationListener listener,
183.691 - NotificationFilter filter,
183.692 - Object handback,
183.693 - boolean subscribed) {
183.694 - return li.getObjectName().equals(name) &&
183.695 - li.getFilter() == filter &&
183.696 - li.getListener() == listener &&
183.697 - li.getHandback() == handback &&
183.698 - li.isSubscription() == subscribed;
183.699 - }
183.700 -
183.701 -// ---------------------------------------------------
183.702 -// private classes
183.703 -// ---------------------------------------------------
183.704 - private class DispatchingJob extends RepeatedSingletonJob {
183.705 - public DispatchingJob() {
183.706 - super(distributingExecutor);
183.707 - }
183.708 -
183.709 - public boolean isSuspended() {
183.710 - return closed || buffer.size() == 0;
183.711 - }
183.712 -
183.713 - public void task() {
183.714 - TargetedNotification[] tns ;
183.715 - int lost = 0;
183.716 -
183.717 - synchronized(buffer) {
183.718 - tns = buffer.removeNotifs();
183.719 - lost = buffer.removeLost();
183.720 - }
183.721 -
183.722 - if ((tns == null || tns.length == 0)
183.723 - && lost == 0) {
183.724 - return;
183.725 - }
183.726 -
183.727 - // forwarding
183.728 - if (tns != null && tns.length > 0) {
183.729 - if (logger.traceOn()) {
183.730 - logger.trace("DispatchingJob-task",
183.731 - "Forwarding: "+tns.length);
183.732 - }
183.733 - for (TargetedNotification tn : tns) {
183.734 - final ListenerInfo li = listenerInfoMap.get(tn.getListenerID());
183.735 - try {
183.736 - li.getListener().handleNotification(tn.getNotification(),
183.737 - li.getHandback());
183.738 - } catch (Exception e) {
183.739 - logger.fine(
183.740 - "DispatchingJob.task", "listener got exception", e);
183.741 - }
183.742 - }
183.743 - }
183.744 -
183.745 - if (lost > 0) {
183.746 - if (logger.traceOn()) {
183.747 - logger.trace("DispatchingJob-task",
183.748 - "lost: "+lost);
183.749 - }
183.750 - final Notification n = new Notification(NOTIFS_LOST,
183.751 - EventClient.this,
183.752 - myNotifCounter.getAndIncrement(),
183.753 - System.currentTimeMillis(),
183.754 - "Lost notifications.");
183.755 - n.setUserData(new Long(lost));
183.756 - broadcaster.sendNotification(n);
183.757 - }
183.758 - }
183.759 - }
183.760 -
183.761 -
183.762 - private class EventReceiverImpl implements EventReceiver {
183.763 - public void receive(NotificationResult nr) {
183.764 - if (logger.traceOn()) {
183.765 - logger.trace("MyEventReceiver-receive", "");
183.766 - }
183.767 -
183.768 - synchronized(buffer) {
183.769 - buffer.addNotifs(nr);
183.770 -
183.771 - dispatchingJob.resume();
183.772 - }
183.773 - }
183.774 -
183.775 - public void failed(Throwable t) {
183.776 - if (logger.traceOn()) {
183.777 - logger.trace("MyEventReceiver-failed", "", t);
183.778 - }
183.779 - final Notification n = new Notification(FAILED,
183.780 - this,
183.781 - myNotifCounter.getAndIncrement(),
183.782 - System.currentTimeMillis());
183.783 - n.setSource(t);
183.784 - broadcaster.sendNotification(n);
183.785 - }
183.786 -
183.787 - public void nonFatal(Exception e) {
183.788 - if (logger.traceOn()) {
183.789 - logger.trace("MyEventReceiver-nonFatal", "", e);
183.790 - }
183.791 -
183.792 - final Notification n = new Notification(NONFATAL,
183.793 - this,
183.794 - myNotifCounter.getAndIncrement(),
183.795 - System.currentTimeMillis());
183.796 - n.setSource(e);
183.797 - broadcaster.sendNotification(n);
183.798 - }
183.799 - }
183.800 -
183.801 -// ----------------------------------------------------
183.802 -// private class
183.803 -// ----------------------------------------------------
183.804 -
183.805 -
183.806 -// ----------------------------------------------------
183.807 -// private methods
183.808 -// ----------------------------------------------------
183.809 - private Integer getListenerInfo(ObjectName name,
183.810 - NotificationListener listener,
183.811 - NotificationFilter filter,
183.812 - Object handback,
183.813 - boolean subscribed) throws ListenerNotFoundException {
183.814 -
183.815 - synchronized(listenerInfoMap) {
183.816 - for (Map.Entry<Integer, ListenerInfo> entry :
183.817 - listenerInfoMap.entrySet()) {
183.818 - ListenerInfo li = entry.getValue();
183.819 - if (match(li, name, listener, filter, handback, subscribed)) {
183.820 - return entry.getKey();
183.821 - }
183.822 - }
183.823 - }
183.824 -
183.825 - throw new ListenerNotFoundException();
183.826 - }
183.827 -
183.828 - private Integer getMatchedListenerInfo(ObjectName name,
183.829 - NotificationListener listener,
183.830 - boolean subscribed) throws ListenerNotFoundException {
183.831 -
183.832 - synchronized(listenerInfoMap) {
183.833 - for (Map.Entry<Integer, ListenerInfo> entry :
183.834 - listenerInfoMap.entrySet()) {
183.835 - ListenerInfo li = entry.getValue();
183.836 - if (li.getObjectName().equals(name) &&
183.837 - li.getListener() == listener &&
183.838 - li.isSubscription() == subscribed) {
183.839 - return entry.getKey();
183.840 - }
183.841 - }
183.842 - }
183.843 -
183.844 - throw new ListenerNotFoundException();
183.845 - }
183.846 -
183.847 - private Collection<Integer> getListenerInfo(ObjectName name,
183.848 - NotificationListener listener,
183.849 - boolean subscribed) throws ListenerNotFoundException {
183.850 -
183.851 - final ArrayList<Integer> ids = new ArrayList<Integer>();
183.852 - synchronized(listenerInfoMap) {
183.853 - for (Map.Entry<Integer, ListenerInfo> entry :
183.854 - listenerInfoMap.entrySet()) {
183.855 - ListenerInfo li = entry.getValue();
183.856 - if (match(li, name, listener, subscribed)) {
183.857 - ids.add(entry.getKey());
183.858 - }
183.859 - }
183.860 - }
183.861 -
183.862 - if (ids.isEmpty()) {
183.863 - throw new ListenerNotFoundException();
183.864 - }
183.865 -
183.866 - return ids;
183.867 - }
183.868 -
183.869 - private void checkState() throws IOException {
183.870 - synchronized(listenerInfoMap) {
183.871 - if (closed) {
183.872 - throw new IOException("Ended!");
183.873 - }
183.874 - }
183.875 - }
183.876 -
183.877 - private void startListening() throws IOException {
183.878 - synchronized(listenerInfoMap) {
183.879 - if (!startedListening && listenerInfoMap.size() > 0) {
183.880 - eventRelay.setEventReceiver(myReceiver);
183.881 - }
183.882 -
183.883 - startedListening = true;
183.884 -
183.885 - if (logger.traceOn()) {
183.886 - logger.trace("startListening", "listening");
183.887 - }
183.888 - }
183.889 - }
183.890 -
183.891 - private void stopListening() throws IOException {
183.892 - synchronized(listenerInfoMap) {
183.893 - if (listenerInfoMap.size() == 0 && startedListening) {
183.894 - eventRelay.setEventReceiver(null);
183.895 -
183.896 - startedListening = false;
183.897 -
183.898 - if (logger.traceOn()) {
183.899 - logger.trace("stopListening", "non listening");
183.900 - }
183.901 - }
183.902 - }
183.903 - }
183.904 -
183.905 - private void removeListener(Integer id)
183.906 - throws InstanceNotFoundException,
183.907 - ListenerNotFoundException,
183.908 - IOException {
183.909 - synchronized(listenerInfoMap) {
183.910 - if (listenerInfoMap.remove(id) == null) {
183.911 - throw new ListenerNotFoundException();
183.912 - }
183.913 -
183.914 - stopListening();
183.915 - }
183.916 -
183.917 - try {
183.918 - eventClientDelegate.removeListenerOrSubscriber(clientId, id);
183.919 - } catch (EventClientNotFoundException cnfe) {
183.920 - logger.trace("removeListener", "ecd.removeListener", cnfe);
183.921 - }
183.922 - }
183.923 -
183.924 -
183.925 -// ----------------------------------------------------
183.926 -// private variables
183.927 -// ----------------------------------------------------
183.928 - private static final ClassLogger logger =
183.929 - new ClassLogger("javax.management.event", "EventClient");
183.930 -
183.931 - private final Executor distributingExecutor;
183.932 - private final EventClientDelegateMBean eventClientDelegate;
183.933 - private final EventRelay eventRelay;
183.934 - private volatile String clientId = null;
183.935 - private final long requestedLeaseTime;
183.936 -
183.937 - private final ReceiverBuffer buffer = new ReceiverBuffer();
183.938 -
183.939 - private final EventReceiverImpl myReceiver =
183.940 - new EventReceiverImpl();
183.941 - private final DispatchingJob dispatchingJob;
183.942 -
183.943 - private final HashMap<Integer, ListenerInfo> listenerInfoMap =
183.944 - new HashMap<Integer, ListenerInfo>();
183.945 -
183.946 - private volatile boolean closed = false;
183.947 -
183.948 - private volatile boolean startedListening = false;
183.949 -
183.950 - // Could change synchronization here. But at worst a race will mean
183.951 - // sequence numbers are not contiguous, which may not matter much.
183.952 - private final AtomicLong myNotifCounter = new AtomicLong();
183.953 -
183.954 - private final static MBeanNotificationInfo[] myInfo =
183.955 - new MBeanNotificationInfo[] {
183.956 - new MBeanNotificationInfo(
183.957 - new String[] {FAILED, NONFATAL, NOTIFS_LOST},
183.958 - Notification.class.getName(),
183.959 - "Notifications that can be sent to a listener added with " +
183.960 - "EventClient.addEventClientListener")};
183.961 -
183.962 - private final NotificationBroadcasterSupport broadcaster =
183.963 - new NotificationBroadcasterSupport();
183.964 -
183.965 - private final static Executor callerExecutor = new Executor() {
183.966 - // DirectExecutor using caller thread
183.967 - public void execute(Runnable r) {
183.968 - r.run();
183.969 - }
183.970 - };
183.971 -
183.972 - private static void checkInit(final MBeanServerConnection conn,
183.973 - final ObjectName delegateName)
183.974 - throws IOException {
183.975 - if (conn == null) {
183.976 - throw new IllegalArgumentException("No connection specified");
183.977 - }
183.978 - if (delegateName != null &&
183.979 - (!conn.isRegistered(delegateName))) {
183.980 - throw new IllegalArgumentException(
183.981 - delegateName +
183.982 - ": not found");
183.983 - }
183.984 - if (delegateName == null &&
183.985 - (!conn.isRegistered(
183.986 - EventClientDelegate.OBJECT_NAME))) {
183.987 - throw new IllegalArgumentException(
183.988 - EventClientDelegate.OBJECT_NAME +
183.989 - ": not found");
183.990 - }
183.991 - }
183.992 -
183.993 -// ----------------------------------------------------
183.994 -// private event lease issues
183.995 -// ----------------------------------------------------
183.996 - private Callable<Long> renewLease = new Callable<Long>() {
183.997 - public Long call() throws IOException, EventClientNotFoundException {
183.998 - return eventClientDelegate.lease(clientId, requestedLeaseTime);
183.999 - }
183.1000 - };
183.1001 -
183.1002 - private final LeaseRenewer leaseRenewer;
183.1003 -
183.1004 -// ------------------------------------------------------------------------
183.1005 - /**
183.1006 - * Constructs an {@code MBeanServerConnection} that uses an {@code EventClient} object,
183.1007 - * if the underlying connection has an {@link EventClientDelegateMBean}.
183.1008 - * <P> The {@code EventClient} object creates a default
183.1009 - * {@link FetchingEventRelay} object to
183.1010 - * receive notifications forwarded by the {@link EventClientDelegateMBean}.
183.1011 - * The {@link EventClientDelegateMBean} it works with is the
183.1012 - * default one registered with the ObjectName
183.1013 - * {@link EventClientDelegate#OBJECT_NAME
183.1014 - * OBJECT_NAME}.
183.1015 - * The thread from the {@link FetchingEventRelay} object that fetches the
183.1016 - * notifications is also used to distribute them.
183.1017 - *
183.1018 - * @param conn An {@link MBeanServerConnection} object used to communicate
183.1019 - * with an {@link EventClientDelegateMBean}.
183.1020 - * @throws IllegalArgumentException If the value of {@code conn} is null,
183.1021 - * or the default {@link EventClientDelegateMBean} is not registered.
183.1022 - * @throws IOException If an I/O error occurs.
183.1023 - */
183.1024 - public static MBeanServerConnection getEventClientConnection(
183.1025 - final MBeanServerConnection conn)
183.1026 - throws IOException {
183.1027 - return getEventClientConnection(conn, null);
183.1028 - }
183.1029 -
183.1030 - /**
183.1031 - * Constructs an MBeanServerConnection that uses an {@code EventClient}
183.1032 - * object with a user-specific {@link EventRelay}
183.1033 - * object.
183.1034 - * <P>
183.1035 - * The {@link EventClientDelegateMBean} which it works with is the
183.1036 - * default one registered with the ObjectName
183.1037 - * {@link EventClientDelegate#OBJECT_NAME
183.1038 - * OBJECT_NAME}
183.1039 - * The thread that calls {@link EventReceiver#receive
183.1040 - * EventReceiver.receive} from the {@link EventRelay} object is used
183.1041 - * to distribute notifications to their listeners.
183.1042 - *
183.1043 - * @param conn An {@link MBeanServerConnection} object used to communicate
183.1044 - * with an {@link EventClientDelegateMBean}.
183.1045 - * @param eventRelay A user-specific object used to receive notifications
183.1046 - * forwarded by the {@link EventClientDelegateMBean}. If null, the default
183.1047 - * {@link FetchingEventRelay} object is used.
183.1048 - * @throws IllegalArgumentException If the value of {@code conn} is null,
183.1049 - * or the default {@link EventClientDelegateMBean} is not registered.
183.1050 - * @throws IOException If an I/O error occurs.
183.1051 - */
183.1052 - public static MBeanServerConnection getEventClientConnection(
183.1053 - final MBeanServerConnection conn,
183.1054 - final EventRelay eventRelay)
183.1055 - throws IOException {
183.1056 -
183.1057 - if (newEventConn == null) {
183.1058 - throw new IllegalArgumentException(
183.1059 - "Class not found: EventClientConnection");
183.1060 - }
183.1061 -
183.1062 - checkInit(conn,null);
183.1063 - final Callable<EventClient> factory = new Callable<EventClient>() {
183.1064 - final public EventClient call() throws Exception {
183.1065 - EventClientDelegateMBean ecd = EventClientDelegate.getProxy(conn);
183.1066 - return new EventClient(ecd, eventRelay, null, null,
183.1067 - DEFAULT_REQUESTED_LEASE_TIME);
183.1068 - }
183.1069 - };
183.1070 -
183.1071 - try {
183.1072 - return (MBeanServerConnection)newEventConn.invoke(null,
183.1073 - conn, factory);
183.1074 - } catch (Exception e) {
183.1075 - throw new IllegalArgumentException(e);
183.1076 - }
183.1077 - }
183.1078 -
183.1079 - private static Method newEventConn = null;
183.1080 - static {
183.1081 - try {
183.1082 - Class<?> c = Class.forName(
183.1083 - "com.sun.jmx.remote.util.EventClientConnection",
183.1084 - false, Thread.currentThread().getContextClassLoader());
183.1085 - newEventConn = c.getMethod("getEventConnectionFor",
183.1086 - MBeanServerConnection.class, Callable.class);
183.1087 - } catch (Exception e) {
183.1088 - // OK: we're running in a subset of our classes
183.1089 - }
183.1090 - }
183.1091 -
183.1092 - /**
183.1093 - * <p>Get the client id of this {@code EventClient} in the
183.1094 - * {@link EventClientDelegateMBean}.
183.1095 - *
183.1096 - * @return the client id.
183.1097 - *
183.1098 - * @see EventClientDelegateMBean#addClient(String, Object[], String[])
183.1099 - * EventClientDelegateMBean.addClient
183.1100 - */
183.1101 - public String getClientId() {
183.1102 - return clientId;
183.1103 - }
183.1104 -
183.1105 - private static final PerThreadGroupPool<ScheduledThreadPoolExecutor>
183.1106 - leaseRenewerThreadPool = PerThreadGroupPool.make();
183.1107 -}
184.1 --- a/src/share/classes/javax/management/event/EventClientDelegate.java Mon Nov 23 10:04:47 2009 +0000
184.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
184.3 @@ -1,824 +0,0 @@
184.4 -/*
184.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
184.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
184.7 - *
184.8 - * This code is free software; you can redistribute it and/or modify it
184.9 - * under the terms of the GNU General Public License version 2 only, as
184.10 - * published by the Free Software Foundation. Sun designates this
184.11 - * particular file as subject to the "Classpath" exception as provided
184.12 - * by Sun in the LICENSE file that accompanied this code.
184.13 - *
184.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
184.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
184.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
184.17 - * version 2 for more details (a copy is included in the LICENSE file that
184.18 - * accompanied this code).
184.19 - *
184.20 - * You should have received a copy of the GNU General Public License version
184.21 - * 2 along with this work; if not, write to the Free Software Foundation,
184.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
184.23 - *
184.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
184.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
184.26 - * have any questions.
184.27 - *
184.28 - * @since JMX 2.0
184.29 - */
184.30 -
184.31 -package javax.management.event;
184.32 -
184.33 -import java.io.IOException;
184.34 -import java.lang.reflect.Method;
184.35 -import java.util.HashMap;
184.36 -import java.util.Collection;
184.37 -import java.util.Collections;
184.38 -import java.util.UUID;
184.39 -
184.40 -import javax.management.InstanceNotFoundException;
184.41 -import javax.management.ListenerNotFoundException;
184.42 -import javax.management.Notification;
184.43 -import javax.management.NotificationFilter;
184.44 -import javax.management.NotificationListener;
184.45 -import javax.management.ObjectName;
184.46 -import javax.management.remote.NotificationResult;
184.47 -import com.sun.jmx.event.EventBuffer;
184.48 -import com.sun.jmx.event.LeaseManager;
184.49 -import com.sun.jmx.interceptor.SingleMBeanForwarder;
184.50 -import com.sun.jmx.mbeanserver.Util;
184.51 -import com.sun.jmx.remote.util.ClassLogger;
184.52 -import java.lang.ref.WeakReference;
184.53 -import java.lang.reflect.Constructor;
184.54 -import java.lang.reflect.InvocationHandler;
184.55 -import java.lang.reflect.Proxy;
184.56 -import java.security.AccessControlContext;
184.57 -import java.security.AccessController;
184.58 -import java.security.PrivilegedAction;
184.59 -import java.security.PrivilegedExceptionAction;
184.60 -import java.util.Arrays;
184.61 -import java.util.Map;
184.62 -import java.util.Set;
184.63 -import java.util.WeakHashMap;
184.64 -import java.util.concurrent.ConcurrentHashMap;
184.65 -import java.util.concurrent.atomic.AtomicInteger;
184.66 -import javax.management.DynamicMBean;
184.67 -import javax.management.MBeanException;
184.68 -import javax.management.MBeanPermission;
184.69 -import javax.management.MBeanServer;
184.70 -import javax.management.MBeanServerConnection;
184.71 -import javax.management.MBeanServerDelegate;
184.72 -import javax.management.MBeanServerInvocationHandler;
184.73 -import javax.management.MBeanServerNotification;
184.74 -import javax.management.ObjectInstance;
184.75 -import javax.management.StandardMBean;
184.76 -import javax.management.remote.MBeanServerForwarder;
184.77 -
184.78 -/**
184.79 - * This is the default implementation of the MBean
184.80 - * {@link EventClientDelegateMBean}.
184.81 - */
184.82 -public class EventClientDelegate implements EventClientDelegateMBean {
184.83 -
184.84 - private EventClientDelegate(MBeanServer server) {
184.85 - if (server == null) {
184.86 - throw new NullPointerException("Null MBeanServer.");
184.87 - }
184.88 -
184.89 - if (logger.traceOn()) {
184.90 - logger.trace("EventClientDelegate", "new one");
184.91 - }
184.92 - mbeanServer = server;
184.93 - eventSubscriber = EventSubscriber.getEventSubscriber(mbeanServer);
184.94 - }
184.95 -
184.96 - /**
184.97 - * Returns an {@code EventClientDelegate} instance for the given
184.98 - * {@code MBeanServer}. Calling this method more than once with the same
184.99 - * {@code server} argument may return the same object or a different object
184.100 - * each time. See {@link EventClientDelegateMBean} for an example use of
184.101 - * this method.
184.102 - *
184.103 - * @param server An MBean server instance to work with.
184.104 - * @return An {@code EventClientDelegate} instance.
184.105 - * @throws NullPointerException If {@code server} is null.
184.106 - */
184.107 - public static EventClientDelegate getEventClientDelegate(MBeanServer server) {
184.108 - EventClientDelegate delegate = null;
184.109 - synchronized(delegateMap) {
184.110 - final WeakReference<EventClientDelegate> wrf = delegateMap.get(server);
184.111 - delegate = (wrf == null) ? null : wrf.get();
184.112 -
184.113 - if (delegate == null) {
184.114 - delegate = new EventClientDelegate(server);
184.115 - try {
184.116 - // TODO: this may not work with federated MBean, because
184.117 - // the delegate will *not* emit notifications for those MBeans.
184.118 - delegate.mbeanServer.addNotificationListener(
184.119 - MBeanServerDelegate.DELEGATE_NAME,
184.120 - delegate.cleanListener, null, null);
184.121 - } catch (InstanceNotFoundException e) {
184.122 - logger.fine(
184.123 - "getEventClientDelegate",
184.124 - "Could not add MBeanServerDelegate listener", e);
184.125 - }
184.126 - delegateMap.put(server,
184.127 - new WeakReference<EventClientDelegate>(delegate));
184.128 - }
184.129 - }
184.130 -
184.131 - return delegate;
184.132 - }
184.133 -
184.134 - // Logic for the MBeanServerForwarder that simulates the existence of the
184.135 - // EventClientDelegate MBean. Things are complicated by the fact that
184.136 - // there may not be anything in the chain after this forwarder when it is
184.137 - // created - the connection to a real MBeanServer might only come later.
184.138 - // Recall that there are two ways of creating a JMXConnectorServer -
184.139 - // either you specify its MBeanServer when you create it, or you specify
184.140 - // no MBeanServer and register it in an MBeanServer later. In the latter
184.141 - // case, the forwarder chain points nowhere until this registration
184.142 - // happens. Since EventClientDelegate wants to add a listener to the
184.143 - // MBeanServerDelegate, we can't create an EventClientDelegate until
184.144 - // there is an MBeanServer. So the forwarder initially has
184.145 - // a dummy ECD where every method throws an exception, and
184.146 - // the real ECD is created as soon as doing so does not produce an
184.147 - // exception.
184.148 - // TODO: rewrite so that the switch from the dummy to the real ECD happens
184.149 - // just before we would otherwise have thrown UnsupportedOperationException.
184.150 - // This is more correct, because it's not guaranteed that we will see the
184.151 - // moment where the real MBeanServer is attached, if it happens by virtue
184.152 - // of a setMBeanServer on some other forwarder later in the chain.
184.153 -
184.154 - private static class Forwarder extends SingleMBeanForwarder {
184.155 - private MBeanServer loopMBS;
184.156 -
184.157 - private static class UnsupportedInvocationHandler
184.158 - implements InvocationHandler {
184.159 - public Object invoke(Object proxy, Method method, Object[] args)
184.160 - throws Throwable {
184.161 - throw new UnsupportedOperationException(
184.162 - "EventClientDelegate unavailable: no MBeanServer, or " +
184.163 - "MBeanServer inaccessible");
184.164 - }
184.165 - }
184.166 -
184.167 - private static DynamicMBean makeUnsupportedECD() {
184.168 - EventClientDelegateMBean unsupported = (EventClientDelegateMBean)
184.169 - Proxy.newProxyInstance(
184.170 - EventClientDelegateMBean.class.getClassLoader(),
184.171 - new Class<?>[] {EventClientDelegateMBean.class},
184.172 - new UnsupportedInvocationHandler());
184.173 - return new StandardMBean(
184.174 - unsupported, EventClientDelegateMBean.class, false);
184.175 - }
184.176 -
184.177 - private volatile boolean madeECD;
184.178 -
184.179 - Forwarder() {
184.180 - super(OBJECT_NAME, makeUnsupportedECD(), true);
184.181 - }
184.182 -
184.183 - synchronized void setLoopMBS(MBeanServer loopMBS) {
184.184 - this.loopMBS = loopMBS;
184.185 - }
184.186 -
184.187 - @Override
184.188 - public synchronized void setMBeanServer(final MBeanServer mbs) {
184.189 - super.setMBeanServer(mbs);
184.190 -
184.191 - if (!madeECD) {
184.192 - try {
184.193 - EventClientDelegate ecd =
184.194 - AccessController.doPrivileged(
184.195 - new PrivilegedAction<EventClientDelegate>() {
184.196 - public EventClientDelegate run() {
184.197 - return getEventClientDelegate(loopMBS);
184.198 - }
184.199 - });
184.200 - DynamicMBean mbean = new StandardMBean(
184.201 - ecd, EventClientDelegateMBean.class, false);
184.202 - setSingleMBean(mbean);
184.203 - madeECD = true;
184.204 - } catch (Exception e) {
184.205 - // OK: assume no MBeanServer
184.206 - logger.fine("setMBeanServer", "isRegistered", e);
184.207 - }
184.208 - }
184.209 - }
184.210 - }
184.211 -
184.212 - /**
184.213 - * <p>Create a new {@link MBeanServerForwarder} that simulates the existence
184.214 - * of an {@code EventClientDelegateMBean} with the {@linkplain
184.215 - * #OBJECT_NAME default name}. This forwarder intercepts MBean requests
184.216 - * that are targeted for that MBean and handles them itself. All other
184.217 - * requests are forwarded to the next element in the forwarder chain.</p>
184.218 - *
184.219 - * @param nextMBS the next {@code MBeanServer} in the chain of forwarders,
184.220 - * which might be another {@code MBeanServerForwarder} or a plain {@code
184.221 - * MBeanServer}. This is the object to which {@code MBeanServer} requests
184.222 - * that do not concern the {@code EventClientDelegateMBean} are sent.
184.223 - * It will be the value of {@link MBeanServerForwarder#getMBeanServer()
184.224 - * getMBeanServer()} on the returned object, and can be changed with {@link
184.225 - * MBeanServerForwarder#setMBeanServer setMBeanServer}. It can be null but
184.226 - * must be set to a non-null value before any {@code MBeanServer} requests
184.227 - * arrive.
184.228 - *
184.229 - * @param loopMBS the {@code MBeanServer} to which requests from the
184.230 - * {@code EventClientDelegateMBean} should be sent. For example,
184.231 - * when you invoke the {@link EventClientDelegateMBean#addListener
184.232 - * addListener} operation on the {@code EventClientDelegateMBean}, it will
184.233 - * result in a call to {@link
184.234 - * MBeanServer#addNotificationListener(ObjectName, NotificationListener,
184.235 - * NotificationFilter, Object) addNotificationListener} on this object.
184.236 - * If this parameter is null, then these requests will be sent to the
184.237 - * newly-created {@code MBeanServerForwarder}. Usually the parameter will
184.238 - * either be null or will be the result of {@link
184.239 - * javax.management.remote.JMXConnectorServer#getSystemMBeanServerForwarder()
184.240 - * getSystemMBeanServerForwarder()} for the connector server in which
184.241 - * this forwarder will be installed.
184.242 - *
184.243 - * @return a new {@code MBeanServerForwarder} that simulates the existence
184.244 - * of an {@code EventClientDelegateMBean}.
184.245 - *
184.246 - * @see javax.management.remote.JMXConnectorServer#installStandardForwarders
184.247 - */
184.248 - public static MBeanServerForwarder newForwarder(
184.249 - MBeanServer nextMBS, MBeanServer loopMBS) {
184.250 - Forwarder mbsf = new Forwarder();
184.251 - // We must setLoopMBS before setMBeanServer, because when we
184.252 - // setMBeanServer that will call getEventClientDelegate(loopMBS).
184.253 - if (loopMBS == null)
184.254 - loopMBS = mbsf;
184.255 - mbsf.setLoopMBS(loopMBS);
184.256 - if (nextMBS != null)
184.257 - mbsf.setMBeanServer(nextMBS);
184.258 - return mbsf;
184.259 - }
184.260 -
184.261 - /**
184.262 - * Returns a proxy of the default {@code EventClientDelegateMBean}.
184.263 - *
184.264 - * @param conn An {@link MBeanServerConnection} to work with.
184.265 - */
184.266 - @SuppressWarnings("cast") // cast for jdk 1.5
184.267 - public static EventClientDelegateMBean getProxy(MBeanServerConnection conn) {
184.268 - return (EventClientDelegateMBean)MBeanServerInvocationHandler.
184.269 - newProxyInstance(conn,
184.270 - OBJECT_NAME,
184.271 - EventClientDelegateMBean.class,
184.272 - false);
184.273 - }
184.274 -
184.275 - public String addClient(String className, Object[] params, String[] sig)
184.276 - throws MBeanException {
184.277 - return addClient(className, null, params, sig, true);
184.278 - }
184.279 -
184.280 - public String addClient(String className,
184.281 - ObjectName classLoader,
184.282 - Object[] params,
184.283 - String[] sig) throws MBeanException {
184.284 - return addClient(className, classLoader, params, sig, false);
184.285 - }
184.286 -
184.287 - private String addClient(String className,
184.288 - ObjectName classLoader,
184.289 - Object[] params,
184.290 - String[] sig,
184.291 - boolean classLoaderRepository) throws MBeanException {
184.292 - try {
184.293 - return addClientX(
184.294 - className, classLoader, params, sig, classLoaderRepository);
184.295 - } catch (RuntimeException e) {
184.296 - throw e;
184.297 - } catch (Exception e) {
184.298 - throw new MBeanException(e);
184.299 - }
184.300 - }
184.301 -
184.302 - private String addClientX(String className,
184.303 - ObjectName classLoader,
184.304 - Object[] params,
184.305 - String[] sig,
184.306 - boolean classLoaderRepository) throws Exception {
184.307 - if (className == null) {
184.308 - throw new IllegalArgumentException("Null class name.");
184.309 - }
184.310 -
184.311 - final Object o;
184.312 -
184.313 - // The special treatment of standard EventForwarders is so that no
184.314 - // special permissions are necessary to use them. Otherwise you
184.315 - // couldn't use EventClient if you didn't have permission to call
184.316 - // MBeanServer.instantiate. We do require that permission for
184.317 - // non-standard forwarders, because otherwise you could instantiate
184.318 - // any class with possibly adverse consequences. We also avoid using
184.319 - // MBeanInstantiator because it looks up constructors by loading each
184.320 - // class in the sig array, which means a remote user could cause any
184.321 - // class to be loaded. That's probably not hugely risky but still.
184.322 - if (className.startsWith("javax.management.event.")) {
184.323 - Class<?> c = Class.forName(
184.324 - className, false, this.getClass().getClassLoader());
184.325 - Constructor<?> foundCons = null;
184.326 - if (sig == null)
184.327 - sig = new String[0];
184.328 - for (Constructor<?> cons : c.getConstructors()) {
184.329 - Class<?>[] types = cons.getParameterTypes();
184.330 - String[] consSig = new String[types.length];
184.331 - for (int i = 0; i < types.length; i++)
184.332 - consSig[i] = types[i].getName();
184.333 - if (Arrays.equals(sig, consSig)) {
184.334 - foundCons = cons;
184.335 - break;
184.336 - }
184.337 - }
184.338 - if (foundCons == null) {
184.339 - throw new NoSuchMethodException(
184.340 - "Constructor for " + className + " with argument types " +
184.341 - Arrays.toString(sig));
184.342 - }
184.343 - o = foundCons.newInstance(params);
184.344 - } else if (classLoaderRepository) {
184.345 - o = mbeanServer.instantiate(className, params, sig);
184.346 - } else {
184.347 - o = mbeanServer.instantiate(className, classLoader, params, sig);
184.348 - }
184.349 -
184.350 - if (!(o instanceof EventForwarder)) {
184.351 - throw new IllegalArgumentException(
184.352 - className+" is not an EventForwarder class.");
184.353 - }
184.354 -
184.355 - final EventForwarder forwarder = (EventForwarder)o;
184.356 - final String clientId = UUID.randomUUID().toString();
184.357 - ClientInfo clientInfo = new ClientInfo(clientId, forwarder);
184.358 -
184.359 - clientInfoMap.put(clientId, clientInfo);
184.360 -
184.361 - forwarder.setClientId(clientId);
184.362 -
184.363 - if (logger.traceOn()) {
184.364 - logger.trace("addClient", clientId);
184.365 - }
184.366 -
184.367 - return clientId;
184.368 - }
184.369 -
184.370 - public Integer[] getListenerIds(String clientId)
184.371 - throws IOException, EventClientNotFoundException {
184.372 - ClientInfo clientInfo = getClientInfo(clientId);
184.373 -
184.374 - if (clientInfo == null) {
184.375 - throw new EventClientNotFoundException("The client is not found.");
184.376 - }
184.377 -
184.378 - Map<Integer, AddedListener> listenerInfoMap = clientInfo.listenerInfoMap;
184.379 - synchronized (listenerInfoMap) {
184.380 - Set<Integer> ids = listenerInfoMap.keySet();
184.381 - return ids.toArray(new Integer[ids.size()]);
184.382 - }
184.383 - }
184.384 -
184.385 - /**
184.386 - * {@inheritDoc}
184.387 - *
184.388 - * <p>The execution of this method includes a call to
184.389 - * {@link MBeanServer#addNotificationListener(ObjectName,
184.390 - * NotificationListener, NotificationFilter, Object)}.</p>
184.391 - */
184.392 - public Integer addListener(String clientId,
184.393 - final ObjectName name,
184.394 - NotificationFilter filter)
184.395 - throws EventClientNotFoundException, InstanceNotFoundException {
184.396 -
184.397 - if (logger.traceOn()) {
184.398 - logger.trace("addListener", "");
184.399 - }
184.400 -
184.401 - return getClientInfo(clientId).addListenerInfo(name, filter);
184.402 - }
184.403 -
184.404 - /**
184.405 - * {@inheritDoc}
184.406 - *
184.407 - * <p>The execution of this method can include call to
184.408 - * {@link MBeanServer#removeNotificationListener(ObjectName,
184.409 - * NotificationListener, NotificationFilter, Object)}.</p>
184.410 - */
184.411 - public void removeListenerOrSubscriber(String clientId, Integer listenerId)
184.412 - throws InstanceNotFoundException,
184.413 - ListenerNotFoundException,
184.414 - EventClientNotFoundException,
184.415 - IOException {
184.416 - if (logger.traceOn()) {
184.417 - logger.trace("removeListener", ""+listenerId);
184.418 - }
184.419 - getClientInfo(clientId).removeListenerInfo(listenerId);
184.420 - }
184.421 -
184.422 - /**
184.423 - * {@inheritDoc}
184.424 - *
184.425 - * <p>The execution of this method includes a call to
184.426 - * {@link MBeanServer#addNotificationListener(ObjectName,
184.427 - * NotificationListener, NotificationFilter, Object)} for
184.428 - * every MBean matching {@code name}. If {@code name} is
184.429 - * an {@code ObjectName} pattern, then the execution of this
184.430 - * method will include a call to {@link MBeanServer#queryNames}.</p>
184.431 - */
184.432 - public Integer addSubscriber(String clientId, ObjectName name,
184.433 - NotificationFilter filter)
184.434 - throws EventClientNotFoundException, IOException {
184.435 - if (logger.traceOn()) {
184.436 - logger.trace("addSubscriber", "");
184.437 - }
184.438 - return getClientInfo(clientId).subscribeListenerInfo(name, filter);
184.439 - }
184.440 -
184.441 - public NotificationResult fetchNotifications(String clientId,
184.442 - long startSequenceNumber,
184.443 - int maxNotifs,
184.444 - long timeout)
184.445 - throws EventClientNotFoundException {
184.446 - if (logger.traceOn()) {
184.447 - logger.trace("fetchNotifications", "for "+clientId);
184.448 - }
184.449 - return getClientInfo(clientId).fetchNotifications(startSequenceNumber,
184.450 - maxNotifs,
184.451 - timeout);
184.452 - }
184.453 -
184.454 - public void removeClient(String clientId)
184.455 - throws EventClientNotFoundException {
184.456 - if (clientId == null)
184.457 - throw new EventClientNotFoundException("Null clientId");
184.458 - if (logger.traceOn()) {
184.459 - logger.trace("removeClient", clientId);
184.460 - }
184.461 - ClientInfo ci = null;
184.462 - ci = clientInfoMap.remove(clientId);
184.463 -
184.464 - if (ci == null) {
184.465 - throw new EventClientNotFoundException("clientId is "+clientId);
184.466 - } else {
184.467 - ci.clean();
184.468 - }
184.469 - }
184.470 -
184.471 - public long lease(String clientId, long timeout)
184.472 - throws IOException, EventClientNotFoundException {
184.473 - if (logger.traceOn()) {
184.474 - logger.trace("lease", "for "+clientId);
184.475 - }
184.476 - return getClientInfo(clientId).lease(timeout);
184.477 - }
184.478 -
184.479 - // ------------------------------------
184.480 - // private classes
184.481 - // ------------------------------------
184.482 - private class ClientInfo {
184.483 - final String clientId;
184.484 - final NotificationListener clientListener;
184.485 - final Map<Integer, AddedListener> listenerInfoMap =
184.486 - new HashMap<Integer, AddedListener>();
184.487 -
184.488 - ClientInfo(String clientId, EventForwarder forwarder) {
184.489 - this.clientId = clientId;
184.490 - this.forwarder = forwarder;
184.491 - clientListener =
184.492 - new ForwardingClientListener(listenerInfoMap, forwarder);
184.493 - }
184.494 -
184.495 - Integer addOrSubscribeListenerInfo(
184.496 - ObjectName name, NotificationFilter filter, boolean subscribe)
184.497 - throws InstanceNotFoundException, IOException {
184.498 -
184.499 - final Integer listenerId = nextListenerId();
184.500 - AddedListener listenerInfo = new AddedListener(
184.501 - listenerId, filter, name, subscribe);
184.502 - if (subscribe) {
184.503 - eventSubscriber.subscribe(name,
184.504 - clientListener,
184.505 - filter,
184.506 - listenerInfo);
184.507 - } else {
184.508 - mbeanServer.addNotificationListener(name,
184.509 - clientListener,
184.510 - filter,
184.511 - listenerInfo);
184.512 - }
184.513 -
184.514 - synchronized(listenerInfoMap) {
184.515 - listenerInfoMap.put(listenerId, listenerInfo);
184.516 - }
184.517 -
184.518 - return listenerId;
184.519 - }
184.520 -
184.521 - Integer addListenerInfo(ObjectName name,
184.522 - NotificationFilter filter) throws InstanceNotFoundException {
184.523 - try {
184.524 - return addOrSubscribeListenerInfo(name, filter, false);
184.525 - } catch (IOException e) { // can't happen
184.526 - logger.warning(
184.527 - "EventClientDelegate.addListenerInfo",
184.528 - "unexpected exception", e);
184.529 - throw new RuntimeException(e);
184.530 - }
184.531 - }
184.532 -
184.533 - Integer subscribeListenerInfo(ObjectName name,
184.534 - NotificationFilter filter) throws IOException {
184.535 - try {
184.536 - return addOrSubscribeListenerInfo(name, filter, true);
184.537 - } catch (InstanceNotFoundException e) { // can't happen
184.538 - logger.warning(
184.539 - "EventClientDelegate.subscribeListenerInfo",
184.540 - "unexpected exception", e);
184.541 - throw new RuntimeException(e);
184.542 - }
184.543 - }
184.544 -
184.545 - private final AtomicInteger nextListenerId = new AtomicInteger();
184.546 -
184.547 - private Integer nextListenerId() {
184.548 - return nextListenerId.getAndIncrement();
184.549 - }
184.550 -
184.551 - NotificationResult fetchNotifications(long startSequenceNumber,
184.552 - int maxNotifs,
184.553 - long timeout) {
184.554 -
184.555 - if (!(forwarder instanceof FetchingEventForwarder)) {
184.556 - throw new IllegalArgumentException(
184.557 - "This client is using Event Postal Service!");
184.558 - }
184.559 -
184.560 - return ((FetchingEventForwarder)forwarder).
184.561 - fetchNotifications(startSequenceNumber,
184.562 - maxNotifs, timeout);
184.563 - }
184.564 -
184.565 - void removeListenerInfo(Integer listenerId)
184.566 - throws InstanceNotFoundException, ListenerNotFoundException, IOException {
184.567 - AddedListener listenerInfo;
184.568 - synchronized(listenerInfoMap) {
184.569 - listenerInfo = listenerInfoMap.remove(listenerId);
184.570 - }
184.571 -
184.572 - if (listenerInfo == null) {
184.573 - throw new ListenerNotFoundException("The listener is not found.");
184.574 - }
184.575 -
184.576 - if (listenerInfo.subscription) {
184.577 - eventSubscriber.unsubscribe(listenerInfo.name,
184.578 - clientListener);
184.579 - } else {
184.580 - mbeanServer.removeNotificationListener(listenerInfo.name,
184.581 - clientListener,
184.582 - listenerInfo.filter,
184.583 - listenerInfo);
184.584 - }
184.585 - }
184.586 -
184.587 - void clean(ObjectName name) {
184.588 - synchronized(listenerInfoMap) {
184.589 - for (Map.Entry<Integer, AddedListener> entry :
184.590 - listenerInfoMap.entrySet()) {
184.591 - AddedListener li = entry.getValue();
184.592 - if (name.equals(li.name)) {
184.593 - listenerInfoMap.remove(entry.getKey());
184.594 - }
184.595 - }
184.596 - }
184.597 - }
184.598 -
184.599 - void clean() {
184.600 - synchronized(listenerInfoMap) {
184.601 - for (AddedListener li : listenerInfoMap.values()) {
184.602 - try {
184.603 - mbeanServer.removeNotificationListener(li.name,
184.604 - clientListener);
184.605 - } catch (Exception e) {
184.606 - logger.trace("ClientInfo.clean", "removeNL", e);
184.607 - }
184.608 - }
184.609 - listenerInfoMap.clear();
184.610 - }
184.611 -
184.612 - try {
184.613 - forwarder.close();
184.614 - } catch (Exception e) {
184.615 - logger.trace(
184.616 - "ClientInfo.clean", "forwarder.close", e);
184.617 - }
184.618 -
184.619 - if (leaseManager != null) {
184.620 - leaseManager.stop();
184.621 - }
184.622 - }
184.623 -
184.624 - long lease(long timeout) {
184.625 - return leaseManager.lease(timeout);
184.626 - }
184.627 -
184.628 - @Override
184.629 - public boolean equals(Object o) {
184.630 - if (this == o) {
184.631 - return true;
184.632 - }
184.633 -
184.634 - if (o instanceof ClientInfo &&
184.635 - clientId.equals(((ClientInfo)o).clientId)) {
184.636 - return true;
184.637 - }
184.638 -
184.639 - return false;
184.640 - }
184.641 -
184.642 - @Override
184.643 - public int hashCode() {
184.644 - return clientId.hashCode();
184.645 - }
184.646 -
184.647 - private EventForwarder forwarder = null;
184.648 -
184.649 - private final Runnable leaseExpiryCallback = new Runnable() {
184.650 - public void run() {
184.651 - try {
184.652 - removeClient(clientId);
184.653 - } catch (Exception e) {
184.654 - logger.trace(
184.655 - "ClientInfo.leaseExpiryCallback", "removeClient", e);
184.656 - }
184.657 - }
184.658 - };
184.659 -
184.660 - private LeaseManager leaseManager = new LeaseManager(leaseExpiryCallback);
184.661 - }
184.662 -
184.663 - private class ForwardingClientListener implements NotificationListener {
184.664 - public ForwardingClientListener(Map<Integer, AddedListener> listenerInfoMap,
184.665 - EventForwarder forwarder) {
184.666 - this.listenerInfoMap = listenerInfoMap;
184.667 - this.forwarder = forwarder;
184.668 - }
184.669 -
184.670 - public void handleNotification(Notification n, Object o) {
184.671 - if (n == null || (!(o instanceof AddedListener))) {
184.672 - if (logger.traceOn()) {
184.673 - logger.trace("ForwardingClientListener-handleNotification",
184.674 - "received a unknown notif");
184.675 - }
184.676 - return;
184.677 - }
184.678 -
184.679 - AddedListener li = (AddedListener) o;
184.680 -
184.681 - if (checkListenerPermission(li.name,li.acc)) {
184.682 - try {
184.683 - forwarder.forward(n, li.listenerId);
184.684 - } catch (Exception e) {
184.685 - if (logger.traceOn()) {
184.686 - logger.trace(
184.687 - "ForwardingClientListener-handleNotification",
184.688 - "forwarding failed.", e);
184.689 - }
184.690 - }
184.691 - }
184.692 - }
184.693 -
184.694 - private final Map<Integer, AddedListener> listenerInfoMap;
184.695 - private final EventForwarder forwarder;
184.696 - }
184.697 -
184.698 - private class AddedListener {
184.699 - final int listenerId;
184.700 - final NotificationFilter filter;
184.701 - final ObjectName name;
184.702 - final boolean subscription;
184.703 - final AccessControlContext acc;
184.704 -
184.705 - public AddedListener(
184.706 - int listenerId,
184.707 - NotificationFilter filter,
184.708 - ObjectName name,
184.709 - boolean subscription) {
184.710 - this.listenerId = listenerId;
184.711 - this.filter = filter;
184.712 - this.name = name;
184.713 - this.subscription = subscription;
184.714 - acc = AccessController.getContext();
184.715 - }
184.716 - }
184.717 -
184.718 - private class CleanListener implements NotificationListener {
184.719 - public void handleNotification(Notification notification,
184.720 - Object handback) {
184.721 - if (notification instanceof MBeanServerNotification) {
184.722 - if (MBeanServerNotification.UNREGISTRATION_NOTIFICATION.equals(
184.723 - notification.getType())) {
184.724 - final ObjectName name =
184.725 - ((MBeanServerNotification)notification).getMBeanName();
184.726 -
184.727 - final Collection <ClientInfo> list =
184.728 - Collections.unmodifiableCollection(clientInfoMap.values());
184.729 -
184.730 - for (ClientInfo ci : list) {
184.731 - ci.clean(name);
184.732 - }
184.733 - }
184.734 -
184.735 - }
184.736 - }
184.737 - }
184.738 -
184.739 - // -------------------------------------------------
184.740 - // private method
184.741 - // -------------------------------------------------
184.742 - private ClientInfo getClientInfo(String clientId)
184.743 - throws EventClientNotFoundException {
184.744 - ClientInfo clientInfo = null;
184.745 - clientInfo = clientInfoMap.get(clientId);
184.746 -
184.747 - if (clientInfo == null) {
184.748 - throw new EventClientNotFoundException(
184.749 - "Client not found (id " + clientId + ")");
184.750 - }
184.751 -
184.752 - return clientInfo;
184.753 - }
184.754 -
184.755 - /**
184.756 - * Explicitly check the MBeanPermission for
184.757 - * the current access control context.
184.758 - */
184.759 - private boolean checkListenerPermission(final ObjectName name,
184.760 - final AccessControlContext acc) {
184.761 - if (logger.traceOn()) {
184.762 - logger.trace("checkListenerPermission", "");
184.763 - }
184.764 - SecurityManager sm = System.getSecurityManager();
184.765 - if (sm != null) {
184.766 - try {
184.767 - final String serverName = getMBeanServerName();
184.768 -
184.769 - ObjectInstance oi = (ObjectInstance)
184.770 - AccessController.doPrivileged(
184.771 - new PrivilegedExceptionAction<Object>() {
184.772 - public Object run()
184.773 - throws InstanceNotFoundException {
184.774 - return mbeanServer.getObjectInstance(name);
184.775 - }
184.776 - });
184.777 -
184.778 - String classname = oi.getClassName();
184.779 - MBeanPermission perm = new MBeanPermission(
184.780 - serverName,
184.781 - classname,
184.782 - null,
184.783 - name,
184.784 - "addNotificationListener");
184.785 - sm.checkPermission(perm, acc);
184.786 - } catch (Exception e) {
184.787 - if (logger.debugOn()) {
184.788 - logger.debug("checkListenerPermission", "refused.", e);
184.789 - }
184.790 - return false;
184.791 - }
184.792 - }
184.793 - return true;
184.794 - }
184.795 -
184.796 - private String getMBeanServerName() {
184.797 - if (mbeanServerName != null) return mbeanServerName;
184.798 - else return (mbeanServerName = getMBeanServerName(mbeanServer));
184.799 - }
184.800 -
184.801 - private static String getMBeanServerName(final MBeanServer server) {
184.802 - final PrivilegedAction<String> action = new PrivilegedAction<String>() {
184.803 - public String run() {
184.804 - return Util.getMBeanServerSecurityName(server);
184.805 - }
184.806 - };
184.807 - return AccessController.doPrivileged(action);
184.808 - }
184.809 -
184.810 - // ------------------------------------
184.811 - // private variables
184.812 - // ------------------------------------
184.813 - private final MBeanServer mbeanServer;
184.814 - private volatile String mbeanServerName = null;
184.815 - private Map<String, ClientInfo> clientInfoMap =
184.816 - new ConcurrentHashMap<String, ClientInfo>();
184.817 -
184.818 - private final CleanListener cleanListener = new CleanListener();
184.819 - private final EventSubscriber eventSubscriber;
184.820 -
184.821 - private static final ClassLogger logger =
184.822 - new ClassLogger("javax.management.event", "EventClientDelegate");
184.823 -
184.824 - private static final
184.825 - Map<MBeanServer, WeakReference<EventClientDelegate>> delegateMap =
184.826 - new WeakHashMap<MBeanServer, WeakReference<EventClientDelegate>>();
184.827 -}
185.1 --- a/src/share/classes/javax/management/event/EventClientDelegateMBean.java Mon Nov 23 10:04:47 2009 +0000
185.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
185.3 @@ -1,317 +0,0 @@
185.4 -/*
185.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
185.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
185.7 - *
185.8 - * This code is free software; you can redistribute it and/or modify it
185.9 - * under the terms of the GNU General Public License version 2 only, as
185.10 - * published by the Free Software Foundation. Sun designates this
185.11 - * particular file as subject to the "Classpath" exception as provided
185.12 - * by Sun in the LICENSE file that accompanied this code.
185.13 - *
185.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
185.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
185.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
185.17 - * version 2 for more details (a copy is included in the LICENSE file that
185.18 - * accompanied this code).
185.19 - *
185.20 - * You should have received a copy of the GNU General Public License version
185.21 - * 2 along with this work; if not, write to the Free Software Foundation,
185.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
185.23 - *
185.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
185.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
185.26 - * have any questions.
185.27 - */
185.28 -
185.29 -package javax.management.event;
185.30 -
185.31 -import com.sun.jmx.mbeanserver.Util;
185.32 -import java.io.IOException;
185.33 -import javax.management.InstanceNotFoundException;
185.34 -import javax.management.ListenerNotFoundException;
185.35 -import javax.management.MBeanException;
185.36 -import javax.management.NotificationFilter;
185.37 -import javax.management.ObjectName;
185.38 -import javax.management.remote.NotificationResult;
185.39 -
185.40 -/**
185.41 - * <p>This interface specifies necessary methods on the MBean server
185.42 - * side for a JMX remote client to manage its notification listeners as
185.43 - * if they are local.
185.44 - * Users do not usually work directly with this MBean; instead, the {@link
185.45 - * EventClient} class is designed to be used directly by the user.</p>
185.46 - *
185.47 - * <p>A default implementation of this interface can be added to an MBean
185.48 - * Server in one of several ways.</p>
185.49 - *
185.50 - * <ul>
185.51 - * <li><p>The most usual is to insert an {@link
185.52 - * javax.management.remote.MBeanServerForwarder MBeanServerForwarder} between
185.53 - * the {@linkplain javax.management.remote.JMXConnectorServer Connector Server}
185.54 - * and the MBean Server, that will intercept accesses to the Event Client
185.55 - * Delegate MBean and treat them as the real MBean would. This forwarder is
185.56 - * inserted by default with the standard RMI Connector Server, and can also
185.57 - * be created explicitly using {@link EventClientDelegate#newForwarder
185.58 - * EventClientDelegate.newForwarder}.
185.59 - *
185.60 - * <li><p>A variant on the above is to replace the MBean Server that is
185.61 - * used locally with a forwarder as described above. Since
185.62 - * {@code MBeanServerForwarder} extends {@code MBeanServer}, you can use
185.63 - * a forwarder anywhere you would have used the original MBean Server. The
185.64 - * code to do this replacement typically looks something like this:</p>
185.65 - *
185.66 - * <pre>
185.67 - * MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); // or whatever
185.68 - * mbs = EventClientDelegate.newForwarder(mbs, null);
185.69 - * // now use mbs just as you did before, but it will have an EventClientDelegate
185.70 - * </pre>
185.71 - *
185.72 - * <li><p>The final way is to create an instance of {@link EventClientDelegate}
185.73 - * and register it in the MBean Server under the standard {@linkplain
185.74 - * #OBJECT_NAME name}:</p>
185.75 - *
185.76 - * <pre>
185.77 - * MBeanServer mbs = ManagementFactory.getPlatformMBeanServer(); // or whatever
185.78 - * EventClientDelegate ecd = EventClientDelegate.getEventClientDelegate(mbs);
185.79 - * mbs.registerMBean(ecd, EventClientDelegateMBean.OBJECT_NAME);
185.80 - * <pre>
185.81 - * </ul>
185.82 - *
185.83 - * @since JMX 2.0
185.84 - */
185.85 -public interface EventClientDelegateMBean {
185.86 - /**
185.87 - * The string representation of {@link #OBJECT_NAME}.
185.88 - */
185.89 - // This shouldn't really be necessary but an apparent javadoc bug
185.90 - // meant that the {@value} tags didn't work if this was a
185.91 - // field in EventClientDelegate, even a public field.
185.92 - public static final String OBJECT_NAME_STRING =
185.93 - "javax.management.event:type=EventClientDelegate";
185.94 -
185.95 - /**
185.96 - * The standard <code>ObjectName</code> used to register the default
185.97 - * <code>EventClientDelegateMBean</code>. The name is
185.98 - * <code>{@value #OBJECT_NAME_STRING}</code>.
185.99 - */
185.100 - public final static ObjectName OBJECT_NAME =
185.101 - ObjectName.valueOf(OBJECT_NAME_STRING);
185.102 -
185.103 - /**
185.104 - * A unique listener identifier specified for an EventClient.
185.105 - * Any notification associated with this id is intended for
185.106 - * the EventClient which receives the notification, rather than
185.107 - * a listener added using that EventClient.
185.108 - */
185.109 - public static final int EVENT_CLIENT_LISTENER_ID = -100;
185.110 -
185.111 - /**
185.112 - * Adds a new client to the <code>EventClientDelegateMBean</code> with
185.113 - * a user-specified
185.114 - * {@link EventForwarder} to forward notifications to the client. The
185.115 - * <code>EventForwarder</code> is created by calling
185.116 - * {@link javax.management.MBeanServer#instantiate(String, Object[],
185.117 - * String[])}.
185.118 - *
185.119 - * @param className The class name used to create an
185.120 - * {@code EventForwarder}.
185.121 - * @param params An array containing the parameters of the constructor to
185.122 - * be invoked.
185.123 - * @param sig An array containing the signature of the constructor to be
185.124 - * invoked
185.125 - * @return A client identifier.
185.126 - * @exception IOException Reserved for a remote call to throw on the client
185.127 - * side.
185.128 - * @exception MBeanException An exception thrown when creating the user
185.129 - * specified <code>EventForwarder</code>.
185.130 - */
185.131 - public String addClient(String className, Object[] params, String[] sig)
185.132 - throws IOException, MBeanException;
185.133 -
185.134 - /**
185.135 - * Adds a new client to the <code>EventClientDelegateMBean</code> with
185.136 - * a user-specified
185.137 - * {@link EventForwarder} to forward notifications to the client. The
185.138 - * <code>EventForwarder</code> is created by calling
185.139 - * {@link javax.management.MBeanServer#instantiate(String, ObjectName,
185.140 - * Object[], String[])}. A user-specified class loader is used to create
185.141 - * this <code>EventForwarder</code>.
185.142 - *
185.143 - * @param className The class name used to create an
185.144 - * {@code EventForwarder}.
185.145 - * @param classLoader An ObjectName registered as a
185.146 - * <code>ClassLoader</code> MBean.
185.147 - * @param params An array containing the parameters of the constructor to
185.148 - * be invoked.
185.149 - * @param sig An array containing the signature of the constructor to be
185.150 - * invoked
185.151 - * @return A client identifier.
185.152 - * @exception IOException Reserved for a remote call to throw on the client
185.153 - * side.
185.154 - * @exception MBeanException An exception thrown when creating the user
185.155 - * specified <code>EventForwarder</code>.
185.156 - */
185.157 - public String addClient(String className,
185.158 - ObjectName classLoader,
185.159 - Object[] params,
185.160 - String[] sig) throws IOException, MBeanException;
185.161 -
185.162 - /**
185.163 - * Removes an added client. Calling this method will remove all listeners
185.164 - * added with the client.
185.165 - *
185.166 - * @exception EventClientNotFoundException If the {@code clientId} is
185.167 - * not found.
185.168 - * @exception IOException Reserved for a remote call to throw on the client
185.169 - * side.
185.170 - */
185.171 - public void removeClient(String clientID)
185.172 - throws EventClientNotFoundException, IOException;
185.173 -
185.174 - /**
185.175 - * Returns the identifiers of listeners added or subscribed to with the
185.176 - * specified client identifier.
185.177 - * <P> If no listener is currently registered with the client, an empty
185.178 - * array is returned.
185.179 - * @param clientID The client identifier with which the listeners are
185.180 - * added or subscribed to.
185.181 - * @return An array of listener identifiers.
185.182 - * @exception EventClientNotFoundException If the {@code clientId} is
185.183 - * not found.
185.184 - * @exception IOException Reserved for a remote call to throw on the client
185.185 - * side.
185.186 - */
185.187 - public Integer[] getListenerIds(String clientID)
185.188 - throws EventClientNotFoundException, IOException;
185.189 -
185.190 - /**
185.191 - * Adds a listener to receive notifications from an MBean and returns
185.192 - * a non-negative integer as the identifier of the listener.
185.193 - * <P>This method is called by an {@link EventClient} to implement the
185.194 - * method {@link EventClient#addNotificationListener(ObjectName,
185.195 - * NotificationListener, NotificationFilter, Object)}.
185.196 - *
185.197 - * @param name The name of the MBean onto which the listener should be added.
185.198 - * @param filter The filter object. If {@code filter} is null,
185.199 - * no filtering will be performed before handling notifications.
185.200 - * @param clientId The client identifier with which the listener is added.
185.201 - * @return A listener identifier.
185.202 - * @throws EventClientNotFoundException Thrown if the {@code clientId} is
185.203 - * not found.
185.204 - * @throws InstanceNotFoundException Thrown if the MBean is not found.
185.205 - * @throws IOException Reserved for a remote call to throw on the client
185.206 - * side.
185.207 - */
185.208 - public Integer addListener(String clientId,
185.209 - ObjectName name,
185.210 - NotificationFilter filter)
185.211 - throws InstanceNotFoundException, EventClientNotFoundException,
185.212 - IOException;
185.213 -
185.214 -
185.215 - /**
185.216 - * <p>Subscribes a listener to receive notifications from an MBean or a
185.217 - * set of MBeans represented by an {@code ObjectName} pattern. (It is
185.218 - * not an error if no MBeans match the pattern at the time this method is
185.219 - * called.)</p>
185.220 - *
185.221 - * <p>Returns a non-negative integer as the identifier of the listener.</p>
185.222 - *
185.223 - * <p>This method is called by an {@link EventClient} to execute its
185.224 - * method {@link EventClient#subscribe(ObjectName, NotificationListener,
185.225 - * NotificationFilter, Object)}.</p>
185.226 - *
185.227 - * @param clientId The remote client's identifier.
185.228 - * @param name The name of an MBean or an {@code ObjectName} pattern
185.229 - * representing a set of MBeans to which the listener should listen.
185.230 - * @param filter The filter object. If {@code filter} is null, no
185.231 - * filtering will be performed before notifications are handled.
185.232 - *
185.233 - * @return A listener identifier.
185.234 - *
185.235 - * @throws IllegalArgumentException If the {@code name} or
185.236 - * {@code listener} is null.
185.237 - * @throws EventClientNotFoundException If the client ID is not found.
185.238 - * @throws IOException Reserved for a remote client to throw if
185.239 - * an I/O error occurs.
185.240 - *
185.241 - * @see EventConsumer#subscribe(ObjectName, NotificationListener,
185.242 - * NotificationFilter,Object)
185.243 - * @see #removeListenerOrSubscriber(String, Integer)
185.244 - */
185.245 - public Integer addSubscriber(String clientId, ObjectName name,
185.246 - NotificationFilter filter)
185.247 - throws EventClientNotFoundException, IOException;
185.248 -
185.249 - /**
185.250 - * Removes a listener, to stop receiving notifications.
185.251 - * <P> This method is called by an {@link EventClient} to execute its
185.252 - * methods {@link EventClient#removeNotificationListener(ObjectName,
185.253 - * NotificationListener, NotificationFilter, Object)},
185.254 - * {@link EventClient#removeNotificationListener(ObjectName,
185.255 - * NotificationListener)}, and {@link EventClient#unsubscribe}.
185.256 - *
185.257 - * @param clientId The client identifier with which the listener was added.
185.258 - * @param listenerId The listener identifier to be removed. This must be
185.259 - * an identifier returned by a previous {@link #addListener addListener}
185.260 - * or {@link #addSubscriber addSubscriber} call.
185.261 - *
185.262 - * @throws InstanceNotFoundException if the MBean on which the listener
185.263 - * was added no longer exists.
185.264 - * @throws ListenerNotFoundException if there is no listener with the
185.265 - * given {@code listenerId}.
185.266 - * @throws EventClientNotFoundException if the {@code clientId} is
185.267 - * not found.
185.268 - * @throws IOException Reserved for a remote call to throw on the client
185.269 - * side.
185.270 - */
185.271 - public void removeListenerOrSubscriber(String clientId, Integer listenerId)
185.272 - throws InstanceNotFoundException, ListenerNotFoundException,
185.273 - EventClientNotFoundException, IOException;
185.274 -
185.275 - /**
185.276 - * Called by a client to fetch notifications that are to be sent to its
185.277 - * listeners.
185.278 - *
185.279 - * @param clientId The client's identifier.
185.280 - * @param startSequenceNumber The first sequence number to
185.281 - * consider.
185.282 - * @param timeout The maximum waiting time.
185.283 - * @param maxNotifs The maximum number of notifications to return.
185.284 - *
185.285 - * @throws EventClientNotFoundException Thrown if the {@code clientId} is
185.286 - * not found.
185.287 - * @throws IllegalArgumentException if the client was {@linkplain
185.288 - * #addClient(String, Object[], String[]) added} with an {@link
185.289 - * EventForwarder} that is not a {@link FetchingEventForwarder}.
185.290 - * @throws IOException Reserved for a remote call to throw on the client
185.291 - * side.
185.292 - */
185.293 - public NotificationResult fetchNotifications(String clientId,
185.294 - long startSequenceNumber,
185.295 - int maxNotifs,
185.296 - long timeout)
185.297 - throws EventClientNotFoundException, IOException;
185.298 -
185.299 - /**
185.300 - * An {@code EventClient} calls this method to keep its {@code clientId}
185.301 - * alive in this MBean. The client will be removed if the lease times out.
185.302 - *
185.303 - * @param clientId The client's identifier.
185.304 - * @param timeout The time in milliseconds by which the lease is to be
185.305 - * extended. The value zero has no special meaning, so it will cause the
185.306 - * lease to time out immediately.
185.307 - *
185.308 - * @return The new lifetime of the lease in milliseconds. This may be
185.309 - * different from the requested time.
185.310 - *
185.311 - * @throws EventClientNotFoundException if the {@code clientId} is
185.312 - * not found.
185.313 - * @throws IOException reserved for a remote call to throw on the client
185.314 - * side.
185.315 - * @throws IllegalArgumentException if {@code clientId} is null or
185.316 - * {@code timeout} is negative.
185.317 - */
185.318 - public long lease(String clientId, long timeout)
185.319 - throws IOException, EventClientNotFoundException;
185.320 -}
186.1 --- a/src/share/classes/javax/management/event/EventClientNotFoundException.java Mon Nov 23 10:04:47 2009 +0000
186.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
186.3 @@ -1,79 +0,0 @@
186.4 -/*
186.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
186.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
186.7 - *
186.8 - * This code is free software; you can redistribute it and/or modify it
186.9 - * under the terms of the GNU General Public License version 2 only, as
186.10 - * published by the Free Software Foundation. Sun designates this
186.11 - * particular file as subject to the "Classpath" exception as provided
186.12 - * by Sun in the LICENSE file that accompanied this code.
186.13 - *
186.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
186.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
186.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
186.17 - * version 2 for more details (a copy is included in the LICENSE file that
186.18 - * accompanied this code).
186.19 - *
186.20 - * You should have received a copy of the GNU General Public License version
186.21 - * 2 along with this work; if not, write to the Free Software Foundation,
186.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
186.23 - *
186.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
186.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
186.26 - * have any questions.
186.27 - */
186.28 -
186.29 -package javax.management.event;
186.30 -
186.31 -import javax.management.JMException;
186.32 -
186.33 -/**
186.34 - * Thrown if an event client identifier is unknown.
186.35 - */
186.36 -public class EventClientNotFoundException extends JMException {
186.37 -
186.38 - /* Serial version */
186.39 - private static final long serialVersionUID = -3910667345840643089L;
186.40 -
186.41 - /**
186.42 - *Constructs a {@code ClientNotFoundException} without a detail message.
186.43 - */
186.44 - public EventClientNotFoundException() {
186.45 - super();
186.46 - }
186.47 -
186.48 - /**
186.49 - * Constructs a {@code ClientNotFoundException} with the specified detail message.
186.50 - * @param message The message.
186.51 - */
186.52 - public EventClientNotFoundException(String message) {
186.53 - super(message);
186.54 - }
186.55 -
186.56 - /**
186.57 - * Constructs a {@code ClientNotFoundException} with the specified detail message
186.58 - * and cause.
186.59 - *
186.60 - * @param message The message.
186.61 - * @param cause The cause (which is saved for later retrieval by the
186.62 - * {@code Throwable.getCause()} method). A null value is permitted, and indicates
186.63 - * that the cause is non-existent or unknown.
186.64 - */
186.65 - public EventClientNotFoundException(String message, Throwable cause) {
186.66 - super(message);
186.67 -
186.68 - initCause(cause);
186.69 - }
186.70 -
186.71 - /**
186.72 - * Constructs a new exception with the specified cause.
186.73 - * @param cause The cause (which is saved for later retrieval by the
186.74 - * {@code Throwable.getCause()} method). A null value is permitted, and indicates
186.75 - * that the cause is non-existent or unknown.
186.76 - */
186.77 - public EventClientNotFoundException(Throwable cause) {
186.78 - super();
186.79 -
186.80 - initCause(cause);
186.81 - }
186.82 -}
187.1 --- a/src/share/classes/javax/management/event/EventConsumer.java Mon Nov 23 10:04:47 2009 +0000
187.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
187.3 @@ -1,98 +0,0 @@
187.4 -/*
187.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
187.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
187.7 - *
187.8 - * This code is free software; you can redistribute it and/or modify it
187.9 - * under the terms of the GNU General Public License version 2 only, as
187.10 - * published by the Free Software Foundation. Sun designates this
187.11 - * particular file as subject to the "Classpath" exception as provided
187.12 - * by Sun in the LICENSE file that accompanied this code.
187.13 - *
187.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
187.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
187.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
187.17 - * version 2 for more details (a copy is included in the LICENSE file that
187.18 - * accompanied this code).
187.19 - *
187.20 - * You should have received a copy of the GNU General Public License version
187.21 - * 2 along with this work; if not, write to the Free Software Foundation,
187.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
187.23 - *
187.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
187.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
187.26 - * have any questions.
187.27 - */
187.28 -
187.29 -package javax.management.event;
187.30 -
187.31 -import java.io.IOException;
187.32 -import javax.management.ListenerNotFoundException;
187.33 -import javax.management.NotificationFilter;
187.34 -import javax.management.NotificationListener;
187.35 -import javax.management.ObjectName;
187.36 -
187.37 -/**
187.38 - * This interface specifies methods to subscribe a listener to receive events
187.39 - * from an MBean or a set of MBeans. The MBeans can already be registered in
187.40 - * an MBean server, or they can be pending registration, or they can be MBeans
187.41 - * that will never be registered, or they can be MBeans that will be registered
187.42 - * then unregistered.
187.43 - * @since JMX 2.0
187.44 - */
187.45 -public interface EventConsumer {
187.46 - /**
187.47 - * <p>Subscribes a listener to receive events from an MBean or a set
187.48 - * of MBeans represented by an {@code ObjectName} pattern.</p>
187.49 - *
187.50 - * <P> An event emitted by an MBean is forwarded to every listener that was
187.51 - * subscribed with the name of that MBean, or with a pattern that matches
187.52 - * that name.</p>
187.53 - *
187.54 - * @param name The name of an MBean or an {@code ObjectName} pattern
187.55 - * representing a set of MBeans to which the listener should listen.
187.56 - * @param listener The listener object that will handle the
187.57 - * notifications emitted by the MBeans.
187.58 - * @param filter The filter object. If {@code filter} is null, no
187.59 - * filtering will be performed before notification handling.
187.60 - * @param handback The context to be sent to the listener when a
187.61 - * notification is emitted.
187.62 - *
187.63 - * @throws IllegalArgumentException If the {@code name} or
187.64 - * {@code listener} is null.
187.65 - * @throws IOException for a remote client, thrown if
187.66 - * an I/O error occurs.
187.67 - * @see #unsubscribe(ObjectName, NotificationListener)
187.68 - */
187.69 - public void subscribe(ObjectName name,
187.70 - NotificationListener listener,
187.71 - NotificationFilter filter,
187.72 - Object handback)
187.73 - throws IOException;
187.74 -
187.75 - /**
187.76 - * <p>Unsubscribes a listener which is listening to an MBean or a set of
187.77 - * MBeans represented by an {@code ObjectName} pattern.</p>
187.78 - *
187.79 - * <p>The listener to be removed must have been added by the {@link
187.80 - * #subscribe subscribe} method with the given {@code name}. If the {@code
187.81 - * name} is a pattern, then the {@code subscribe} must have used the same
187.82 - * pattern. If the same listener has been subscribed more than once to the
187.83 - * {@code name}, perhaps with different filters or handbacks, then all such
187.84 - * listeners are removed.</p>
187.85 - *
187.86 - * @param name The name of the MBean or an {@code ObjectName} pattern
187.87 - * representing a set of MBeans to which the listener was subscribed.
187.88 - * @param listener A listener that was previously subscribed to the
187.89 - * MBean(s).
187.90 - *
187.91 - * @throws ListenerNotFoundException The given {@code listener} was not
187.92 - * subscribed to the given {@code name}.
187.93 - * @throws IOException for a remote client, thrown if
187.94 - * an I/O error occurs.
187.95 - *
187.96 - * @see #subscribe
187.97 - */
187.98 - public void unsubscribe(ObjectName name,
187.99 - NotificationListener listener)
187.100 - throws ListenerNotFoundException, IOException;
187.101 -}
188.1 --- a/src/share/classes/javax/management/event/EventForwarder.java Mon Nov 23 10:04:47 2009 +0000
188.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
188.3 @@ -1,63 +0,0 @@
188.4 -/*
188.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
188.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
188.7 - *
188.8 - * This code is free software; you can redistribute it and/or modify it
188.9 - * under the terms of the GNU General Public License version 2 only, as
188.10 - * published by the Free Software Foundation. Sun designates this
188.11 - * particular file as subject to the "Classpath" exception as provided
188.12 - * by Sun in the LICENSE file that accompanied this code.
188.13 - *
188.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
188.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
188.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
188.17 - * version 2 for more details (a copy is included in the LICENSE file that
188.18 - * accompanied this code).
188.19 - *
188.20 - * You should have received a copy of the GNU General Public License version
188.21 - * 2 along with this work; if not, write to the Free Software Foundation,
188.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
188.23 - *
188.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
188.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
188.26 - * have any questions.
188.27 - */
188.28 -
188.29 -package javax.management.event;
188.30 -
188.31 -import java.io.IOException;
188.32 -import javax.management.Notification;
188.33 -
188.34 -/**
188.35 - * This interface can be used to specify a custom forwarding mechanism for
188.36 - * {@code EventClientDelegateMBean} to forward events to the client.
188.37 - *
188.38 - * @see <a href="package-summary.html#transports">Custom notification
188.39 - * transports</a>
188.40 - */
188.41 -public interface EventForwarder {
188.42 - /**
188.43 - * Forwards a notification.
188.44 - * @param n The notification to be forwarded to a remote listener.
188.45 - * @param listenerId The identifier of the listener to receive the notification.
188.46 - * @throws IOException If it is closed or an I/O error occurs.
188.47 - */
188.48 - public void forward(Notification n, Integer listenerId)
188.49 - throws IOException;
188.50 -
188.51 - /**
188.52 - * Informs the {@code EventForwarder} to shut down.
188.53 - * <p> After this method is called, any call to the method
188.54 - * {@link #forward forward(Notification, Integer)} may get an {@code IOException}.
188.55 - * @throws IOException If an I/O error occurs.
188.56 - */
188.57 - public void close() throws IOException;
188.58 -
188.59 - /**
188.60 - * Sets an event client identifier created by {@link EventClientDelegateMBean}.
188.61 - * <P> This method will be called just after this {@code EventForwarder}
188.62 - * is constructed and before calling the {@code forward} method to forward any
188.63 - * notifications.
188.64 - */
188.65 - public void setClientId(String clientId) throws IOException;
188.66 -}
189.1 --- a/src/share/classes/javax/management/event/EventReceiver.java Mon Nov 23 10:04:47 2009 +0000
189.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
189.3 @@ -1,77 +0,0 @@
189.4 -/*
189.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
189.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
189.7 - *
189.8 - * This code is free software; you can redistribute it and/or modify it
189.9 - * under the terms of the GNU General Public License version 2 only, as
189.10 - * published by the Free Software Foundation. Sun designates this
189.11 - * particular file as subject to the "Classpath" exception as provided
189.12 - * by Sun in the LICENSE file that accompanied this code.
189.13 - *
189.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
189.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
189.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
189.17 - * version 2 for more details (a copy is included in the LICENSE file that
189.18 - * accompanied this code).
189.19 - *
189.20 - * You should have received a copy of the GNU General Public License version
189.21 - * 2 along with this work; if not, write to the Free Software Foundation,
189.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
189.23 - *
189.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
189.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
189.26 - * have any questions.
189.27 - */
189.28 -
189.29 -package javax.management.event;
189.30 -
189.31 -import javax.management.remote.NotificationResult;
189.32 -
189.33 -/**
189.34 - * An object implementing this interface is passed by an {@link EventClient}
189.35 - * to its {@link EventRelay}, to allow the {@code EventRelay} to communicate
189.36 - * received notifications to the {@code EventClient}.
189.37 - *
189.38 - * @see <a href="package-summary.html#transports">Custom notification
189.39 - * transports</a>
189.40 - */
189.41 -public interface EventReceiver {
189.42 -
189.43 - /**
189.44 - * This method is implemented by {@code EventClient} as a callback to
189.45 - * receive notifications from {@code EventRelay}.
189.46 - * <P>The notifications are included in an object specified by the class
189.47 - * {@link NotificationResult}. In
189.48 - * addition to a set of notifications, the class object also contains two values:
189.49 - * {@code earliestSequenceNumber} and {@code nextSequenceNumber}.
189.50 - * These two values determine whether any notifications have been lost.
189.51 - * The {@code nextSequenceNumber} value of the last time is compared
189.52 - * to the received value {@code earliestSequenceNumber}. If the
189.53 - * received {@code earliesSequenceNumber} is greater, than the difference
189.54 - * signifies the number of lost notifications. A sender should
189.55 - * ensure the sequence of notifications sent, meaning that the value
189.56 - * {@code earliestSequenceNumber} of the next return should be always equal to
189.57 - * or greater than the value {@code nextSequenceNumber} of the last return.
189.58 - *
189.59 - * @param nr the received notifications and sequence numbers.
189.60 - */
189.61 - public void receive(NotificationResult nr);
189.62 -
189.63 - /**
189.64 - * Allows the {@link EventRelay} to report when it receives an unexpected
189.65 - * exception, which may be fatal and which may make it stop receiving
189.66 - * notifications.
189.67 - *
189.68 - * @param t The unexpected exception received while {@link EventRelay} was running.
189.69 - */
189.70 - public void failed(Throwable t);
189.71 -
189.72 - /**
189.73 - * Allows the {@link EventRelay} to report when it receives an unexpected
189.74 - * exception that is not fatal. For example, a notification received is not
189.75 - * serializable or its class is not found.
189.76 - *
189.77 - * @param e The unexpected exception received while notifications are being received.
189.78 - */
189.79 - public void nonFatal(Exception e);
189.80 -}
190.1 --- a/src/share/classes/javax/management/event/EventRelay.java Mon Nov 23 10:04:47 2009 +0000
190.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
190.3 @@ -1,79 +0,0 @@
190.4 -/*
190.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
190.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
190.7 - *
190.8 - * This code is free software; you can redistribute it and/or modify it
190.9 - * under the terms of the GNU General Public License version 2 only, as
190.10 - * published by the Free Software Foundation. Sun designates this
190.11 - * particular file as subject to the "Classpath" exception as provided
190.12 - * by Sun in the LICENSE file that accompanied this code.
190.13 - *
190.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
190.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
190.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
190.17 - * version 2 for more details (a copy is included in the LICENSE file that
190.18 - * accompanied this code).
190.19 - *
190.20 - * You should have received a copy of the GNU General Public License version
190.21 - * 2 along with this work; if not, write to the Free Software Foundation,
190.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
190.23 - *
190.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
190.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
190.26 - * have any questions.
190.27 - */
190.28 -
190.29 -package javax.management.event;
190.30 -
190.31 -import java.io.IOException;
190.32 -import java.util.concurrent.Executors; // for javadoc
190.33 -
190.34 -/**
190.35 - * This interface is used to specify a way to receive
190.36 - * notifications from a remote MBean server and then to forward the notifications
190.37 - * to an {@link EventClient}.
190.38 - *
190.39 - * @see <a href="package-summary.html#transports">Custom notification
190.40 - * transports</a>
190.41 - */
190.42 -public interface EventRelay {
190.43 - /**
190.44 - * Returns an identifier that is used by this {@code EventRelay} to identify
190.45 - * the client when communicating with the {@link EventClientDelegateMBean}.
190.46 - * <P> This identifier is obtained by calling
190.47 - * {@link EventClientDelegateMBean#addClient(String, Object[], String[])
190.48 - * EventClientDelegateMBean.addClient}.
190.49 - * <P> It is the {@code EventRelay} that calls {@code EventClientDelegateMBean} to obtain
190.50 - * the client identifier because it is the {@code EventRelay} that decides
190.51 - * how to get notifications from the {@code EventClientDelegateMBean},
190.52 - * by creating the appropriate {@link EventForwarder}.
190.53 - *
190.54 - * @return A client identifier.
190.55 - * @throws IOException If an I/O error occurs when communicating with
190.56 - * the {@code EventClientDelegateMBean}.
190.57 - */
190.58 - public String getClientId() throws IOException;
190.59 -
190.60 - /**
190.61 - * This method is called by {@link EventClient} to register a callback
190.62 - * to receive notifications from an {@link EventClientDelegateMBean} object.
190.63 - * A {@code null} value is allowed, which means that the {@code EventClient} suspends
190.64 - * reception of notifications, so that the {@code EventRelay} can decide to stop receiving
190.65 - * notifications from its {@code EventForwarder}.
190.66 - *
190.67 - * @param eventReceiver An {@link EventClient} callback to receive
190.68 - * events.
190.69 - */
190.70 - public void setEventReceiver(EventReceiver eventReceiver);
190.71 -
190.72 - /**
190.73 - * Stops receiving and forwarding notifications and performs any necessary
190.74 - * cleanup. After calling this method, the {@link EventClient} will never
190.75 - * call any other methods of this object.
190.76 - *
190.77 - * @throws IOException If an I/O exception appears.
190.78 - *
190.79 - * @see EventClient#close
190.80 - */
190.81 - public void stop() throws IOException;
190.82 -}
191.1 --- a/src/share/classes/javax/management/event/EventSubscriber.java Mon Nov 23 10:04:47 2009 +0000
191.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
191.3 @@ -1,376 +0,0 @@
191.4 -/*
191.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
191.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
191.7 - *
191.8 - * This code is free software; you can redistribute it and/or modify it
191.9 - * under the terms of the GNU General Public License version 2 only, as
191.10 - * published by the Free Software Foundation. Sun designates this
191.11 - * particular file as subject to the "Classpath" exception as provided
191.12 - * by Sun in the LICENSE file that accompanied this code.
191.13 - *
191.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
191.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
191.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
191.17 - * version 2 for more details (a copy is included in the LICENSE file that
191.18 - * accompanied this code).
191.19 - *
191.20 - * You should have received a copy of the GNU General Public License version
191.21 - * 2 along with this work; if not, write to the Free Software Foundation,
191.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
191.23 - *
191.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
191.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
191.26 - * have any questions.
191.27 - */
191.28 -
191.29 -package javax.management.event;
191.30 -
191.31 -import com.sun.jmx.remote.util.ClassLogger;
191.32 -import java.io.IOException;
191.33 -import java.lang.ref.WeakReference;
191.34 -import java.lang.reflect.Method;
191.35 -import java.security.AccessController;
191.36 -import java.security.PrivilegedActionException;
191.37 -import java.security.PrivilegedExceptionAction;
191.38 -import java.util.ArrayList;
191.39 -import java.util.Collections;
191.40 -import java.util.HashMap;
191.41 -import java.util.List;
191.42 -import java.util.Map;
191.43 -import java.util.Set;
191.44 -import java.util.WeakHashMap;
191.45 -import javax.management.InstanceNotFoundException;
191.46 -import javax.management.ListenerNotFoundException;
191.47 -import javax.management.MBeanServer;
191.48 -import javax.management.MBeanServerConnection;
191.49 -import javax.management.MBeanServerDelegate;
191.50 -import javax.management.MBeanServerNotification;
191.51 -import javax.management.Notification;
191.52 -import javax.management.NotificationBroadcaster;
191.53 -import javax.management.NotificationFilter;
191.54 -import javax.management.NotificationListener;
191.55 -import javax.management.ObjectName;
191.56 -import javax.management.Query;
191.57 -import javax.management.QueryEval;
191.58 -import javax.management.QueryExp;
191.59 -
191.60 -/**
191.61 - * <p>An object that can be used to subscribe for notifications from all MBeans
191.62 - * in an MBeanServer that match a pattern. For example, to listen for
191.63 - * notifications from all MBeans in the MBeanServer {@code mbs} that match
191.64 - * {@code com.example:type=Controller,name=*} you could write:</p>
191.65 - *
191.66 - * <pre>
191.67 - * EventSubscriber subscriber = EventSubscriber.getEventSubscriber(mbs);
191.68 - * ObjectName pattern = new ObjectName("com.example:type=Controller,name=*");
191.69 - * NotificationListener myListener = ...;
191.70 - * NotificationFilter myFilter = null; // or whatever
191.71 - * Object handback = null; // or whatever
191.72 - * subscriber.subscribe(pattern, myListener, myFilter, myHandback);
191.73 - * </pre>
191.74 - */
191.75 -public class EventSubscriber implements EventConsumer {
191.76 - /**
191.77 - * Returns an {@code EventSubscriber} object to subscribe for notifications
191.78 - * from the given {@code MBeanServer}. Calling this method more
191.79 - * than once with the same parameter may or may not return the same object.
191.80 - *
191.81 - * @param mbs the {@code MBeanServer} containing MBeans to be subscribed to.
191.82 - * @return An {@code EventSubscriber} object.
191.83 - *
191.84 - * @throws NullPointerException if mbs is null.
191.85 - */
191.86 - public static EventSubscriber getEventSubscriber(MBeanServer mbs) {
191.87 - if (mbs == null)
191.88 - throw new NullPointerException("Null MBeanServer");
191.89 -
191.90 - EventSubscriber eventSubscriber = null;
191.91 - synchronized (subscriberMap) {
191.92 - final WeakReference<EventSubscriber> wrf = subscriberMap.get(mbs);
191.93 - eventSubscriber = (wrf == null) ? null : wrf.get();
191.94 -
191.95 - if (eventSubscriber == null) {
191.96 - eventSubscriber = new EventSubscriber(mbs);
191.97 -
191.98 - subscriberMap.put(mbs,
191.99 - new WeakReference<EventSubscriber>(eventSubscriber));
191.100 - }
191.101 - }
191.102 -
191.103 - return eventSubscriber;
191.104 - }
191.105 -
191.106 - private EventSubscriber(final MBeanServer mbs) {
191.107 - logger.trace("EventSubscriber", "create a new one");
191.108 - this.mbeanServer = mbs;
191.109 -
191.110 - Exception x = null;
191.111 - try {
191.112 - AccessController.doPrivileged(
191.113 - new PrivilegedExceptionAction<Void>() {
191.114 - public Void run() throws Exception {
191.115 - mbs.addNotificationListener(
191.116 - MBeanServerDelegate.DELEGATE_NAME,
191.117 - myMBeanServerListener, null, null);
191.118 - return null;
191.119 - }
191.120 - });
191.121 - } catch (PrivilegedActionException ex) {
191.122 - x = ex.getException();
191.123 - }
191.124 -
191.125 - // handle possible exceptions.
191.126 - //
191.127 - // Fail unless x is null or x is instance of InstanceNotFoundException
191.128 - // The logic here is that if the MBeanServerDelegate is not present,
191.129 - // we will assume that the connection will not emit any
191.130 - // MBeanServerNotifications.
191.131 - //
191.132 - if (x != null && !(x instanceof InstanceNotFoundException)) {
191.133 - if (x instanceof RuntimeException)
191.134 - throw (RuntimeException) x;
191.135 - throw new RuntimeException(
191.136 - "Can't add listener to MBean server delegate: " + x, x);
191.137 - }
191.138 - }
191.139 -
191.140 - public void subscribe(ObjectName name,
191.141 - NotificationListener listener,
191.142 - NotificationFilter filter,
191.143 - Object handback)
191.144 - throws IOException {
191.145 -
191.146 - if (logger.traceOn())
191.147 - logger.trace("subscribe", "" + name);
191.148 -
191.149 - if (name == null)
191.150 - throw new IllegalArgumentException("Null MBean name");
191.151 -
191.152 - if (listener == null)
191.153 - throw new IllegalArgumentException("Null listener");
191.154 -
191.155 - final MyListenerInfo li = new MyListenerInfo(listener, filter, handback);
191.156 - List<MyListenerInfo> list;
191.157 -
191.158 - Map<ObjectName, List<MyListenerInfo>> map;
191.159 - Set<ObjectName> names;
191.160 - if (name.isPattern()) {
191.161 - map = patternSubscriptionMap;
191.162 - names = mbeanServer.queryNames(name, notificationBroadcasterExp);
191.163 - } else {
191.164 - map = exactSubscriptionMap;
191.165 - names = Collections.singleton(name);
191.166 - }
191.167 -
191.168 - synchronized (map) {
191.169 - list = map.get(name);
191.170 - if (list == null) {
191.171 - list = new ArrayList<MyListenerInfo>();
191.172 - map.put(name, list);
191.173 - }
191.174 - list.add(li);
191.175 - }
191.176 -
191.177 - for (ObjectName mbeanName : names) {
191.178 - try {
191.179 - mbeanServer.addNotificationListener(mbeanName,
191.180 - listener,
191.181 - filter,
191.182 - handback);
191.183 - } catch (Exception e) {
191.184 - logger.fine("subscribe", "addNotificationListener", e);
191.185 - }
191.186 - }
191.187 - }
191.188 -
191.189 - public void unsubscribe(ObjectName name,
191.190 - NotificationListener listener)
191.191 - throws ListenerNotFoundException, IOException {
191.192 - if (logger.traceOn())
191.193 - logger.trace("unsubscribe", "" + name);
191.194 -
191.195 - if (name == null)
191.196 - throw new IllegalArgumentException("Null MBean name");
191.197 -
191.198 - if (listener == null)
191.199 - throw new ListenerNotFoundException();
191.200 -
191.201 - Map<ObjectName, List<MyListenerInfo>> map;
191.202 - Set<ObjectName> names;
191.203 -
191.204 - if (name.isPattern()) {
191.205 - map = patternSubscriptionMap;
191.206 - names = mbeanServer.queryNames(name, notificationBroadcasterExp);
191.207 - } else {
191.208 - map = exactSubscriptionMap;
191.209 - names = Collections.singleton(name);
191.210 - }
191.211 -
191.212 - List<MyListenerInfo> toRemove = new ArrayList<MyListenerInfo>();
191.213 - synchronized (map) {
191.214 - List<MyListenerInfo> list = map.get(name);
191.215 - if (list == null) {
191.216 - throw new ListenerNotFoundException();
191.217 - }
191.218 -
191.219 - for (MyListenerInfo info : list) {
191.220 - if (info.listener == listener) {
191.221 - toRemove.add(info);
191.222 - }
191.223 - }
191.224 -
191.225 - if (toRemove.isEmpty()) {
191.226 - throw new ListenerNotFoundException();
191.227 - }
191.228 -
191.229 - for (MyListenerInfo info : toRemove) {
191.230 - list.remove(info);
191.231 - }
191.232 -
191.233 - if (list.isEmpty())
191.234 - map.remove(name);
191.235 - }
191.236 -
191.237 - for (ObjectName mbeanName : names) {
191.238 - for (MyListenerInfo i : toRemove) {
191.239 - try {
191.240 - mbeanServer.removeNotificationListener(mbeanName,
191.241 - i.listener, i.filter, i.handback);
191.242 - } catch (Exception e) {
191.243 - logger.fine("unsubscribe", "removeNotificationListener", e);
191.244 - }
191.245 - }
191.246 - }
191.247 - }
191.248 -
191.249 - // ---------------------------------
191.250 - // private stuff
191.251 - // ---------------------------------
191.252 - // used to receive MBeanServerNotification
191.253 - private NotificationListener myMBeanServerListener =
191.254 - new NotificationListener() {
191.255 - public void handleNotification(Notification n, Object hb) {
191.256 - if (!(n instanceof MBeanServerNotification) ||
191.257 - !MBeanServerNotification.
191.258 - REGISTRATION_NOTIFICATION.equals(n.getType())) {
191.259 - return;
191.260 - }
191.261 -
191.262 - final ObjectName name =
191.263 - ((MBeanServerNotification)n).getMBeanName();
191.264 - try {
191.265 - if (!mbeanServer.isInstanceOf(name,
191.266 - NotificationBroadcaster.class.getName())) {
191.267 - return;
191.268 - }
191.269 - } catch (Exception e) {
191.270 - // The only documented exception is InstanceNotFoundException,
191.271 - // which could conceivably happen if the MBean is unregistered
191.272 - // immediately after being registered.
191.273 - logger.fine("myMBeanServerListener.handleNotification",
191.274 - "isInstanceOf", e);
191.275 - return;
191.276 - }
191.277 -
191.278 - final List<MyListenerInfo> listeners = new ArrayList<MyListenerInfo>();
191.279 -
191.280 - // If there are subscribers for the exact name that has just arrived
191.281 - // then add their listeners to the list.
191.282 - synchronized (exactSubscriptionMap) {
191.283 - List<MyListenerInfo> exactListeners = exactSubscriptionMap.get(name);
191.284 - if (exactListeners != null)
191.285 - listeners.addAll(exactListeners);
191.286 - }
191.287 -
191.288 - // For every subscription pattern that matches the new name,
191.289 - // add all the listeners for that pattern to "listeners".
191.290 - synchronized (patternSubscriptionMap) {
191.291 - for (ObjectName on : patternSubscriptionMap.keySet()) {
191.292 - if (on.apply(name)) {
191.293 - listeners.addAll(patternSubscriptionMap.get(on));
191.294 - }
191.295 - }
191.296 - }
191.297 -
191.298 - // Add all the listeners just found to the new MBean.
191.299 - for (MyListenerInfo li : listeners) {
191.300 - try {
191.301 - mbeanServer.addNotificationListener(
191.302 - name,
191.303 - li.listener,
191.304 - li.filter,
191.305 - li.handback);
191.306 - } catch (Exception e) {
191.307 - logger.fine("myMBeanServerListener.handleNotification",
191.308 - "addNotificationListener", e);
191.309 - }
191.310 - }
191.311 - }
191.312 - };
191.313 -
191.314 - private static class MyListenerInfo {
191.315 - public final NotificationListener listener;
191.316 - public final NotificationFilter filter;
191.317 - public final Object handback;
191.318 -
191.319 - public MyListenerInfo(NotificationListener listener,
191.320 - NotificationFilter filter,
191.321 - Object handback) {
191.322 -
191.323 - if (listener == null)
191.324 - throw new IllegalArgumentException("Null listener");
191.325 -
191.326 - this.listener = listener;
191.327 - this.filter = filter;
191.328 - this.handback = handback;
191.329 - }
191.330 - }
191.331 -
191.332 - // ---------------------------------
191.333 - // private methods
191.334 - // ---------------------------------
191.335 - // ---------------------------------
191.336 - // private variables
191.337 - // ---------------------------------
191.338 - private final MBeanServer mbeanServer;
191.339 -
191.340 - private final Map<ObjectName, List<MyListenerInfo>> exactSubscriptionMap =
191.341 - new HashMap<ObjectName, List<MyListenerInfo>>();
191.342 - private final Map<ObjectName, List<MyListenerInfo>> patternSubscriptionMap =
191.343 - new HashMap<ObjectName, List<MyListenerInfo>>();
191.344 -
191.345 -
191.346 -
191.347 - // trace issues
191.348 - private static final ClassLogger logger =
191.349 - new ClassLogger("javax.management.event", "EventSubscriber");
191.350 -
191.351 - // Compatibility code, so we can run on Tiger:
191.352 - private static final QueryExp notificationBroadcasterExp;
191.353 - static {
191.354 - QueryExp broadcasterExp;
191.355 - try {
191.356 - final Method m = Query.class.getMethod("isInstanceOf", String.class);
191.357 - broadcasterExp = (QueryExp)m.invoke(Query.class,
191.358 - new Object[] {NotificationBroadcaster.class.getName()});
191.359 - } catch (Exception e) {
191.360 - broadcasterExp = new BroadcasterQueryExp();
191.361 - }
191.362 - notificationBroadcasterExp = broadcasterExp;
191.363 - }
191.364 - private static class BroadcasterQueryExp extends QueryEval implements QueryExp {
191.365 - private static final long serialVersionUID = 1234L;
191.366 - public boolean apply(ObjectName name) {
191.367 - try {
191.368 - return getMBeanServer().isInstanceOf(
191.369 - name, NotificationBroadcaster.class.getName());
191.370 - } catch (Exception e) {
191.371 - return false;
191.372 - }
191.373 - }
191.374 - }
191.375 -
191.376 - private static final
191.377 - Map<MBeanServerConnection, WeakReference<EventSubscriber>> subscriberMap =
191.378 - new WeakHashMap<MBeanServerConnection, WeakReference<EventSubscriber>>();
191.379 -}
192.1 --- a/src/share/classes/javax/management/event/FetchingEventForwarder.java Mon Nov 23 10:04:47 2009 +0000
192.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
192.3 @@ -1,151 +0,0 @@
192.4 -/*
192.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
192.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
192.7 - *
192.8 - * This code is free software; you can redistribute it and/or modify it
192.9 - * under the terms of the GNU General Public License version 2 only, as
192.10 - * published by the Free Software Foundation. Sun designates this
192.11 - * particular file as subject to the "Classpath" exception as provided
192.12 - * by Sun in the LICENSE file that accompanied this code.
192.13 - *
192.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
192.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
192.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
192.17 - * version 2 for more details (a copy is included in the LICENSE file that
192.18 - * accompanied this code).
192.19 - *
192.20 - * You should have received a copy of the GNU General Public License version
192.21 - * 2 along with this work; if not, write to the Free Software Foundation,
192.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
192.23 - *
192.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
192.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
192.26 - * have any questions.
192.27 - */
192.28 -
192.29 -package javax.management.event;
192.30 -
192.31 -import com.sun.jmx.event.EventBuffer;
192.32 -import com.sun.jmx.remote.util.ClassLogger;
192.33 -import java.io.IOException;
192.34 -import java.util.List;
192.35 -import javax.management.Notification;
192.36 -import javax.management.remote.NotificationResult;
192.37 -import javax.management.remote.TargetedNotification;
192.38 -
192.39 -/**
192.40 - * This class is used by {@link FetchingEventRelay}. When
192.41 - * {@link FetchingEventRelay} calls {@link
192.42 - * EventClientDelegateMBean#addClient(String, Object[], String[])} to get a new
192.43 - * client identifier, it uses
192.44 - * this class name as the first argument to ask {@code EventClientDelegateMBean}
192.45 - * to create an object of this class.
192.46 - * Then {@code EventClientDelegateMBean} forwards client notifications
192.47 - * to this object.
192.48 - * When {@link FetchingEventRelay} calls
192.49 - * {@link EventClientDelegateMBean#fetchNotifications(String, long, int, long)}
192.50 - * to fetch notifications, the {@code EventClientDelegateMBean} will forward
192.51 - * the call to this object.
192.52 - */
192.53 -public class FetchingEventForwarder implements EventForwarder {
192.54 -
192.55 - /**
192.56 - * Construct a new {@code FetchingEventForwarder} with the given
192.57 - * buffer size.
192.58 - * @param bufferSize the size of the buffer that will store notifications
192.59 - * until they have been fetched and acknowledged by the client.
192.60 - */
192.61 - public FetchingEventForwarder(int bufferSize) {
192.62 - if (logger.traceOn()) {
192.63 - logger.trace("Constructor", "buffer size is "+bufferSize);
192.64 - }
192.65 -
192.66 - buffer = new EventBuffer(bufferSize);
192.67 - this.bufferSize = bufferSize;
192.68 - }
192.69 -
192.70 - /**
192.71 - * Called by an {@link EventClientDelegateMBean} to forward a user call
192.72 - * {@link EventClientDelegateMBean#fetchNotifications(String, long, int, long)}.
192.73 - * A call of this method is considered to acknowledge reception of all
192.74 - * notifications whose sequence numbers are less the
192.75 - * {@code startSequenceNumber}, so all these notifications can be deleted
192.76 - * from this object.
192.77 - *
192.78 - * @param startSequenceNumber The first sequence number to
192.79 - * consider.
192.80 - * @param timeout The maximum waiting time in milliseconds.
192.81 - * If no notifications have arrived after this period of time, the call
192.82 - * will return with an empty list of notifications.
192.83 - * @param maxNotifs The maximum number of notifications to return.
192.84 - */
192.85 - public NotificationResult fetchNotifications(long startSequenceNumber,
192.86 - int maxNotifs, long timeout) {
192.87 - if (logger.traceOn()) {
192.88 - logger.trace("fetchNotifications",
192.89 - startSequenceNumber+" "+
192.90 - maxNotifs+" "+
192.91 - timeout);
192.92 - }
192.93 -
192.94 - return buffer.fetchNotifications(startSequenceNumber,
192.95 - timeout,
192.96 - maxNotifs);
192.97 - }
192.98 -
192.99 - /**
192.100 - * {@inheritDoc}
192.101 - * In this implementation, the notification is stored in the local buffer
192.102 - * waiting for {@link #fetchNotifications fetchNotifications} to pick
192.103 - * it up.
192.104 - */
192.105 - public void forward(Notification n, Integer listenerId) throws IOException {
192.106 - if (logger.traceOn()) {
192.107 - logger.trace("forward", n+" "+listenerId);
192.108 - }
192.109 -
192.110 - buffer.add(new TargetedNotification(n, listenerId));
192.111 - }
192.112 -
192.113 - public void close() throws IOException {
192.114 - if (logger.traceOn()) {
192.115 - logger.trace("close", "");
192.116 - }
192.117 -
192.118 - buffer.close();
192.119 - }
192.120 -
192.121 - public void setClientId(String clientId) throws IOException {
192.122 - if (logger.traceOn()) {
192.123 - logger.trace("setClientId", clientId);
192.124 - }
192.125 - this.clientId = clientId;
192.126 - }
192.127 -
192.128 - /**
192.129 - * Sets a user specific list to save notifications in server side
192.130 - * before forwarding to an FetchingEventRelay in client side.
192.131 - * <P> This method should be called before any notification is
192.132 - * forwarded to this forwader.
192.133 - *
192.134 - * @param list a user specific list to save notifications
192.135 - */
192.136 - protected void setList(List<TargetedNotification> list) {
192.137 - if (logger.traceOn()) {
192.138 - logger.trace("setList", "");
192.139 - }
192.140 -
192.141 - if (clientId == null) {
192.142 - buffer = new EventBuffer(bufferSize, list);
192.143 - } else {
192.144 - throw new IllegalStateException();
192.145 - }
192.146 - }
192.147 -
192.148 - private EventBuffer buffer;
192.149 - private int bufferSize;
192.150 - private String clientId;
192.151 -
192.152 - private static final ClassLogger logger =
192.153 - new ClassLogger("javax.management.event", "FetchingEventForwarder");
192.154 -}
193.1 --- a/src/share/classes/javax/management/event/FetchingEventRelay.java Mon Nov 23 10:04:47 2009 +0000
193.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
193.3 @@ -1,391 +0,0 @@
193.4 -/*
193.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
193.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
193.7 - *
193.8 - * This code is free software; you can redistribute it and/or modify it
193.9 - * under the terms of the GNU General Public License version 2 only, as
193.10 - * published by the Free Software Foundation. Sun designates this
193.11 - * particular file as subject to the "Classpath" exception as provided
193.12 - * by Sun in the LICENSE file that accompanied this code.
193.13 - *
193.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
193.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
193.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
193.17 - * version 2 for more details (a copy is included in the LICENSE file that
193.18 - * accompanied this code).
193.19 - *
193.20 - * You should have received a copy of the GNU General Public License version
193.21 - * 2 along with this work; if not, write to the Free Software Foundation,
193.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
193.23 - *
193.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
193.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
193.26 - * have any questions.
193.27 - */
193.28 -
193.29 -package javax.management.event;
193.30 -
193.31 -import com.sun.jmx.event.DaemonThreadFactory;
193.32 -import com.sun.jmx.event.RepeatedSingletonJob;
193.33 -import com.sun.jmx.remote.util.ClassLogger;
193.34 -import java.io.IOException;
193.35 -import java.io.NotSerializableException;
193.36 -import java.util.concurrent.Executor;
193.37 -import java.util.concurrent.ExecutorService;
193.38 -import java.util.concurrent.ScheduledThreadPoolExecutor;
193.39 -import java.util.concurrent.ThreadFactory;
193.40 -import java.util.concurrent.TimeUnit;
193.41 -import javax.management.MBeanException;
193.42 -import javax.management.remote.NotificationResult;
193.43 -
193.44 -/**
193.45 - * <p>This class is an implementation of the {@link EventRelay} interface. It calls
193.46 - * {@link EventClientDelegateMBean#fetchNotifications
193.47 - * fetchNotifications(String, long, int, long)} to get
193.48 - * notifications and then forwards them to an {@link EventReceiver} object.</p>
193.49 - *
193.50 - * <p>A {@code fetchExecutor} parameter can be specified when creating a
193.51 - * {@code FetchingEventRelay}. That is then the {@code Executor} that will
193.52 - * be used to perform the {@code fetchNotifications} operation. Only one
193.53 - * job at a time will be submitted to this {@code Executor}. The behavior
193.54 - * is unspecified if {@link Executor#execute} throws an exception, including
193.55 - * {@link java.util.concurrent.RejectedExecutionException
193.56 - * RejectedExecutionException}.
193.57 - *
193.58 - * @since JMX 2.0
193.59 - */
193.60 -public class FetchingEventRelay implements EventRelay {
193.61 - /**
193.62 - * The default buffer size: {@value #DEFAULT_BUFFER_SIZE}.
193.63 - */
193.64 - public final static int DEFAULT_BUFFER_SIZE = 1000;
193.65 -
193.66 - /**
193.67 - * The default waiting timeout: {@value #DEFAULT_WAITING_TIMEOUT}
193.68 - * in millseconds when fetching notifications from
193.69 - * an {@code EventClientDelegateMBean}.
193.70 - */
193.71 - public final static long DEFAULT_WAITING_TIMEOUT = 60000;
193.72 -
193.73 - /**
193.74 - * The default maximum notifications to fetch every time:
193.75 - * {@value #DEFAULT_MAX_NOTIFICATIONS}.
193.76 - */
193.77 - public final static int DEFAULT_MAX_NOTIFICATIONS = DEFAULT_BUFFER_SIZE;
193.78 -
193.79 - /**
193.80 - * Constructs a default {@code FetchingEventRelay} object by using the default
193.81 - * configuration: {@code DEFAULT_BUFFER_SIZE}, {@code DEFAULT_WAITING_TIMEOUT}
193.82 - * {@code DEFAULT_MAX_NOTIFICATIONS}. A single thread is created
193.83 - * to do fetching.
193.84 - *
193.85 - * @param delegate The {@code EventClientDelegateMBean} to work with.
193.86 - * @throws IOException If failed to work with the {@code delegate}.
193.87 - * @throws MBeanException if unable to add a client to the remote
193.88 - * {@code EventClientDelegateMBean} (see {@link
193.89 - * EventClientDelegateMBean#addClient(String, Object[], String[])
193.90 - * EventClientDelegateMBean.addClient}).
193.91 - * @throws IllegalArgumentException If {@code delegate} is {@code null}.
193.92 - */
193.93 - public FetchingEventRelay(EventClientDelegateMBean delegate)
193.94 - throws IOException, MBeanException {
193.95 - this(delegate, null);
193.96 - }
193.97 -
193.98 - /**
193.99 - * Constructs a {@code FetchingEventRelay} object by using the default
193.100 - * configuration: {@code DEFAULT_BUFFER_SIZE}, {@code DEFAULT_WAITING_TIMEOUT}
193.101 - * {@code DEFAULT_MAX_NOTIFICATIONS}, with a user-specific executor to do
193.102 - * the fetching.
193.103 - *
193.104 - * @param delegate The {@code EventClientDelegateMBean} to work with.
193.105 - * @param fetchExecutor Used to do the fetching. A new thread is created if
193.106 - * {@code null}.
193.107 - * @throws IOException If failed to work with the {@code delegate}.
193.108 - * @throws MBeanException if unable to add a client to the remote
193.109 - * {@code EventClientDelegateMBean} (see {@link
193.110 - * EventClientDelegateMBean#addClient(String, Object[], String[])
193.111 - * EventClientDelegateMBean.addClient}).
193.112 - * @throws IllegalArgumentException If {@code delegate} is {@code null}.
193.113 - */
193.114 - public FetchingEventRelay(EventClientDelegateMBean delegate,
193.115 - Executor fetchExecutor) throws IOException, MBeanException {
193.116 - this(delegate,
193.117 - DEFAULT_BUFFER_SIZE,
193.118 - DEFAULT_WAITING_TIMEOUT,
193.119 - DEFAULT_MAX_NOTIFICATIONS,
193.120 - fetchExecutor);
193.121 - }
193.122 -
193.123 - /**
193.124 - * Constructs a {@code FetchingEventRelay} object with user-specific
193.125 - * configuration and executor to fetch notifications via the
193.126 - * {@link EventClientDelegateMBean}.
193.127 - *
193.128 - * @param delegate The {@code EventClientDelegateMBean} to work with.
193.129 - * @param bufferSize The buffer size for saving notifications in
193.130 - * {@link EventClientDelegateMBean} before they are fetched.
193.131 - * @param timeout The waiting time in millseconds when fetching
193.132 - * notifications from an {@code EventClientDelegateMBean}.
193.133 - * @param maxNotifs The maximum notifications to fetch every time.
193.134 - * @param fetchExecutor Used to do the fetching. A new thread is created if
193.135 - * {@code null}.
193.136 - * @throws IOException if failed to communicate with the {@code delegate}.
193.137 - * @throws MBeanException if unable to add a client to the remote
193.138 - * {@code EventClientDelegateMBean} (see {@link
193.139 - * EventClientDelegateMBean#addClient(String, Object[], String[])
193.140 - * EventClientDelegateMBean.addClient}).
193.141 - * @throws IllegalArgumentException If {@code delegate} is {@code null}.
193.142 - */
193.143 - public FetchingEventRelay(EventClientDelegateMBean delegate,
193.144 - int bufferSize,
193.145 - long timeout,
193.146 - int maxNotifs,
193.147 - Executor fetchExecutor) throws IOException, MBeanException {
193.148 - this(delegate,
193.149 - bufferSize,
193.150 - timeout,
193.151 - maxNotifs,
193.152 - fetchExecutor,
193.153 - FetchingEventForwarder.class.getName(),
193.154 - new Object[] {bufferSize},
193.155 - new String[] {int.class.getName()});
193.156 - }
193.157 -
193.158 - /**
193.159 - * Constructs a {@code FetchingEventRelay} object with user-specific
193.160 - * configuration and executor to fetch notifications via the
193.161 - * {@link EventClientDelegateMBean}.
193.162 - *
193.163 - * @param delegate The {@code EventClientDelegateMBean} to work with.
193.164 - * @param bufferSize The buffer size for saving notifications in
193.165 - * {@link EventClientDelegateMBean} before they are fetched.
193.166 - * @param timeout The waiting time in millseconds when fetching
193.167 - * notifications from an {@code EventClientDelegateMBean}.
193.168 - * @param maxNotifs The maximum notifications to fetch every time.
193.169 - * @param fetchExecutor Used to do the fetching.
193.170 - * @param forwarderName the class name of a user specific EventForwarder
193.171 - * to create in server to forward notifications to this object. The class
193.172 - * should be a subclass of the class {@link FetchingEventForwarder}.
193.173 - * @param params the parameters passed to create {@code forwarderName}
193.174 - * @param sig the signature of the {@code params}
193.175 - * @throws IOException if failed to communicate with the {@code delegate}.
193.176 - * @throws MBeanException if unable to add a client to the remote
193.177 - * {@code EventClientDelegateMBean} (see {@link
193.178 - * EventClientDelegateMBean#addClient(String, Object[], String[])
193.179 - * EventClientDelegateMBean.addClient}).
193.180 - * @throws IllegalArgumentException if {@code bufferSize} or
193.181 - * {@code maxNotifs} is less than {@code 1}
193.182 - * @throws NullPointerException if {@code delegate} is {@code null}.
193.183 - */
193.184 - public FetchingEventRelay(EventClientDelegateMBean delegate,
193.185 - int bufferSize,
193.186 - long timeout,
193.187 - int maxNotifs,
193.188 - Executor fetchExecutor,
193.189 - String forwarderName,
193.190 - Object[] params,
193.191 - String[] sig) throws IOException, MBeanException {
193.192 -
193.193 - if (logger.traceOn()) {
193.194 - logger.trace("FetchingEventRelay", "delegateMBean "+
193.195 - bufferSize+" "+
193.196 - timeout+" "+
193.197 - maxNotifs+" "+
193.198 - fetchExecutor+" "+
193.199 - forwarderName+" ");
193.200 - }
193.201 -
193.202 - if (delegate == null) {
193.203 - throw new NullPointerException("Null EventClientDelegateMBean!");
193.204 - }
193.205 -
193.206 -
193.207 - if (bufferSize<=1) {
193.208 - throw new IllegalArgumentException(
193.209 - "The bufferSize cannot be less than 1, no meaning.");
193.210 - }
193.211 -
193.212 - if (maxNotifs<=1) {
193.213 - throw new IllegalArgumentException(
193.214 - "The maxNotifs cannot be less than 1, no meaning.");
193.215 - }
193.216 -
193.217 - clientId = delegate.addClient(
193.218 - forwarderName,
193.219 - params,
193.220 - sig);
193.221 -
193.222 - this.delegate = delegate;
193.223 - this.timeout = timeout;
193.224 - this.maxNotifs = maxNotifs;
193.225 -
193.226 - if (fetchExecutor == null) {
193.227 - ScheduledThreadPoolExecutor executor =
193.228 - new ScheduledThreadPoolExecutor(1, daemonThreadFactory);
193.229 - executor.setKeepAliveTime(1, TimeUnit.SECONDS);
193.230 - executor.allowCoreThreadTimeOut(true);
193.231 - fetchExecutor = executor;
193.232 - this.defaultExecutor = executor;
193.233 - } else
193.234 - this.defaultExecutor = null;
193.235 - this.fetchExecutor = fetchExecutor;
193.236 -
193.237 - startSequenceNumber = 0;
193.238 - fetchingJob = new MyJob();
193.239 - }
193.240 -
193.241 - public synchronized void setEventReceiver(EventReceiver eventReceiver) {
193.242 - if (logger.traceOn()) {
193.243 - logger.trace("setEventReceiver", ""+eventReceiver);
193.244 - }
193.245 -
193.246 - EventReceiver old = this.eventReceiver;
193.247 - this.eventReceiver = eventReceiver;
193.248 - if (old == null && eventReceiver != null)
193.249 - fetchingJob.resume();
193.250 - }
193.251 -
193.252 - public String getClientId() {
193.253 - return clientId;
193.254 - }
193.255 -
193.256 - public synchronized void stop() {
193.257 - if (logger.traceOn()) {
193.258 - logger.trace("stop", "");
193.259 - }
193.260 - if (stopped) {
193.261 - return;
193.262 - }
193.263 -
193.264 - stopped = true;
193.265 - clientId = null;
193.266 - if (defaultExecutor != null)
193.267 - defaultExecutor.shutdown();
193.268 - }
193.269 -
193.270 - private class MyJob extends RepeatedSingletonJob {
193.271 - public MyJob() {
193.272 - super(fetchExecutor);
193.273 - }
193.274 -
193.275 - public boolean isSuspended() {
193.276 - boolean b;
193.277 - synchronized(FetchingEventRelay.this) {
193.278 - b = stopped ||
193.279 - (eventReceiver == null) ||
193.280 - (clientId == null);
193.281 - }
193.282 -
193.283 - if (logger.traceOn()) {
193.284 - logger.trace("-MyJob-isSuspended", ""+b);
193.285 - }
193.286 - return b;
193.287 - }
193.288 -
193.289 - public void task() {
193.290 - logger.trace("MyJob-task", "");
193.291 - long fetchTimeout = timeout;
193.292 - NotificationResult nr = null;
193.293 - Throwable failedExcep = null;
193.294 - try {
193.295 - nr = delegate.fetchNotifications(
193.296 - clientId,
193.297 - startSequenceNumber,
193.298 - maxNotifs,
193.299 - fetchTimeout);
193.300 - } catch (Exception e) {
193.301 - if (isSerialOrClassNotFound(e)) {
193.302 - try {
193.303 - nr = fetchOne();
193.304 - } catch (Exception ee) {
193.305 - failedExcep = e;
193.306 - }
193.307 - } else {
193.308 - failedExcep = e;
193.309 - }
193.310 - }
193.311 -
193.312 - if (failedExcep != null &&
193.313 - !isSuspended()) {
193.314 - logger.fine("MyJob-task",
193.315 - "Failed to fetch notification, stopping...", failedExcep);
193.316 - try {
193.317 - eventReceiver.failed(failedExcep);
193.318 - } catch (Exception e) {
193.319 - logger.trace(
193.320 - "MyJob-task", "exception from eventReceiver.failed", e);
193.321 - }
193.322 -
193.323 - stop();
193.324 - } else if (nr != null) {
193.325 - try {
193.326 - eventReceiver.receive(nr);
193.327 - } catch (RuntimeException e) {
193.328 - logger.trace(
193.329 - "MyJob-task",
193.330 - "exception delivering notifs to EventClient", e);
193.331 - } finally {
193.332 - startSequenceNumber = nr.getNextSequenceNumber();
193.333 - }
193.334 - }
193.335 - }
193.336 - }
193.337 -
193.338 - private NotificationResult fetchOne() throws Exception {
193.339 - logger.trace("fetchOne", "");
193.340 -
193.341 - while (true) {
193.342 - try {
193.343 - // 1 notif to skip possible missing class
193.344 - return delegate.fetchNotifications(
193.345 - clientId,
193.346 - startSequenceNumber,
193.347 - 1,
193.348 - timeout);
193.349 - } catch (Exception e) {
193.350 - if (isSerialOrClassNotFound(e)) { // skip and continue
193.351 - if (logger.traceOn()) {
193.352 - logger.trace("fetchOne", "Ignore", e);
193.353 - }
193.354 - eventReceiver.nonFatal(e);
193.355 - startSequenceNumber++;
193.356 - } else {
193.357 - throw e;
193.358 - }
193.359 - }
193.360 - }
193.361 - }
193.362 -
193.363 - static boolean isSerialOrClassNotFound(Exception e) {
193.364 - Throwable cause = e.getCause();
193.365 -
193.366 - while (cause != null &&
193.367 - !(cause instanceof ClassNotFoundException) &&
193.368 - !(cause instanceof NotSerializableException)) {
193.369 - cause = cause.getCause();
193.370 - }
193.371 -
193.372 - return (cause instanceof ClassNotFoundException ||
193.373 - cause instanceof NotSerializableException);
193.374 - }
193.375 -
193.376 - private long startSequenceNumber = 0;
193.377 - private EventReceiver eventReceiver = null;
193.378 - private final EventClientDelegateMBean delegate;
193.379 - private String clientId;
193.380 - private boolean stopped = false;
193.381 -
193.382 - private final Executor fetchExecutor;
193.383 - private final ExecutorService defaultExecutor;
193.384 - private final MyJob fetchingJob;
193.385 -
193.386 - private final long timeout;
193.387 - private final int maxNotifs;
193.388 -
193.389 - private static final ClassLogger logger =
193.390 - new ClassLogger("javax.management.event",
193.391 - "FetchingEventRelay");
193.392 - private static final ThreadFactory daemonThreadFactory =
193.393 - new DaemonThreadFactory("JMX FetchingEventRelay executor %d");
193.394 -}
194.1 --- a/src/share/classes/javax/management/event/ListenerInfo.java Mon Nov 23 10:04:47 2009 +0000
194.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
194.3 @@ -1,169 +0,0 @@
194.4 -/*
194.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
194.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
194.7 - *
194.8 - * This code is free software; you can redistribute it and/or modify it
194.9 - * under the terms of the GNU General Public License version 2 only, as
194.10 - * published by the Free Software Foundation. Sun designates this
194.11 - * particular file as subject to the "Classpath" exception as provided
194.12 - * by Sun in the LICENSE file that accompanied this code.
194.13 - *
194.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
194.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
194.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
194.17 - * version 2 for more details (a copy is included in the LICENSE file that
194.18 - * accompanied this code).
194.19 - *
194.20 - * You should have received a copy of the GNU General Public License version
194.21 - * 2 along with this work; if not, write to the Free Software Foundation,
194.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
194.23 - *
194.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
194.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
194.26 - * have any questions.
194.27 - */
194.28 -
194.29 -package javax.management.event;
194.30 -
194.31 -import javax.management.NotificationFilter;
194.32 -import javax.management.NotificationListener;
194.33 -import javax.management.ObjectName;
194.34 -
194.35 -/**
194.36 - * This class specifies all the information required to register a user listener into
194.37 - * a remote MBean server. This class is not serializable because a user listener
194.38 - * is not serialized in order to be sent to the remote server.
194.39 - *
194.40 - * @since JMX 2.0
194.41 - */
194.42 -public class ListenerInfo {
194.43 -
194.44 - /**
194.45 - * Constructs a {@code ListenerInfo} object.
194.46 - *
194.47 - * @param name The name of the MBean to which the listener should
194.48 - * be added.
194.49 - * @param listener The listener object which will handle the
194.50 - * notifications emitted by the MBean.
194.51 - * @param filter The filter object. If the filter is null, no
194.52 - * filtering will be performed before notifications are handled.
194.53 - * @param handback The context to be sent to the listener when a
194.54 - * notification is emitted.
194.55 - * @param isSubscription If true, the listener is subscribed via
194.56 - * an {@code EventManager}. Otherwise it is added to a registered MBean.
194.57 - */
194.58 - public ListenerInfo(ObjectName name,
194.59 - NotificationListener listener,
194.60 - NotificationFilter filter,
194.61 - Object handback,
194.62 - boolean isSubscription) {
194.63 - this.name = name;
194.64 - this.listener = listener;
194.65 - this.filter = filter;
194.66 - this.handback = handback;
194.67 - this.isSubscription = isSubscription;
194.68 - }
194.69 -
194.70 - /**
194.71 - * Returns an MBean or an MBean pattern that the listener listens to.
194.72 - *
194.73 - * @return An MBean or an MBean pattern.
194.74 - */
194.75 - public ObjectName getObjectName() {
194.76 - return name;
194.77 - }
194.78 -
194.79 - /**
194.80 - * Returns the listener.
194.81 - *
194.82 - * @return The listener.
194.83 - */
194.84 - public NotificationListener getListener() {
194.85 - return listener;
194.86 - }
194.87 -
194.88 - /**
194.89 - * Returns the listener filter.
194.90 - *
194.91 - * @return The filter.
194.92 - */
194.93 - public NotificationFilter getFilter() {
194.94 - return filter;
194.95 - }
194.96 -
194.97 - /**
194.98 - * Returns the listener handback.
194.99 - *
194.100 - * @return The handback.
194.101 - */
194.102 - public Object getHandback() {
194.103 - return handback;
194.104 - }
194.105 -
194.106 - /**
194.107 - * Returns true if this is a subscription listener.
194.108 - *
194.109 - * @return True if this is a subscription listener.
194.110 - *
194.111 - * @see EventClient#addListeners
194.112 - */
194.113 - public boolean isSubscription() {
194.114 - return isSubscription;
194.115 - }
194.116 -
194.117 - /**
194.118 - * <p>Indicates whether some other object is "equal to" this one.
194.119 - * The return value is true if and only if {@code o} is an instance of
194.120 - * {@code ListenerInfo} and has equal values for all of its properties.</p>
194.121 - */
194.122 - @Override
194.123 - public boolean equals(Object o) {
194.124 - if (this == o) {
194.125 - return true;
194.126 - }
194.127 -
194.128 - if (!(o instanceof ListenerInfo)) {
194.129 - return false;
194.130 - }
194.131 -
194.132 - ListenerInfo li = (ListenerInfo)o;
194.133 -
194.134 - boolean ret = name.equals(li.name) &&
194.135 - (listener == li.listener) &&
194.136 - (isSubscription == li.isSubscription);
194.137 -
194.138 - if (filter != null) {
194.139 - ret &= filter.equals(li.filter);
194.140 - } else {
194.141 - ret &= (li.filter == null);
194.142 - }
194.143 -
194.144 - if (handback != null) {
194.145 - ret &= handback.equals(li.handback);
194.146 - } else {
194.147 - ret &= (li.handback == null);
194.148 - }
194.149 -
194.150 - return ret;
194.151 - }
194.152 -
194.153 - @Override
194.154 - public int hashCode() {
194.155 - return name.hashCode() + listener.hashCode();
194.156 - }
194.157 -
194.158 - @Override
194.159 - public String toString() {
194.160 - return name.toString() + "_" +
194.161 - listener + "_" +
194.162 - filter + "_" +
194.163 - handback + "_" +
194.164 - isSubscription;
194.165 - }
194.166 -
194.167 - private final ObjectName name;
194.168 - private final NotificationListener listener;
194.169 - private final NotificationFilter filter;
194.170 - private final Object handback;
194.171 - private final boolean isSubscription;
194.172 -}
195.1 --- a/src/share/classes/javax/management/event/NotificationManager.java Mon Nov 23 10:04:47 2009 +0000
195.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
195.3 @@ -1,136 +0,0 @@
195.4 -/*
195.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
195.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
195.7 - *
195.8 - * This code is free software; you can redistribute it and/or modify it
195.9 - * under the terms of the GNU General Public License version 2 only, as
195.10 - * published by the Free Software Foundation. Sun designates this
195.11 - * particular file as subject to the "Classpath" exception as provided
195.12 - * by Sun in the LICENSE file that accompanied this code.
195.13 - *
195.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
195.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
195.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
195.17 - * version 2 for more details (a copy is included in the LICENSE file that
195.18 - * accompanied this code).
195.19 - *
195.20 - * You should have received a copy of the GNU General Public License version
195.21 - * 2 along with this work; if not, write to the Free Software Foundation,
195.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
195.23 - *
195.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
195.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
195.26 - * have any questions.
195.27 - */
195.28 -
195.29 -package javax.management.event;
195.30 -
195.31 -import java.io.IOException;
195.32 -import javax.management.InstanceNotFoundException;
195.33 -import javax.management.ListenerNotFoundException;
195.34 -import javax.management.NotificationFilter;
195.35 -import javax.management.NotificationListener;
195.36 -import javax.management.ObjectName;
195.37 -
195.38 -/**
195.39 - * This interface specifies methods to add and remove notification listeners
195.40 - * on named MBeans.
195.41 - */
195.42 -public interface NotificationManager {
195.43 - /**
195.44 - * <p>Adds a listener to a registered MBean.
195.45 - * Notifications emitted by the MBean will be forwarded
195.46 - * to the listener.
195.47 - *
195.48 - * @param name The name of the MBean on which the listener should
195.49 - * be added.
195.50 - * @param listener The listener object which will handle the
195.51 - * notifications emitted by the registered MBean.
195.52 - * @param filter The filter object. If filter is null, no
195.53 - * filtering will be performed before handling notifications.
195.54 - * @param handback The context to be sent to the listener when a
195.55 - * notification is emitted.
195.56 - *
195.57 - * @exception InstanceNotFoundException The MBean name provided
195.58 - * does not match any of the registered MBeans.
195.59 - * @exception IOException A communication problem occurred when
195.60 - * talking to the MBean server.
195.61 - *
195.62 - * @see #removeNotificationListener(ObjectName, NotificationListener)
195.63 - * @see #removeNotificationListener(ObjectName, NotificationListener,
195.64 - * NotificationFilter, Object)
195.65 - */
195.66 - public void addNotificationListener(ObjectName name,
195.67 - NotificationListener listener,
195.68 - NotificationFilter filter,
195.69 - Object handback)
195.70 - throws InstanceNotFoundException,
195.71 - IOException;
195.72 -
195.73 - /**
195.74 - * <p>Removes a listener from a registered MBean.</p>
195.75 - *
195.76 - * <P> If the listener is registered more than once, perhaps with
195.77 - * different filters or callbacks, this method will remove all
195.78 - * those registrations.
195.79 - *
195.80 - * @param name The name of the MBean on which the listener should
195.81 - * be removed.
195.82 - * @param listener The listener to be removed.
195.83 - *
195.84 - * @exception InstanceNotFoundException The MBean name provided
195.85 - * does not match any of the registered MBeans.
195.86 - * @exception ListenerNotFoundException The listener is not
195.87 - * registered in the MBean.
195.88 - * @exception IOException A communication problem occurred when
195.89 - * talking to the MBean server.
195.90 - *
195.91 - * @see #addNotificationListener(ObjectName, NotificationListener,
195.92 - * NotificationFilter, Object)
195.93 - */
195.94 - public void removeNotificationListener(ObjectName name,
195.95 - NotificationListener listener)
195.96 - throws InstanceNotFoundException,
195.97 - ListenerNotFoundException,
195.98 - IOException;
195.99 -
195.100 - /**
195.101 - * <p>Removes a listener from a registered MBean.</p>
195.102 - *
195.103 - * <p>The MBean must have a listener that exactly matches the
195.104 - * given <code>listener</code>, <code>filter</code>, and
195.105 - * <code>handback</code> parameters. If there is more than one
195.106 - * such listener, only one is removed.</p>
195.107 - *
195.108 - * <p>The <code>filter</code> and <code>handback</code> parameters
195.109 - * may be null if and only if they are null in a listener to be
195.110 - * removed.</p>
195.111 - *
195.112 - * @param name The name of the MBean on which the listener should
195.113 - * be removed.
195.114 - * @param listener The listener to be removed.
195.115 - * @param filter The filter that was specified when the listener
195.116 - * was added.
195.117 - * @param handback The handback that was specified when the
195.118 - * listener was added.
195.119 - *
195.120 - * @exception InstanceNotFoundException The MBean name provided
195.121 - * does not match any of the registered MBeans.
195.122 - * @exception ListenerNotFoundException The listener is not
195.123 - * registered in the MBean, or it is not registered with the given
195.124 - * filter and handback.
195.125 - * @exception IOException A communication problem occurred when
195.126 - * talking to the MBean server.
195.127 - *
195.128 - * @see #addNotificationListener(ObjectName, NotificationListener,
195.129 - * NotificationFilter, Object)
195.130 - *
195.131 - */
195.132 - public void removeNotificationListener(ObjectName name,
195.133 - NotificationListener listener,
195.134 - NotificationFilter filter,
195.135 - Object handback)
195.136 - throws InstanceNotFoundException,
195.137 - ListenerNotFoundException,
195.138 - IOException;
195.139 -}
196.1 --- a/src/share/classes/javax/management/event/RMIPushEventForwarder.java Mon Nov 23 10:04:47 2009 +0000
196.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
196.3 @@ -1,198 +0,0 @@
196.4 -/*
196.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
196.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
196.7 - *
196.8 - * This code is free software; you can redistribute it and/or modify it
196.9 - * under the terms of the GNU General Public License version 2 only, as
196.10 - * published by the Free Software Foundation. Sun designates this
196.11 - * particular file as subject to the "Classpath" exception as provided
196.12 - * by Sun in the LICENSE file that accompanied this code.
196.13 - *
196.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
196.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
196.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
196.17 - * version 2 for more details (a copy is included in the LICENSE file that
196.18 - * accompanied this code).
196.19 - *
196.20 - * You should have received a copy of the GNU General Public License version
196.21 - * 2 along with this work; if not, write to the Free Software Foundation,
196.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
196.23 - *
196.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
196.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
196.26 - * have any questions.
196.27 - */
196.28 -
196.29 -package javax.management.event;
196.30 -
196.31 -import com.sun.jmx.event.DaemonThreadFactory;
196.32 -import com.sun.jmx.event.RepeatedSingletonJob;
196.33 -import com.sun.jmx.remote.util.ClassLogger;
196.34 -import java.rmi.RemoteException;
196.35 -import java.util.ArrayList;
196.36 -import java.util.List;
196.37 -import java.util.concurrent.ArrayBlockingQueue;
196.38 -import java.util.concurrent.BlockingQueue;
196.39 -import java.util.concurrent.ExecutorService;
196.40 -import java.util.concurrent.Executors;
196.41 -import javax.management.Notification;
196.42 -import javax.management.remote.NotificationResult;
196.43 -import javax.management.remote.TargetedNotification;
196.44 -
196.45 -
196.46 -/**
196.47 - * This class is used by {@link RMIPushEventRelay}. When
196.48 - * {@link RMIPushEventRelay} calls {@link
196.49 - * EventClientDelegateMBean#addClient(String, Object[], String[])} to get a new
196.50 - * client identifier, it uses this class name as the
196.51 - * first argument to ask {@code EventClientDelegateMBean} to create an object of
196.52 - * this class.
196.53 - * Then {@code EventClientDelegateMBean} forwards client notifications
196.54 - * to this object. This object then continues forwarding the notifications
196.55 - * to the {@code RMIPushEventRelay}.
196.56 - */
196.57 -public class RMIPushEventForwarder implements EventForwarder {
196.58 - private static final int DEFAULT_BUFFER_SIZE = 6000;
196.59 -
196.60 - /**
196.61 - * Creates a new instance of {@code RMIPushEventForwarder}.
196.62 - *
196.63 - * @param receiver An RMI stub exported to receive notifications
196.64 - * from this object for its {@link RMIPushEventRelay}.
196.65 - *
196.66 - * @param bufferSize The maximum number of notifications to store
196.67 - * while waiting for the last remote send to complete.
196.68 - */
196.69 - public RMIPushEventForwarder(RMIPushServer receiver, int bufferSize) {
196.70 - if (logger.traceOn()) {
196.71 - logger.trace("RMIEventForwarder", "new one");
196.72 - }
196.73 -
196.74 - if (bufferSize < 0) {
196.75 - throw new IllegalArgumentException(
196.76 - "Negative buffer size: " + bufferSize);
196.77 - } else if (bufferSize == 0)
196.78 - bufferSize = DEFAULT_BUFFER_SIZE;
196.79 -
196.80 - if (receiver == null) {
196.81 - throw new NullPointerException();
196.82 - }
196.83 -
196.84 - this.receiver = receiver;
196.85 - this.buffer = new ArrayBlockingQueue<TargetedNotification>(bufferSize);
196.86 - }
196.87 -
196.88 - public void forward(Notification n, Integer listenerId) {
196.89 - if (logger.traceOn()) {
196.90 - logger.trace("forward", "to the listener: "+listenerId);
196.91 - }
196.92 - synchronized(sendingJob) {
196.93 - TargetedNotification tn = new TargetedNotification(n, listenerId);
196.94 - while (!buffer.offer(tn)) {
196.95 - buffer.remove();
196.96 - passed++;
196.97 - }
196.98 - sendingJob.resume();
196.99 - }
196.100 - }
196.101 -
196.102 - public void close() {
196.103 - if (logger.traceOn()) {
196.104 - logger.trace("close", "called");
196.105 - }
196.106 -
196.107 - synchronized(sendingJob) {
196.108 - ended = true;
196.109 - buffer.clear();
196.110 - }
196.111 - }
196.112 -
196.113 - public void setClientId(String clientId) {
196.114 - if (logger.traceOn()) {
196.115 - logger.trace("setClientId", clientId);
196.116 - }
196.117 - }
196.118 -
196.119 - private class SendingJob extends RepeatedSingletonJob {
196.120 - public SendingJob() {
196.121 - super(executor);
196.122 - }
196.123 -
196.124 - public boolean isSuspended() {
196.125 - return ended || buffer.isEmpty();
196.126 - }
196.127 -
196.128 - public void task() {
196.129 - final long earliest = passed;
196.130 -
196.131 - List<TargetedNotification> tns =
196.132 - new ArrayList<TargetedNotification>(buffer.size());
196.133 - synchronized(sendingJob) {
196.134 - buffer.drainTo(tns);
196.135 - passed += tns.size();
196.136 - }
196.137 -
196.138 - if (logger.traceOn()) {
196.139 - logger.trace("SendingJob-task", "sending: "+tns.size());
196.140 - }
196.141 -
196.142 - if (!tns.isEmpty()) {
196.143 - try {
196.144 - TargetedNotification[] tnArray =
196.145 - new TargetedNotification[tns.size()];
196.146 - tns.toArray(tnArray);
196.147 - receiver.receive(new NotificationResult(earliest, passed, tnArray));
196.148 - } catch (RemoteException e) {
196.149 - if (logger.debugOn()) {
196.150 - logger.debug("SendingJob-task",
196.151 - "Got exception to forward notifs.", e);
196.152 - }
196.153 -
196.154 - long currentLost = passed - earliest;
196.155 - if (FetchingEventRelay.isSerialOrClassNotFound(e)) {
196.156 - // send one by one
196.157 - long tmpPassed = earliest;
196.158 - for (TargetedNotification tn : tns) {
196.159 - try {
196.160 - receiver.receive(new NotificationResult(earliest,
196.161 - ++tmpPassed, new TargetedNotification[]{tn}));
196.162 - } catch (RemoteException ioee) {
196.163 - logger.trace(
196.164 - "SendingJob-task", "send to remote", ioee);
196.165 - // sends nonFatal notifs?
196.166 - }
196.167 - }
196.168 -
196.169 - currentLost = passed - tmpPassed;
196.170 - }
196.171 -
196.172 - if (currentLost > 0) { // inform of the lost.
196.173 - try {
196.174 - receiver.receive(new NotificationResult(
196.175 - passed, passed,
196.176 - new TargetedNotification[]{}));
196.177 - } catch (RemoteException ee) {
196.178 - logger.trace(
196.179 - "SendingJob-task", "receiver.receive", ee);
196.180 - }
196.181 - }
196.182 - }
196.183 - }
196.184 - }
196.185 - }
196.186 -
196.187 - private long passed = 0;
196.188 -
196.189 - private static final ExecutorService executor =
196.190 - Executors.newCachedThreadPool(
196.191 - new DaemonThreadFactory("JMX RMIEventForwarder Executor"));
196.192 - private final SendingJob sendingJob = new SendingJob();
196.193 -
196.194 - private final BlockingQueue<TargetedNotification> buffer;
196.195 -
196.196 - private final RMIPushServer receiver;
196.197 - private boolean ended = false;
196.198 -
196.199 - private static final ClassLogger logger =
196.200 - new ClassLogger("javax.management.event", "RMIEventForwarder");
196.201 -}
197.1 --- a/src/share/classes/javax/management/event/RMIPushEventRelay.java Mon Nov 23 10:04:47 2009 +0000
197.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
197.3 @@ -1,161 +0,0 @@
197.4 -/*
197.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
197.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
197.7 - *
197.8 - * This code is free software; you can redistribute it and/or modify it
197.9 - * under the terms of the GNU General Public License version 2 only, as
197.10 - * published by the Free Software Foundation. Sun designates this
197.11 - * particular file as subject to the "Classpath" exception as provided
197.12 - * by Sun in the LICENSE file that accompanied this code.
197.13 - *
197.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
197.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
197.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
197.17 - * version 2 for more details (a copy is included in the LICENSE file that
197.18 - * accompanied this code).
197.19 - *
197.20 - * You should have received a copy of the GNU General Public License version
197.21 - * 2 along with this work; if not, write to the Free Software Foundation,
197.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
197.23 - *
197.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
197.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
197.26 - * have any questions.
197.27 - */
197.28 -
197.29 -package javax.management.event;
197.30 -
197.31 -import com.sun.jmx.remote.util.ClassLogger;
197.32 -import java.io.IOException;
197.33 -import java.rmi.NoSuchObjectException;
197.34 -import java.rmi.RemoteException;
197.35 -import java.rmi.server.UnicastRemoteObject;
197.36 -import java.rmi.server.RMIClientSocketFactory;
197.37 -import java.rmi.server.RMIServerSocketFactory;
197.38 -import javax.management.MBeanException;
197.39 -import javax.management.remote.NotificationResult;
197.40 -
197.41 -/**
197.42 - * This class is an implementation of the {@link EventRelay} interface, using
197.43 - * push mode. It exports an RMI object that {@link RMIPushEventForwarder} uses
197.44 - * to forward notifications.
197.45 - *
197.46 - * @since JMX 2.0
197.47 - */
197.48 -public class RMIPushEventRelay implements EventRelay {
197.49 - /**
197.50 - * Constructs a default {@code RMIPushEventRelay} object
197.51 - * and exports its {@linkplain RMIPushServer notification
197.52 - * receiver} on any free port. This constructor is equivalent
197.53 - * to {@link #RMIPushEventRelay(EventClientDelegateMBean,
197.54 - * int, RMIClientSocketFactory, RMIServerSocketFactory, int)
197.55 - * RMIPushEventRelay(delegate, 0, null, null, <em><default buffer
197.56 - * size></em>)}.
197.57 - *
197.58 - * @param delegate The {@link EventClientDelegateMBean} proxy to work with.
197.59 - * @throws IOException if failed to communicate with
197.60 - * {@link EventClientDelegateMBean}.
197.61 - * @throws MBeanException if the {@link EventClientDelegateMBean} failed
197.62 - * to create an {@code EventForwarder} for this object.
197.63 - */
197.64 - public RMIPushEventRelay(EventClientDelegateMBean delegate)
197.65 - throws IOException, MBeanException {
197.66 - this(delegate, 0, null, null, 0);
197.67 - }
197.68 -
197.69 - /**
197.70 - * Constructs a {@code RMIPushEventRelay} object and exports its
197.71 - * {@linkplain RMIPushServer notification receiver} on a specified port.
197.72 - *
197.73 - * @param delegate The {@link EventClientDelegateMBean} proxy to work with.
197.74 - * @param port The port used to export an RMI object to receive notifications
197.75 - * from a server. If the port is zero, an anonymous port is used.
197.76 - * @param csf The client socket factory used to export the RMI object.
197.77 - * Can be null.
197.78 - * @param ssf The server socket factory used to export the RMI object.
197.79 - * Can be null.
197.80 - * @param bufferSize The number of notifications held on the server
197.81 - * while waiting for the previous transmission to complete. A value of
197.82 - * zero means the default buffer size.
197.83 - *
197.84 - * @throws IOException if failed to communicate with
197.85 - * {@link EventClientDelegateMBean}.
197.86 - * @throws MBeanException if the {@link EventClientDelegateMBean} failed
197.87 - * to create an {@code EventForwarder} for this object.
197.88 - *
197.89 - * @see RMIPushEventForwarder#RMIPushEventForwarder(RMIPushServer, int)
197.90 - */
197.91 - public RMIPushEventRelay(EventClientDelegateMBean delegate,
197.92 - int port,
197.93 - RMIClientSocketFactory csf,
197.94 - RMIServerSocketFactory ssf,
197.95 - int bufferSize)
197.96 - throws IOException, MBeanException {
197.97 -
197.98 - UnicastRemoteObject.exportObject(exportedReceiver, port, csf, ssf);
197.99 -
197.100 - clientId = delegate.addClient(
197.101 - RMIPushEventForwarder.class.getName(),
197.102 - new Object[] {exportedReceiver, bufferSize},
197.103 - new String[] {RMIPushServer.class.getName(),
197.104 - int.class.getName()});
197.105 - }
197.106 -
197.107 - public String getClientId() {
197.108 - return clientId;
197.109 - }
197.110 -
197.111 - public void setEventReceiver(EventReceiver receiver) {
197.112 - if (logger.traceOn()) {
197.113 - logger.trace("setEventReceiver", ""+receiver);
197.114 - }
197.115 - synchronized(lock) {
197.116 - this.receiver = receiver;
197.117 - }
197.118 - }
197.119 -
197.120 - public void stop() {
197.121 - if (logger.traceOn()) {
197.122 - logger.trace("stop", "");
197.123 - }
197.124 - synchronized(lock) {
197.125 - if (stopped) {
197.126 - return;
197.127 - } else {
197.128 - stopped = true;
197.129 - }
197.130 -
197.131 - if (clientId == null) {
197.132 - return;
197.133 - }
197.134 -
197.135 - try {
197.136 - UnicastRemoteObject.unexportObject(exportedReceiver, true);
197.137 - } catch (NoSuchObjectException nsoe) {
197.138 - logger.fine("RMIPushEventRelay.stop", "unexport", nsoe);
197.139 - // OK: we wanted it unexported, and apparently it already is
197.140 - }
197.141 - }
197.142 - }
197.143 -
197.144 - private volatile String clientId;
197.145 - private volatile EventReceiver receiver;
197.146 -
197.147 - private RMIPushServer exportedReceiver = new RMIPushServer() {
197.148 - public void receive(NotificationResult nr) throws RemoteException {
197.149 - if (logger.traceOn()) {
197.150 - logger.trace("EventPusherImpl-receive","");
197.151 - }
197.152 - receiver.receive(nr);
197.153 - // Any exception will be sent back to the client.
197.154 - }
197.155 - };
197.156 -
197.157 - private boolean stopped = false;
197.158 -
197.159 - private final int[] lock = new int[0];
197.160 -
197.161 - private static final ClassLogger logger =
197.162 - new ClassLogger("javax.management.event",
197.163 - "PushEventRelay");
197.164 -}
198.1 --- a/src/share/classes/javax/management/event/RMIPushServer.java Mon Nov 23 10:04:47 2009 +0000
198.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
198.3 @@ -1,48 +0,0 @@
198.4 -/*
198.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
198.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
198.7 - *
198.8 - * This code is free software; you can redistribute it and/or modify it
198.9 - * under the terms of the GNU General Public License version 2 only, as
198.10 - * published by the Free Software Foundation. Sun designates this
198.11 - * particular file as subject to the "Classpath" exception as provided
198.12 - * by Sun in the LICENSE file that accompanied this code.
198.13 - *
198.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
198.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
198.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
198.17 - * version 2 for more details (a copy is included in the LICENSE file that
198.18 - * accompanied this code).
198.19 - *
198.20 - * You should have received a copy of the GNU General Public License version
198.21 - * 2 along with this work; if not, write to the Free Software Foundation,
198.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
198.23 - *
198.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
198.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
198.26 - * have any questions.
198.27 - */
198.28 -
198.29 -package javax.management.event;
198.30 -
198.31 -import java.rmi.Remote;
198.32 -import java.rmi.RemoteException;
198.33 -import javax.management.remote.NotificationResult;
198.34 -
198.35 -/**
198.36 - * The {@link RMIPushEventRelay} exports an RMI object of this class and
198.37 - * sends a client stub for that object to the associated
198.38 - * {@link RMIPushEventForwarder} in a remote MBean server. The
198.39 - * {@code RMIPushEventForwarder} then sends notifications to the
198.40 - * RMI object.
198.41 - */
198.42 -public interface RMIPushServer extends Remote {
198.43 - /**
198.44 - * <p>Dispatch the notifications in {@code nr} to the {@link RMIPushEventRelay}
198.45 - * associated with this object.</p>
198.46 - * @param nr the notification result to dispatch.
198.47 - * @throws java.rmi.RemoteException if the remote invocation of this method
198.48 - * failed.
198.49 - */
198.50 - public void receive(NotificationResult nr) throws RemoteException;
198.51 -}
199.1 --- a/src/share/classes/javax/management/event/package-info.java Mon Nov 23 10:04:47 2009 +0000
199.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
199.3 @@ -1,312 +0,0 @@
199.4 -/**
199.5 - * <p>Defines the <em>Event Service</em>, which provides extended support
199.6 - * for JMX notifications.</p>
199.7 - *
199.8 - * <p>The Event Service provides greater control over
199.9 - * notification handling than the default technique using {@link
199.10 - * javax.management.MBeanServer#addNotificationListener(ObjectName,
199.11 - * NotificationListener, NotificationFilter, Object)
199.12 - * MBeanServer.addNotificationListener} or {@link
199.13 - * javax.management.MBeanServerConnection#addNotificationListener(ObjectName,
199.14 - * NotificationListener, NotificationFilter, Object)
199.15 - * MBeanServerConnection.addNotificationListener}.</p>
199.16 - *
199.17 - * <p>Here are some reasons you may want to use the Event Service:</p>
199.18 - *
199.19 - * <ul>
199.20 - * <li>To receive notifications from a set of MBeans defined by an
199.21 - * ObjectName pattern, such as {@code com.example.config:type=Cache,*}.
199.22 - *
199.23 - * <li>When the notification-handling behavior of the connector you are
199.24 - * using does not match your requirements. For example, with the standard
199.25 - * RMI connector you can lose notifications if there are very many of them
199.26 - * in the MBean Server you are connected to, even if you are only listening
199.27 - * for a small proportion of them.
199.28 - *
199.29 - * <li>To change the threading behavior of notification dispatch.
199.30 - *
199.31 - * <li>To define a different transport for notifications, for example to
199.32 - * arrange for them to be delivered through the Java Message Service (<a
199.33 - * href="http://java.sun.com/jms">JMS</a>). The Event Service comes with
199.34 - * one alternative transport as standard, a "push-mode" RMI transport.
199.35 - *
199.36 - * <li>To handle notifications on behalf of MBeans (often virtual) in a
199.37 - * namespace.
199.38 - * </ul>
199.39 - *
199.40 - * <p>The Event Service is new in version 2.0 of the JMX API, which is the
199.41 - * version introduced in version 7 of the Java SE platform. It is not usually
199.42 - * possible to use the Event Service when connecting remotely to an
199.43 - * MBean Server that is running an earlier version.</p>
199.44 - *
199.45 - *
199.46 - * <h3 id="handlingremote">Handling remote notifications with the Event
199.47 - * Service</h3>
199.48 - *
199.49 - * <p>Prior to version 2.0 of the JMX API, every connector
199.50 - * had to include logic to handle notifications. The standard {@linkplain
199.51 - * javax.management.remote.rmi RMI} and JMXMP connectors defined by <a
199.52 - * href="http://jcp.org/en/jsr/detail?id=160">JSR 160</a> handle notifications
199.53 - * in a way that is not always appropriate for applications. Specifically,
199.54 - * the connector server adds one listener to every MBean that might emit
199.55 - * notifications, and adds all received notifications to a fixed-size
199.56 - * buffer. This means that if there are very many notifications, a
199.57 - * remote client may miss some, even if it is only registered for a
199.58 - * very small subset of notifications. Furthermore, since every {@link
199.59 - * javax.management.NotificationBroadcaster NotificationBroadcaster} MBean
199.60 - * gets a listener from the connector server, MBeans cannot usefully optimize
199.61 - * by only sending notifications when there is a listener. Finally, since
199.62 - * the connector server uses just one listener per MBean, MBeans cannot
199.63 - * impose custom behavior per listener, such as security checks or localized
199.64 - * notifications.</p>
199.65 - *
199.66 - * <p>The Event Service does not have these restrictions. The RMI connector
199.67 - * that is included in this version of the JMX API uses the Event Service by
199.68 - * default, although it can be configured to have the previous behavior if
199.69 - * required.</p>
199.70 - *
199.71 - * <p>The Event Service can be used with <em>any</em> connector via the
199.72 - * method {@link javax.management.event.EventClient#getEventClientConnection
199.73 - * EventClient.getEventClientConnection}, like this:</p>
199.74 - *
199.75 - * <pre>
199.76 - * JMXConnector conn = ...;
199.77 - * MBeanServerConnection mbsc = conn.getMBeanServerConnection();
199.78 - * MBeanServerConnection eventMbsc = EventClient.getEventClientConnection(mbsc);
199.79 - * </pre>
199.80 - *
199.81 - * <p>If you add listeners using {@code eventMbsc.addNotificationListener}
199.82 - * instead of {@code mbsc.addNotificationListener}, then they will be handled
199.83 - * by the Event Service rather than by the connector's notification system.</p>
199.84 - *
199.85 - * <p>For the Event Service to work, either the {@link
199.86 - * javax.management.event.EventClientDelegateMBean EventClientDelegateMBean}
199.87 - * must be registered in the MBean Server, or the connector server must
199.88 - * be configured to simulate the existence of this MBean, for example
199.89 - * using {@link javax.management.event.EventClientDelegate#newForwarder
199.90 - * EventClientDelegate.newForwarder}. The standard RMI connector is so
199.91 - * configured by default. The {@code EventClientDelegateMBean} documentation
199.92 - * has further details.</p>
199.93 - *
199.94 - *
199.95 - * <h3 id="subscribepattern">Receiving notifications from a set of MBeans</h3>
199.96 - *
199.97 - * <p>The Event Server allows you to receive notifications from every MBean
199.98 - * that matches an {@link javax.management.ObjectName ObjectName} pattern.
199.99 - * For local clients (in the same JVM as the MBean Server), the {@link
199.100 - * javax.management.event.EventSubscriber EventSubscriber} class can be used for
199.101 - * this. For remote clients, or if the same code is to be used locally and
199.102 - * remotely, use an
199.103 - * {@link javax.management.event.EventClient EventClient}.</p>
199.104 - *
199.105 - * <p>EventSubscriber and EventClient correctly handle the case where a new
199.106 - * MBean is registered under a name that matches the pattern. Notifications
199.107 - * from the new MBean will also be received.</p>
199.108 - *
199.109 - * <p>Here is how to receive notifications from all MBeans in a local
199.110 - * {@code MBeanServer} that match {@code com.example.config:type=Cache,*}:</p>
199.111 - *
199.112 - * <pre>
199.113 - * MBeanServer mbs = ...;
199.114 - * NotificationListener listener = ...;
199.115 - * ObjectName pattern = new ObjectName("com.example.config:type=Cache,*");
199.116 - * EventSubscriber esub = EventSubscriber.getEventSubscriber(mbs);
199.117 - * esub.{@link javax.management.event.EventSubscriber#subscribe
199.118 - * subscribe}(pattern, listener, null, null);
199.119 - * </pre>
199.120 - *
199.121 - * <p>Here is how to do the same thing remotely:</p>
199.122 - *
199.123 - * <pre>
199.124 - * MBeanServerConnection mbsc = jmxConnector.getMBeanServerConnection();
199.125 - * EventClient events = new EventClient(mbsc);
199.126 - * NotificationListener listener = ...;
199.127 - * ObjectName pattern = new ObjectName("com.example.config:type=Cache,*");
199.128 - * events.{@link javax.management.event.EventClient#subscribe
199.129 - * subscribe}(pattern, listener, null, null);
199.130 - * </pre>
199.131 - *
199.132 - *
199.133 - * <h3 id="threading">Controlling threading behavior for notification
199.134 - * dispatch</h3>
199.135 - *
199.136 - * <p>The EventClient class can be used to control threading of listener
199.137 - * dispatch. For example, to arrange for all listeners to be invoked
199.138 - * in the same thread, you can create an {@code EventClient} like this:</p>
199.139 - *
199.140 - * <pre>
199.141 - * MBeanServerConnection mbsc = ...;
199.142 - * Executor singleThreadExecutor = {@link
199.143 - * java.util.concurrent.Executors#newSingleThreadExecutor()
199.144 - * Executors.newSingleThreadExecutor}();
199.145 - * EventClient events = new EventClient(
199.146 - * mbsc, null, singleThreadExecutor, EventClient.DEFAULT_LEASE_TIMEOUT);
199.147 - * events.addNotificationListener(...);
199.148 - * events.subscribe(...);
199.149 - * </pre>
199.150 - *
199.151 - *
199.152 - * <h3 id="leasing">Leasing</h3>
199.153 - *
199.154 - * <p>The {@code EventClient} uses a <em>lease</em> mechanism to ensure
199.155 - * that resources are eventually released on the server even if the client
199.156 - * does not explicitly clean up. (This can happen through network
199.157 - * partitioning, for example.)</p>
199.158 - *
199.159 - * <p>When an {@code EventClient} registers with the {@code
199.160 - * EventClientDelegateMBean} using one of the {@code addClient} methods,
199.161 - * an initial lease is created with a default expiry time. The {@code
199.162 - * EventClient} requests an explicit lease shortly after that, with a
199.163 - * configurable expiry time. Then the {@code EventClient} periodically
199.164 - * <em>renews</em> the lease before it expires, typically about half way
199.165 - * through the lifetime of the lease. If at any point the lease reaches
199.166 - * the expiry time of the last renewal then it expires, and {@code
199.167 - * EventClient} is unregistered as if it had called the {@link
199.168 - * javax.management.event.EventClientDelegateMBean#removeClient removeClient}
199.169 - * method.</p>
199.170 - *
199.171 - *
199.172 - * <h3 id="transports">Custom notification transports</h3>
199.173 - *
199.174 - * <p>When you create an {@code EventClient}, you can define the transport
199.175 - * that it uses to deliver notifications. The transport might use the
199.176 - * Java Message Service (<a href="http://java.sun.com/jms">JMS</a>) or
199.177 - * any other communication system. Specifying a transport is useful for
199.178 - * example when you want different network behavior from the default, or
199.179 - * different reliability guarantees. The default transport calls {@link
199.180 - * javax.management.event.EventClientDelegateMBean#fetchNotifications
199.181 - * EventClientDelegateMBean.fetchNotifications} repeatedly, which usually means
199.182 - * that there must be a network connection permanently open between the client
199.183 - * and the server. If the same client is connected to many servers this can
199.184 - * cause scalability problems. If notifications are relatively rare, then
199.185 - * JMS or the {@linkplain javax.management.event.RMIPushEventRelay push-mode
199.186 - * RMI transport} may be more suitable.</p>
199.187 - *
199.188 - * <p>A transport is implemented by an {@link javax.management.event.EventRelay
199.189 - * EventRelay} on the client side and a corresponding {@link
199.190 - * javax.management.event.EventForwarder EventForwarder}
199.191 - * on the server side. An example is the {@link
199.192 - * javax.management.event.RMIPushEventRelay RMIPushEventRelay} and its
199.193 - * {@link javax.management.event.RMIPushEventForwarder RMIPushEventForwarder}.</p>
199.194 - *
199.195 - * <p>To use a given transport with an {@code EventClient}, you first create
199.196 - * an instance of its {@code EventRelay}. Typically the {@code EventRelay}'s
199.197 - * constructor will have a parameter of type {@code MBeanServerConnection}
199.198 - * or {@code EventClientDelegateMBean}, so that it can communicate with the
199.199 - * {@code EventClientDelegateMBean} in the server. For example, the {@link
199.200 - * javax.management.event.RMIPushEventForwarder RMIPushEventForwarder}'s constructors
199.201 - * all take an {@code EventClientDelegateMBean} parameter, which is expected to
199.202 - * be a {@linkplain javax.management.JMX#newMBeanProxy(MBeanServerConnection,
199.203 - * ObjectName, Class) proxy} for the {@code EventClientDelegateMBean} in the
199.204 - * server.</p>
199.205 - *
199.206 - * <p>When it is created, the {@code EventRelay} will call
199.207 - * {@link javax.management.event.EventClientDelegateMBean#addClient(String,
199.208 - * Object[], String[]) EventClientDelegateMBean.addClient}. It passes the
199.209 - * name of the {@code EventForwarder} class and its constructor parameters.
199.210 - * The {@code EventClientDelegateMBean} will instantiate this class using
199.211 - * {@link javax.management.MBeanServer#instantiate(String, Object[], String[])
199.212 - * MBeanServer.instantiate}, and it will return a unique <em>client id</em>.</p>
199.213 - *
199.214 - * <p>Then you pass the newly-created {@code EventRelay} to one of the {@code
199.215 - * EventClient} constructors, and you have an {@code EventClient} that uses the
199.216 - * chosen transport.</p>
199.217 - *
199.218 - * <p>For example, when you create an {@code RMIPushEventRelay}, it
199.219 - * uses {@code MBeanServerDelegateMBean.addClient} to create an {@code
199.220 - * RMIEventForwarder} in the server. Notifications will then be delivered
199.221 - * through an RMI communication from the {@code RMIEventForwarder} to the
199.222 - * {@code RMIPushEventRelay}.</p>
199.223 - *
199.224 - *
199.225 - * <h4 id="writingcustomtransport">Writing a custom transport</h4>
199.226 - *
199.227 - * <p>To write a custom transport, you need to understand the sequence
199.228 - * of events when an {@code EventRelay} and its corresponding {@code
199.229 - * EventForwarder} are created, and when a notification is sent from the {@code
199.230 - * EventForwarder} to the {@code EventRelay}.</p>
199.231 - *
199.232 - * <p>When an {@code EventRelay} is created:</p>
199.233 - *
199.234 - * <ul>
199.235 - * <li><p>The {@code EventRelay} must call {@code
199.236 - * EventClientDelegateMBean.addClient} with the name of the {@code
199.237 - * EventForwarder} and the constructor parameters.</p>
199.238 - *
199.239 - * <li><p>{@code EventClientDelegateMBean.addClient} will do the following
199.240 - * steps:</p>
199.241 - *
199.242 - * <ul>
199.243 - * <li>create the {@code EventForwarder} using {@code MBeanServer.instantiate};
199.244 - * <li>allocate a unique client id;
199.245 - * <li>call the new {@code EventForwarder}'s {@link
199.246 - * javax.management.event.EventForwarder#setClientId setClientId} method with
199.247 - * the new client id;
199.248 - * <li>return the client id to the caller.
199.249 - * </ul>
199.250 - *
199.251 - * </ul>
199.252 - *
199.253 - * <p>When an {@code EventClient} is created with an {@code EventRelay}
199.254 - * parameter, it calls {@link javax.management.event.EventRelay#setEventReceiver
199.255 - * EventRelay.setEventReceiver} with an {@code EventReceiver} that the
199.256 - * {@code EventRelay} will use to deliver notifications.</p>
199.257 - *
199.258 - * <p>When a listener is added using the {@code EventClient}, the
199.259 - * {@code EventRelay} and {@code EventForwarder} are not involved.</p>
199.260 - *
199.261 - * <p>When an MBean emits a notification and a listener has been added
199.262 - * to that MBean using the {@code EventClient}:</p>
199.263 - *
199.264 - * <ul>
199.265 - * <li><p>The {@code EventForwarder}'s
199.266 - * {@link javax.management.event.EventForwarder#forward forward} method
199.267 - * is called with the notification and a <em>listener id</em>.</p>
199.268 - *
199.269 - * <li><p>The {@code EventForwarder} sends the notification and listener id
199.270 - * to the {@code EventRelay} using the custom transport.</p>
199.271 - *
199.272 - * <li><p>The {@code EventRelay} delivers the notification by calling
199.273 - * {@link javax.management.event.EventReceiver#receive EventReceiver.receive}.</p>
199.274 - * </ul>
199.275 - *
199.276 - * <p>When the {@code EventClient} is closed ({@link
199.277 - * javax.management.event.EventClient#close EventClient.close}):</p>
199.278 - *
199.279 - * <ul>
199.280 - * <li><p>The {@code EventClient} calls {@link
199.281 - * javax.management.event.EventRelay#stop EventRelay.stop}.</p>
199.282 - *
199.283 - * <li><p>The {@code EventClient} calls {@link
199.284 - * javax.management.event.EventClientDelegateMBean#removeClient
199.285 - * EventClientDelegateMBean.removeClient}.</p>
199.286 - *
199.287 - * <li><p>The {@code EventClientDelegateMBean} removes any listeners it
199.288 - * had added on behalf of this {@code EventClient}.</p>
199.289 - *
199.290 - * <li><p>The {@code EventClientDelegateMBean} calls
199.291 - * {@link javax.management.event.EventForwarder#close EventForwarder.close}.</p>
199.292 - * </ul>
199.293 - *
199.294 - *
199.295 - * <h4 id="threading">Threading and buffering</h3>
199.296 - *
199.297 - * <p>The {@link javax.management.event.EventForwarder#forward
199.298 - * EventForwarder.forward} method may be called in the thread that the
199.299 - * source MBean is using to send its notification. MBeans can expect
199.300 - * that notification sending does not block. Therefore a {@code forward}
199.301 - * method will typically add the notification to a queue, with a separate
199.302 - * thread that takes notifications off the queue and sends them.</p>
199.303 - *
199.304 - * <p>An {@code EventRelay} does not usually need to buffer notifications
199.305 - * before giving them to
199.306 - * {@link javax.management.event.EventReceiver#receive EventReceiver.receive}.
199.307 - * Although by default each such notification will be sent to potentially-slow
199.308 - * listeners, if this is a problem then an {@code Executor} can be given to
199.309 - * the {@code EventClient} constructor to cause the listeners to be called
199.310 - * in a different thread.</p>
199.311 - *
199.312 - * @since 1.7
199.313 - */
199.314 -
199.315 -package javax.management.event;
200.1 --- a/src/share/classes/javax/management/modelmbean/DescriptorSupport.java Mon Nov 23 10:04:47 2009 +0000
200.2 +++ b/src/share/classes/javax/management/modelmbean/DescriptorSupport.java Wed Nov 25 11:08:25 2009 -0800
200.3 @@ -229,10 +229,9 @@
200.4 init(inDescr.descriptorMap);
200.5 }
200.6
200.7 +
200.8 /**
200.9 - * <p>Descriptor constructor taking an XML String or a
200.10 - * <i>fieldName=fieldValue</i> format String. The String parameter is
200.11 - * parsed as XML if it begins with a '<' character.</p>
200.12 + * <p>Descriptor constructor taking an XML String.</p>
200.13 *
200.14 * <p>The format of the XML string is not defined, but an
200.15 * implementation must ensure that the string returned by
200.16 @@ -245,20 +244,17 @@
200.17 * programmer will have to reset or convert these fields
200.18 * correctly.</p>
200.19 *
200.20 - * @param inStr An XML-format or a fieldName=fieldValue formatted string
200.21 - * used to populate this Descriptor. The XML format is not defined, but any
200.22 + * @param inStr An XML-formatted string used to populate this
200.23 + * Descriptor. The format is not defined, but any
200.24 * implementation must ensure that the string returned by
200.25 * method {@link #toXMLString toXMLString} on an existing
200.26 * descriptor can be used to instantiate an equivalent
200.27 * descriptor when instantiated using this constructor.
200.28 *
200.29 - * @exception RuntimeOperationsException If the String inStr passed in
200.30 - * parameter is null or, when it is not an XML string, if the field name or
200.31 - * field value is illegal. If inStr is not an XML string then it must
200.32 - * contain an "=". "fieldValue", "fieldName", and "fieldValue" are illegal.
200.33 - * FieldName cannot be empty. "fieldName=" will cause the value to be empty.
200.34 + * @exception RuntimeOperationsException If the String inStr
200.35 + * passed in parameter is null
200.36 * @exception XMLParseException XML parsing problem while parsing
200.37 - * the XML-format input String
200.38 + * the input String
200.39 * @exception MBeanException Wraps a distributed communication Exception.
200.40 */
200.41 /* At some stage we should rewrite this code to be cleverer. Using
200.42 @@ -287,27 +283,14 @@
200.43 throw new RuntimeOperationsException(iae, msg);
200.44 }
200.45
200.46 - // parse parameter string into structures
200.47 -
200.48 - init(null);
200.49 -
200.50 - if(!inStr.startsWith("<")) {
200.51 - parseNamesValues(inStr);
200.52 - if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) {
200.53 - MODELMBEAN_LOGGER.logp(Level.FINEST,
200.54 - DescriptorSupport.class.getName(),
200.55 - "Descriptor(name=value)", "Exit");
200.56 - }
200.57 - return;
200.58 - }
200.59 -
200.60 final String lowerInStr = inStr.toLowerCase();
200.61 if (!lowerInStr.startsWith("<descriptor>")
200.62 || !lowerInStr.endsWith("</descriptor>")) {
200.63 throw new XMLParseException("No <descriptor>, </descriptor> pair");
200.64 }
200.65
200.66 -
200.67 + // parse xmlstring into structures
200.68 + init(null);
200.69 // create dummy descriptor: should have same size
200.70 // as number of fields in xmlstring
200.71 // loop through structures and put them in descriptor
200.72 @@ -471,16 +454,6 @@
200.73
200.74 init(null);
200.75
200.76 - parseNamesValues(fields);
200.77 -
200.78 - if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) {
200.79 - MODELMBEAN_LOGGER.logp(Level.FINEST,
200.80 - DescriptorSupport.class.getName(),
200.81 - "Descriptor(String... fields)", "Exit");
200.82 - }
200.83 - }
200.84 -
200.85 - private void parseNamesValues(String... fields) {
200.86 for (int i=0; i < fields.length; i++) {
200.87 if ((fields[i] == null) || (fields[i].equals(""))) {
200.88 continue;
200.89 @@ -522,6 +495,11 @@
200.90
200.91 setField(fieldName,fieldValue);
200.92 }
200.93 + if (MODELMBEAN_LOGGER.isLoggable(Level.FINEST)) {
200.94 + MODELMBEAN_LOGGER.logp(Level.FINEST,
200.95 + DescriptorSupport.class.getName(),
200.96 + "Descriptor(String... fields)", "Exit");
200.97 + }
200.98 }
200.99
200.100 private void init(Map<String, ?> initMap) {
201.1 --- a/src/share/classes/javax/management/modelmbean/ModelMBeanAttributeInfo.java Mon Nov 23 10:04:47 2009 +0000
201.2 +++ b/src/share/classes/javax/management/modelmbean/ModelMBeanAttributeInfo.java Wed Nov 25 11:08:25 2009 -0800
201.3 @@ -231,16 +231,14 @@
201.4 * @param descriptor An instance of Descriptor containing the
201.5 * appropriate metadata for this instance of the Attribute. If
201.6 * it is null, then a default descriptor will be created. If
201.7 - * the descriptor does not contain all the following fields,
201.8 - * the missing ones are added with their default values:
201.9 - * displayName, name, descriptorType.
201.10 + * the descriptor does not contain the field "displayName" this field is added
201.11 + * in the descriptor with its default value.
201.12 * @exception IntrospectionException There is a consistency
201.13 * problem in the definition of this attribute.
201.14 * @exception RuntimeOperationsException Wraps an
201.15 - * IllegalArgumentException. The descriptor is invalid, or
201.16 - * descriptor field "name" is present but not equal to name
201.17 - * parameter, or descriptor field "descriptorType" is present
201.18 - * but not equal to "attribute".
201.19 + * IllegalArgumentException. The descriptor is invalid, or descriptor
201.20 + * field "name" is not equal to name parameter, or descriptor field
201.21 + * "descriptorType" is not equal to "attribute".
201.22 *
201.23 */
201.24
201.25 @@ -295,7 +293,7 @@
201.26 }
201.27
201.28 /**
201.29 - * Constructs a ModelMBeanAttributeInfo object with a default descriptor.
201.30 + * Constructs a ModelMBeanAttributeInfo object.
201.31 *
201.32 * @param name The name of the attribute
201.33 * @param type The type or class name of the attribute
201.34 @@ -306,14 +304,12 @@
201.35 * @param descriptor An instance of Descriptor containing the
201.36 * appropriate metadata for this instance of the Attribute. If
201.37 * it is null then a default descriptor will be created. If
201.38 - * the descriptor does not contain all the following fields,
201.39 - * the missing ones are added with their default values:
201.40 - * displayName, name, descriptorType.
201.41 + * the descriptor does not contain the field "displayName" this field
201.42 + * is added in the descriptor with its default value.
201.43 * @exception RuntimeOperationsException Wraps an
201.44 - * IllegalArgumentException. The descriptor is invalid, or
201.45 - * descriptor field "name" is present but not equal to name
201.46 - * parameter, or descriptor field "descriptorType" is present
201.47 - * but not equal to "attribute".
201.48 + * IllegalArgumentException. The descriptor is invalid, or descriptor
201.49 + * field "name" is not equal to name parameter, or descriptor field
201.50 + * "descriptorType" is not equal to "attribute".
201.51 *
201.52 */
201.53 public ModelMBeanAttributeInfo(String name,
201.54 @@ -392,9 +388,6 @@
201.55 * assigned. If the new Descriptor is invalid, then a
201.56 * RuntimeOperationsException wrapping an
201.57 * IllegalArgumentException is thrown.
201.58 - * If the descriptor does not contain all the following fields, the
201.59 - * missing ones are added with
201.60 - * their default values: displayName, name, descriptorType.
201.61 * @param inDescriptor replaces the Descriptor associated with the
201.62 * ModelMBeanAttributeInfo
201.63 *
201.64 @@ -415,6 +408,7 @@
201.65 * fails for any reason, this exception will be thrown.
201.66 */
201.67
201.68 + @Override
201.69 public Object clone()
201.70 {
201.71 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
201.72 @@ -429,6 +423,7 @@
201.73 * Returns a human-readable version of the
201.74 * ModelMBeanAttributeInfo instance.
201.75 */
201.76 + @Override
201.77 public String toString()
201.78 {
201.79 return
201.80 @@ -456,7 +451,8 @@
201.81 private Descriptor validDescriptor(final Descriptor in) throws RuntimeOperationsException {
201.82
201.83 Descriptor clone;
201.84 - if (in == null) {
201.85 + boolean defaulted = (in == null);
201.86 + if (defaulted) {
201.87 clone = new DescriptorSupport();
201.88 MODELMBEAN_LOGGER.finer("Null Descriptor, creating new.");
201.89 } else {
201.90 @@ -464,11 +460,11 @@
201.91 }
201.92
201.93 //Setting defaults.
201.94 - if (clone.getFieldValue("name")==null) {
201.95 + if (defaulted && clone.getFieldValue("name")==null) {
201.96 clone.setField("name", this.getName());
201.97 MODELMBEAN_LOGGER.finer("Defaulting Descriptor name to " + this.getName());
201.98 }
201.99 - if (clone.getFieldValue("descriptorType")==null) {
201.100 + if (defaulted && clone.getFieldValue("descriptorType")==null) {
201.101 clone.setField("descriptorType", "attribute");
201.102 MODELMBEAN_LOGGER.finer("Defaulting descriptorType to \"attribute\"");
201.103 }
201.104 @@ -483,13 +479,13 @@
201.105 "The isValid() method of the Descriptor object itself returned false,"+
201.106 "one or more required fields are invalid. Descriptor:" + clone.toString());
201.107 }
201.108 - if (! ((String)clone.getFieldValue("name")).equalsIgnoreCase(this.getName())) {
201.109 + if (!getName().equalsIgnoreCase((String)clone.getFieldValue("name"))) {
201.110 throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"),
201.111 "The Descriptor \"name\" field does not match the object described. " +
201.112 " Expected: "+ this.getName() + " , was: " + clone.getFieldValue("name"));
201.113 }
201.114
201.115 - if (! ((String)clone.getFieldValue("descriptorType")).equalsIgnoreCase("attribute")) {
201.116 + if (!"attribute".equalsIgnoreCase((String)clone.getFieldValue("descriptorType"))) {
201.117 throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"),
201.118 "The Descriptor \"descriptorType\" field does not match the object described. " +
201.119 " Expected: \"attribute\" ," + " was: " + clone.getFieldValue("descriptorType"));
202.1 --- a/src/share/classes/javax/management/modelmbean/ModelMBeanConstructorInfo.java Mon Nov 23 10:04:47 2009 +0000
202.2 +++ b/src/share/classes/javax/management/modelmbean/ModelMBeanConstructorInfo.java Wed Nov 25 11:08:25 2009 -0800
202.3 @@ -78,9 +78,7 @@
202.4 * are meaningless for constructors, but are not considered invalid.</p>
202.5 *
202.6 * <p>The default descriptor will have the {@code name}, {@code
202.7 - * descriptorType}, {@code displayName} and {@code role} fields. The
202.8 - * default value of the {@code name} and {@code displayName} fields is
202.9 - * the name of the constructor.
202.10 + * descriptorType}, {@code displayName} and {@code role} fields.
202.11 *
202.12 * <p>The <b>serialVersionUID</b> of this class is <code>3862947819818064362L</code>.
202.13 *
202.14 @@ -193,14 +191,14 @@
202.15 * appropriate metadata for this instance of the
202.16 * ModelMBeanConstructorInfo. If it is null, then a default
202.17 * descriptor will be created. If the descriptor does not
202.18 - * contain all the following fields, the missing ones are added with
202.19 - * their default values: displayName, name, role, descriptorType.
202.20 + * contain the field "displayName" this field is added in the
202.21 + * descriptor with its default value.
202.22 *
202.23 * @exception RuntimeOperationsException Wraps an
202.24 * IllegalArgumentException. The descriptor is invalid, or
202.25 - * descriptor field "name" is present but not equal to name
202.26 - * parameter, or descriptor field "descriptorType" is present
202.27 - * but not equal to "operation" or descriptor field "role" is
202.28 + * descriptor field "name" is not equal to name
202.29 + * parameter, or descriptor field "descriptorType" is
202.30 + * not equal to "operation" or descriptor field "role" is
202.31 * present but not equal to "constructor".
202.32 */
202.33
202.34 @@ -250,15 +248,14 @@
202.35 * @param signature MBeanParameterInfo objects describing the parameters(arguments) of the constructor.
202.36 * @param descriptor An instance of Descriptor containing the appropriate metadata
202.37 * for this instance of the MBeanConstructorInfo. If it is null then a default descriptor will be created.
202.38 - * If the descriptor does not
202.39 - * contain all the following fields, the missing ones are added with
202.40 - * their default values: displayName, name, role, descriptorType.
202.41 + * If the descriptor does not contain the field "displayName" this field
202.42 + * is added in the descriptor with its default value.
202.43 *
202.44 * @exception RuntimeOperationsException Wraps an
202.45 * IllegalArgumentException. The descriptor is invalid, or
202.46 - * descriptor field "name" is present but not equal to name
202.47 - * parameter, or descriptor field "descriptorType" is present
202.48 - * but not equal to "operation" or descriptor field "role" is
202.49 + * descriptor field "name" is not equal to name
202.50 + * parameter, or descriptor field "descriptorType" is
202.51 + * not equal to "operation" or descriptor field "role" is
202.52 * present but not equal to "constructor".
202.53 */
202.54
202.55 @@ -300,6 +297,7 @@
202.56 * Creates and returns a new ModelMBeanConstructorInfo which is a duplicate of this ModelMBeanConstructorInfo.
202.57 *
202.58 */
202.59 + @Override
202.60 public Object clone ()
202.61 {
202.62 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
202.63 @@ -320,6 +318,7 @@
202.64 */
202.65
202.66
202.67 + @Override
202.68 public Descriptor getDescriptor()
202.69 {
202.70 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
202.71 @@ -368,6 +367,7 @@
202.72 /**
202.73 * Returns a string containing the entire contents of the ModelMBeanConstructorInfo in human readable form.
202.74 */
202.75 + @Override
202.76 public String toString()
202.77 {
202.78 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
202.79 @@ -404,8 +404,9 @@
202.80 * @exception RuntimeOperationsException if Descriptor is invalid
202.81 */
202.82 private Descriptor validDescriptor(final Descriptor in) throws RuntimeOperationsException {
202.83 - Descriptor clone;
202.84 - if (in == null) {
202.85 + Descriptor clone;
202.86 + boolean defaulted = (in == null);
202.87 + if (defaulted) {
202.88 clone = new DescriptorSupport();
202.89 MODELMBEAN_LOGGER.finer("Null Descriptor, creating new.");
202.90 } else {
202.91 @@ -413,11 +414,11 @@
202.92 }
202.93
202.94 //Setting defaults.
202.95 - if (clone.getFieldValue("name")==null) {
202.96 + if (defaulted && clone.getFieldValue("name")==null) {
202.97 clone.setField("name", this.getName());
202.98 MODELMBEAN_LOGGER.finer("Defaulting Descriptor name to " + this.getName());
202.99 }
202.100 - if (clone.getFieldValue("descriptorType")==null) {
202.101 + if (defaulted && clone.getFieldValue("descriptorType")==null) {
202.102 clone.setField("descriptorType", "operation");
202.103 MODELMBEAN_LOGGER.finer("Defaulting descriptorType to \"operation\"");
202.104 }
202.105 @@ -436,12 +437,12 @@
202.106 "The isValid() method of the Descriptor object itself returned false,"+
202.107 "one or more required fields are invalid. Descriptor:" + clone.toString());
202.108 }
202.109 - if (! ((String)clone.getFieldValue("name")).equalsIgnoreCase(this.getName())) {
202.110 + if (!getName().equalsIgnoreCase((String) clone.getFieldValue("name"))) {
202.111 throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"),
202.112 "The Descriptor \"name\" field does not match the object described. " +
202.113 " Expected: "+ this.getName() + " , was: " + clone.getFieldValue("name"));
202.114 }
202.115 - if (! ((String)clone.getFieldValue("descriptorType")).equalsIgnoreCase("operation")) {
202.116 + if (!"operation".equalsIgnoreCase((String) clone.getFieldValue("descriptorType"))) {
202.117 throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"),
202.118 "The Descriptor \"descriptorType\" field does not match the object described. " +
202.119 " Expected: \"operation\" ," + " was: " + clone.getFieldValue("descriptorType"));
203.1 --- a/src/share/classes/javax/management/modelmbean/ModelMBeanInfoSupport.java Mon Nov 23 10:04:47 2009 +0000
203.2 +++ b/src/share/classes/javax/management/modelmbean/ModelMBeanInfoSupport.java Wed Nov 25 11:08:25 2009 -0800
203.3 @@ -945,7 +945,8 @@
203.4 */
203.5 private Descriptor validDescriptor(final Descriptor in) throws RuntimeOperationsException {
203.6 Descriptor clone;
203.7 - if (in == null) {
203.8 + boolean defaulted = (in == null);
203.9 + if (defaulted) {
203.10 clone = new DescriptorSupport();
203.11 MODELMBEAN_LOGGER.finer("Null Descriptor, creating new.");
203.12 } else {
203.13 @@ -953,11 +954,11 @@
203.14 }
203.15
203.16 //Setting defaults.
203.17 - if (clone.getFieldValue("name")==null) {
203.18 + if (defaulted && clone.getFieldValue("name")==null) {
203.19 clone.setField("name", this.getClassName());
203.20 MODELMBEAN_LOGGER.finer("Defaulting Descriptor name to " + this.getClassName());
203.21 }
203.22 - if (clone.getFieldValue("descriptorType")==null) {
203.23 + if (defaulted && clone.getFieldValue("descriptorType")==null) {
203.24 clone.setField("descriptorType", MMB);
203.25 MODELMBEAN_LOGGER.finer("Defaulting descriptorType to \"" + MMB + "\"");
203.26 }
204.1 --- a/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java Mon Nov 23 10:04:47 2009 +0000
204.2 +++ b/src/share/classes/javax/management/modelmbean/ModelMBeanNotificationInfo.java Wed Nov 25 11:08:25 2009 -0800
204.3 @@ -186,14 +186,14 @@
204.4 * @param descriptor An instance of Descriptor containing the
204.5 * appropriate metadata for this instance of the
204.6 * MBeanNotificationInfo. If it is null a default descriptor
204.7 - * will be created. If the descriptor does not contain all the
204.8 - * fields "name", "descriptorType", "displayName" and "severity",
204.9 + * will be created. If the descriptor does not contain the
204.10 + * fields "displayName" or "severity",
204.11 * the missing ones are added with their default values.
204.12 *
204.13 * @exception RuntimeOperationsException Wraps an
204.14 * {@link IllegalArgumentException}. The descriptor is invalid, or
204.15 - * descriptor field "name" is present but not equal to parameter name, or
204.16 - * descriptor field "descriptorType" is present but not equal to "notification".
204.17 + * descriptor field "name" is not equal to parameter name, or
204.18 + * descriptor field "descriptorType" is not equal to "notification".
204.19 *
204.20 **/
204.21 public ModelMBeanNotificationInfo(String[] notifTypes,
204.22 @@ -341,7 +341,8 @@
204.23 */
204.24 private Descriptor validDescriptor(final Descriptor in) throws RuntimeOperationsException {
204.25 Descriptor clone;
204.26 - if (in == null) {
204.27 + boolean defaulted = (in == null);
204.28 + if (defaulted) {
204.29 clone = new DescriptorSupport();
204.30 MODELMBEAN_LOGGER.finer("Null Descriptor, creating new.");
204.31 } else {
204.32 @@ -349,11 +350,11 @@
204.33 }
204.34
204.35 //Setting defaults.
204.36 - if (clone.getFieldValue("name")==null) {
204.37 + if (defaulted && clone.getFieldValue("name")==null) {
204.38 clone.setField("name", this.getName());
204.39 MODELMBEAN_LOGGER.finer("Defaulting Descriptor name to " + this.getName());
204.40 }
204.41 - if (clone.getFieldValue("descriptorType")==null) {
204.42 + if (defaulted && clone.getFieldValue("descriptorType")==null) {
204.43 clone.setField("descriptorType", "notification");
204.44 MODELMBEAN_LOGGER.finer("Defaulting descriptorType to \"notification\"");
204.45 }
204.46 @@ -372,12 +373,12 @@
204.47 "The isValid() method of the Descriptor object itself returned false,"+
204.48 "one or more required fields are invalid. Descriptor:" + clone.toString());
204.49 }
204.50 - if (! ((String)clone.getFieldValue("name")).equalsIgnoreCase(this.getName())) {
204.51 + if (!getName().equalsIgnoreCase((String) clone.getFieldValue("name"))) {
204.52 throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"),
204.53 "The Descriptor \"name\" field does not match the object described. " +
204.54 " Expected: "+ this.getName() + " , was: " + clone.getFieldValue("name"));
204.55 }
204.56 - if (! ((String)clone.getFieldValue("descriptorType")).equalsIgnoreCase("notification")) {
204.57 + if (!"notification".equalsIgnoreCase((String) clone.getFieldValue("descriptorType"))) {
204.58 throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"),
204.59 "The Descriptor \"descriptorType\" field does not match the object described. " +
204.60 " Expected: \"notification\" ," + " was: " + clone.getFieldValue("descriptorType"));
205.1 --- a/src/share/classes/javax/management/modelmbean/ModelMBeanOperationInfo.java Mon Nov 23 10:04:47 2009 +0000
205.2 +++ b/src/share/classes/javax/management/modelmbean/ModelMBeanOperationInfo.java Wed Nov 25 11:08:25 2009 -0800
205.3 @@ -208,16 +208,16 @@
205.4 * appropriate metadata for this instance of the
205.5 * ModelMBeanOperationInfo. If it is null a default
205.6 * descriptor will be created. If the descriptor does not
205.7 - * contain all the fields "name", "descriptorType",
205.8 - * "displayName", and "role", the missing ones are added with
205.9 + * contain the fields
205.10 + * "displayName" or "role", the missing ones are added with
205.11 * their default values.
205.12 *
205.13 * @exception RuntimeOperationsException Wraps an
205.14 * IllegalArgumentException. The descriptor is invalid; or
205.15 - * descriptor field "name" is present but not equal to
205.16 + * descriptor field "name" is not equal to
205.17 * operation name; or descriptor field "DescriptorType" is
205.18 - * present but not equal to "operation"; or descriptor
205.19 - * optional field "role" is not equal to "operation",
205.20 + * not equal to "operation"; or descriptor
205.21 + * optional field "role" is present but not equal to "operation",
205.22 * "getter", or "setter".
205.23 *
205.24 */
205.25 @@ -281,16 +281,16 @@
205.26 * @param descriptor An instance of Descriptor containing the
205.27 * appropriate metadata for this instance of the
205.28 * MBeanOperationInfo. If it is null then a default descriptor
205.29 - * will be created. If the descriptor does not contain all the
205.30 - * fields "name", "descriptorType", "displayName", and "role",
205.31 + * will be created. If the descriptor does not contain
205.32 + * fields "displayName" or "role",
205.33 * the missing ones are added with their default values.
205.34 *
205.35 * @exception RuntimeOperationsException Wraps an
205.36 * IllegalArgumentException. The descriptor is invalid; or
205.37 - * descriptor field "name" is present but not equal to
205.38 + * descriptor field "name" is not equal to
205.39 * operation name; or descriptor field "DescriptorType" is
205.40 - * present but not equal to "operation"; or descriptor optional
205.41 - * field "role" is not equal to "operation", "getter", or
205.42 + * not equal to "operation"; or descriptor optional
205.43 + * field "role" is present but not equal to "operation", "getter", or
205.44 * "setter".
205.45 */
205.46
205.47 @@ -446,7 +446,8 @@
205.48 private Descriptor validDescriptor(final Descriptor in)
205.49 throws RuntimeOperationsException {
205.50 Descriptor clone;
205.51 - if (in == null) {
205.52 + boolean defaulted = (in == null);
205.53 + if (defaulted) {
205.54 clone = new DescriptorSupport();
205.55 MODELMBEAN_LOGGER.finer("Null Descriptor, creating new.");
205.56 } else {
205.57 @@ -454,11 +455,11 @@
205.58 }
205.59
205.60 //Setting defaults.
205.61 - if (clone.getFieldValue("name")==null) {
205.62 + if (defaulted && clone.getFieldValue("name")==null) {
205.63 clone.setField("name", this.getName());
205.64 MODELMBEAN_LOGGER.finer("Defaulting Descriptor name to " + this.getName());
205.65 }
205.66 - if (clone.getFieldValue("descriptorType")==null) {
205.67 + if (defaulted && clone.getFieldValue("descriptorType")==null) {
205.68 clone.setField("descriptorType", "operation");
205.69 MODELMBEAN_LOGGER.finer("Defaulting descriptorType to \"operation\"");
205.70 }
205.71 @@ -477,15 +478,15 @@
205.72 "The isValid() method of the Descriptor object itself returned false,"+
205.73 "one or more required fields are invalid. Descriptor:" + clone.toString());
205.74 }
205.75 - if (! ((String)clone.getFieldValue("name")).equalsIgnoreCase(this.getName())) {
205.76 + if (!getName().equalsIgnoreCase((String) clone.getFieldValue("name"))) {
205.77 throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"),
205.78 "The Descriptor \"name\" field does not match the object described. " +
205.79 " Expected: "+ this.getName() + " , was: " + clone.getFieldValue("name"));
205.80 }
205.81 - if (! ((String)clone.getFieldValue("descriptorType")).equalsIgnoreCase("operation")) {
205.82 + if (!"operation".equalsIgnoreCase((String) clone.getFieldValue("descriptorType"))) {
205.83 throw new RuntimeOperationsException(new IllegalArgumentException("Invalid Descriptor argument"),
205.84 "The Descriptor \"descriptorType\" field does not match the object described. " +
205.85 - " Expected: \"attribute\" ," + " was: " + clone.getFieldValue("descriptorType"));
205.86 + " Expected: \"operation\" ," + " was: " + clone.getFieldValue("descriptorType"));
205.87 }
205.88 final String role = (String)clone.getFieldValue("role");
205.89 if (!(role.equalsIgnoreCase("operation") ||
206.1 --- a/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java Mon Nov 23 10:04:47 2009 +0000
206.2 +++ b/src/share/classes/javax/management/modelmbean/RequiredModelMBean.java Wed Nov 25 11:08:25 2009 -0800
206.3 @@ -23,7 +23,7 @@
206.4 * have any questions.
206.5 */
206.6 /*
206.7 - * @(#)author IBM Corp.
206.8 + * @author IBM Corp.
206.9 *
206.10 * Copyright IBM Corp. 1999-2000. All rights reserved.
206.11 */
206.12 @@ -55,7 +55,6 @@
206.13 import javax.management.AttributeList;
206.14 import javax.management.AttributeNotFoundException;
206.15 import javax.management.Descriptor;
206.16 -import javax.management.DynamicWrapperMBean;
206.17 import javax.management.InstanceNotFoundException;
206.18 import javax.management.InvalidAttributeValueException;
206.19 import javax.management.ListenerNotFoundException;
206.20 @@ -116,7 +115,7 @@
206.21 */
206.22
206.23 public class RequiredModelMBean
206.24 - implements ModelMBean, MBeanRegistration, NotificationEmitter, DynamicWrapperMBean {
206.25 + implements ModelMBean, MBeanRegistration, NotificationEmitter {
206.26
206.27 /*************************************/
206.28 /* attributes */
206.29 @@ -134,8 +133,6 @@
206.30 * and operations will be executed */
206.31 private Object managedResource = null;
206.32
206.33 - /* true if getWrappedObject returns the wrapped resource */
206.34 - private boolean visible;
206.35
206.36 /* records the registering in MBeanServer */
206.37 private boolean registered = false;
206.38 @@ -322,13 +319,9 @@
206.39 *
206.40 * @param mr Object that is the managed resource
206.41 * @param mr_type The type of reference for the managed resource.
206.42 - * <br>Can be: "ObjectReference", "VisibleObjectReference",
206.43 - * "Handle", "IOR", "EJBHandle", or "RMIReference".
206.44 - * <br>In this implementation only "ObjectReference" and
206.45 - * "VisibleObjectReference" are supported. The two
206.46 - * types are equivalent except for the behavior of the
206.47 - * {@link #getWrappedObject()} and {@link #getWrappedClassLoader()}
206.48 - * methods.
206.49 + * <br>Can be: "ObjectReference", "Handle", "IOR", "EJBHandle",
206.50 + * or "RMIReference".
206.51 + * <br>In this implementation only "ObjectReference" is supported.
206.52 *
206.53 * @exception MBeanException The initializer of the object has
206.54 * thrown an exception.
206.55 @@ -348,11 +341,10 @@
206.56 "setManagedResource(Object,String)","Entry");
206.57 }
206.58
206.59 - visible = "visibleObjectReference".equalsIgnoreCase(mr_type);
206.60 -
206.61 // check that the mr_type is supported by this JMXAgent
206.62 // only "objectReference" is supported
206.63 - if (!"objectReference".equalsIgnoreCase(mr_type) && !visible) {
206.64 + if ((mr_type == null) ||
206.65 + (! mr_type.equalsIgnoreCase("objectReference"))) {
206.66 if (MODELMBEAN_LOGGER.isLoggable(Level.FINER)) {
206.67 MODELMBEAN_LOGGER.logp(Level.FINER,
206.68 RequiredModelMBean.class.getName(),
206.69 @@ -378,51 +370,6 @@
206.70 }
206.71
206.72 /**
206.73 - * <p>Get the managed resource for this Model MBean. For compatibility
206.74 - * reasons, the managed resource is only returned if the resource type
206.75 - * specified to {@link #setManagedResource setManagedResource} was {@code
206.76 - * "visibleObjectReference"}. Otherwise, {@code this} is returned.</p>
206.77 - *
206.78 - * @return The value that was specified to {@link #setManagedResource
206.79 - * setManagedResource}, if the resource type is {@code
206.80 - * "visibleObjectReference"}. Otherwise, {@code this}.
206.81 - */
206.82 - public Object getWrappedObject() {
206.83 - if (visible)
206.84 - return managedResource;
206.85 - else
206.86 - return this;
206.87 - }
206.88 -
206.89 - /**
206.90 - * <p>Get the ClassLoader of the managed resource for this Model MBean. For
206.91 - * compatibility reasons, the ClassLoader of the managed resource is only
206.92 - * returned if the resource type specified to {@link #setManagedResource
206.93 - * setManagedResource} was {@code "visibleObjectReference"}. Otherwise,
206.94 - * {@code this.getClass().getClassLoader()} is returned.</p>
206.95 - *
206.96 - * @return The ClassLoader of the value that was specified to
206.97 - * {@link #setManagedResource setManagedResource}, if the resource
206.98 - * type is {@code "visibleObjectReference"}. Otherwise, {@code
206.99 - * this.getClass().getClassLoader()}.
206.100 - */
206.101 - public ClassLoader getWrappedClassLoader() {
206.102 - return getWrappedObject().getClass().getClassLoader();
206.103 - }
206.104 -
206.105 - private static boolean isTrue(Descriptor d, String field) {
206.106 - if (d == null)
206.107 - return false;
206.108 - Object x = d.getFieldValue(field);
206.109 - if (x instanceof Boolean)
206.110 - return (Boolean) x;
206.111 - if (!(x instanceof String))
206.112 - return false;
206.113 - String s = (String) x;
206.114 - return ("true".equalsIgnoreCase(s) || "T".equalsIgnoreCase(s));
206.115 - }
206.116 -
206.117 - /**
206.118 * <p>Instantiates this MBean instance with the data found for
206.119 * the MBean in the persistent store. The data loaded could include
206.120 * attribute and operation values.</p>
207.1 --- a/src/share/classes/javax/management/monitor/MonitorNotification.java Mon Nov 23 10:04:47 2009 +0000
207.2 +++ b/src/share/classes/javax/management/monitor/MonitorNotification.java Wed Nov 25 11:08:25 2009 -0800
207.3 @@ -201,7 +201,7 @@
207.4 * @param derGauge The derived gauge.
207.5 * @param trigger The threshold/string (depending on the monitor type) that triggered the notification.
207.6 */
207.7 - public MonitorNotification(String type, Object source, long sequenceNumber, long timeStamp, String msg,
207.8 + MonitorNotification(String type, Object source, long sequenceNumber, long timeStamp, String msg,
207.9 ObjectName obsObj, String obsAtt, Object derGauge, Object trigger) {
207.10
207.11 super(type, source, sequenceNumber, timeStamp, msg);
208.1 --- a/src/share/classes/javax/management/namespace/JMXDomain.java Mon Nov 23 10:04:47 2009 +0000
208.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
208.3 @@ -1,378 +0,0 @@
208.4 -/*
208.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
208.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
208.7 - *
208.8 - * This code is free software; you can redistribute it and/or modify it
208.9 - * under the terms of the GNU General Public License version 2 only, as
208.10 - * published by the Free Software Foundation. Sun designates this
208.11 - * particular file as subject to the "Classpath" exception as provided
208.12 - * by Sun in the LICENSE file that accompanied this code.
208.13 - *
208.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
208.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
208.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
208.17 - * version 2 for more details (a copy is included in the LICENSE file that
208.18 - * accompanied this code).
208.19 - *
208.20 - * You should have received a copy of the GNU General Public License version
208.21 - * 2 along with this work; if not, write to the Free Software Foundation,
208.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
208.23 - *
208.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
208.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
208.26 - * have any questions.
208.27 - */
208.28 -
208.29 -package javax.management.namespace;
208.30 -
208.31 -import java.io.IOException;
208.32 -import javax.management.ListenerNotFoundException;
208.33 -import javax.management.NotificationFilter;
208.34 -import javax.management.NotificationListener;
208.35 -import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR;
208.36 -
208.37 -
208.38 -import javax.management.InstanceNotFoundException;
208.39 -import javax.management.MBeanServer;
208.40 -import javax.management.MBeanServerDelegate;
208.41 -import javax.management.ObjectName;
208.42 -
208.43 -/**
208.44 - * A special {@link JMXNamespace} that can handle part of
208.45 - * the MBeanServer local name space.
208.46 - * <p>
208.47 - * A {@code JMXDomain} makes a domain <i>X</i> of a
208.48 - * {@linkplain #getSourceServer() source MBean server} appear in the same domain
208.49 - * <i>X</i> of a containing {@code MBeanServer} in which the
208.50 - * {@code JMXDomain} MBean {@linkplain #getMBeanServer() is registered}.
208.51 - * </p>
208.52 - * <p>
208.53 - * The JMX infrastructure of the containing {@code MBeanServer} takes care of
208.54 - * routing all calls to MBeans whose names have domain <i>X</i> to the
208.55 - * {@linkplain #getSourceServer() source MBean server} exported by the
208.56 - * {@code JMXDomain} MBean in charge of domain <i>X</i>.
208.57 - * </p>
208.58 - * <p>
208.59 - * The {@linkplain #getSourceServer() source MBean server} of a {@code JMXDomain}
208.60 - * can, but need not be a regular {@code MBeanServer} created through
208.61 - * the {@link javax.management.MBeanServerFactory}. It could also be,
208.62 - * for instance, an instance of a subclass of {@link MBeanServerSupport},
208.63 - * or a custom object implementing the {@link MBeanServer} interface.
208.64 - * </p>
208.65 - *
208.66 - * <h4>Differences between {@code JMXNamespace} and {@code JMXDomain}</h4>
208.67 - *
208.68 - * <p>
208.69 - * A {@code JMXDomain} is a special kind of {@code JMXNamespace}.
208.70 - * A {@code JMXNamespace} such as {@code foo//} is triggered by an
208.71 - * {@code ObjectName} that begins with the string {@code foo//}, for example
208.72 - * {@code foo//bar:type=Baz}. A {@code JMXDomain} such as {@code foo} is
208.73 - * triggered by an {@code ObjectName} with that exact domain, for example
208.74 - * {@code foo:type=Baz}. A client can immediately see that an MBean is
208.75 - * handled by a {@code JMXNamespace} because of the {@code //} in the name.
208.76 - * A client cannot see whether a name such as {@code foo:type=Baz} is an
208.77 - * ordinary MBean or is handled by a {@code JMXDomain}.
208.78 - * </p>
208.79 - *
208.80 - * <p>
208.81 - * A {@linkplain MBeanServer#queryNames query} on the containing {@code
208.82 - * MBeanserver} will return all MBeans from the {@code JMXDomain} that match
208.83 - * the query. In particular, {@code queryNames(null, null)} will return all
208.84 - * MBeans including those from {@code JMXDomain} domains. On the other hand,
208.85 - * a query will not include MBeans from a {@code JMXNamespace} unless the
208.86 - * {@code ObjectName} pattern in the query starts with the name of that
208.87 - * namespace.
208.88 - * </p>
208.89 - *
208.90 - * <h4 id="security">Permission checks</h4>
208.91 - *
208.92 - * <p>
208.93 - * When a JMXDomain MBean is registered in a containing
208.94 - * MBean server created through the default {@link
208.95 - * javax.management.MBeanServerBuilder}, and if a {@link
208.96 - * SecurityManager SecurityManager} is
208.97 - * {@linkplain System#getSecurityManager() present}, the containing MBeanServer will
208.98 - * check an {@link javax.management.MBeanPermission} before invoking
208.99 - * any method on the {@linkplain #getSourceServer() source MBeanServer} of the
208.100 - * JMXDomain.
208.101 - * </p>
208.102 - *
208.103 - * <p>First, if there is no security manager ({@link
208.104 - * System#getSecurityManager()} is null), that containing
208.105 - * {@code MBeanServer} is free not to make any checks.
208.106 - * </p>
208.107 - *
208.108 - * <p>
208.109 - * Assuming that there is a security manager, or that the
208.110 - * implementation chooses to make checks anyway, the containing
208.111 - * {@code MBeanServer} will perform
208.112 - * {@link javax.management.MBeanPermission MBeanPermission} checks
208.113 - * for access to the MBeans in domain <i>X</i> handled by a {@code JMXDomain}
208.114 - * in the same way that it would do for MBeans registered in its own local
208.115 - * repository, and as <a href="../MBeanServer.html#security">described in
208.116 - * the MBeanServer interface</a>, with the following exceptions:
208.117 - * </p>
208.118 - *
208.119 - * <p>
208.120 - * For those permissions that require a {@code className}, the
208.121 - * <code>className</code> is the
208.122 - * string returned by {@link #getSourceServer() getSourceServer()}.
208.123 - * {@link MBeanServer#getObjectInstance(ObjectName)
208.124 - * getObjectInstance(mbeanName)}.
208.125 - * {@link javax.management.ObjectInstance#getClassName() getClassName()},
208.126 - * except for {@code createMBean} and {@code registerMBean} operations,
208.127 - * for which the permission checks are performed as follows:
208.128 - * </p>
208.129 - * <ul>
208.130 - * <li><p>For {@code createMBean} operations, the {@code className} of the
208.131 - * permission you need is the {@code className} passed as first parameter
208.132 - * to {@code createMBean}.</p>
208.133 - *
208.134 - * <li><p>For {@code registerMBean} operations, the {@code className} of the
208.135 - * permission you need is the name of the class of the mbean object, as
208.136 - * returned by {@code mbean.getClass().getClassName()}, where
208.137 - * {@code mbean} is the mbean reference passed as first parameter
208.138 - * to {@code registerMBean}.</p>
208.139 - *
208.140 - * <li><p>In addition, for {@code createMBean} and {@code registerMBean}, the
208.141 - * permission you need is checked with the {@linkplain ObjectName object name} of
208.142 - * the mbean that is passed as second parameter to the {@code createMBean} or
208.143 - * {@code registerMBean} operation.
208.144 - * </p>
208.145 - *
208.146 - * <li><p>Contrarily to what is done for regular MBeans registered in the
208.147 - * MBeanServer local repository, the containing MBeanServer will not
208.148 - * check the {@link javax.management.MBeanTrustPermission#MBeanTrustPermission(String)
208.149 - * MBeanTrustPermission("register")} against the protection domain
208.150 - * of the MBean's class. This check can be performed by the
208.151 - * {@linkplain #getSourceServer source MBean server} implementation,
208.152 - * if necessary.
208.153 - * </p>
208.154 - * </ul>
208.155 - *
208.156 - * <p>If a security check fails, the method throws {@link
208.157 - * SecurityException}.</p>
208.158 - *
208.159 - * <p>For methods that can throw {@link InstanceNotFoundException},
208.160 - * this exception is thrown for a non-existent MBean, regardless of
208.161 - * permissions. This is because a non-existent MBean has no
208.162 - * <code>className</code>.</p>
208.163 - *
208.164 - * All these checks are performed by the containing {@code MBeanServer},
208.165 - * before accessing the JMXDomain {@linkplain #getSourceServer source MBean server}.
208.166 - * The implementation of the JMXDomain {@linkplain #getSourceServer source MBean
208.167 - * server} is free to make any additional checks. In fact, if the JMXDomain
208.168 - * {@linkplain #getSourceServer source MBean server} is an {@code MBeanServer}
208.169 - * obtained through the {@link javax.management.MBeanServerFactory}, it will
208.170 - * again make permission checks as described in the
208.171 - * <a href="../MBeanServer.html#security">MBeanServer</a> interface.
208.172 - *
208.173 - * <p>See the <a href="../MBeanServer.html#security">MBeanServer</a> interface
208.174 - * for more details on permission checks.</p>
208.175 - *
208.176 - * @since 1.7
208.177 - */
208.178 -public class JMXDomain extends JMXNamespace {
208.179 -
208.180 -
208.181 - /**
208.182 - * This constant contains the value of the {@code type}
208.183 - * key used in defining a standard JMXDomain MBean object name.
208.184 - * By definition, a standard JMXDomain MBean object name must be of
208.185 - * the form:
208.186 - * <pre>
208.187 - * {@code "<domain>:"}+{@value javax.management.namespace.JMXDomain#TYPE_ASSIGNMENT}
208.188 - * </pre>
208.189 - */
208.190 - public static final String TYPE = "JMXDomain";
208.191 -
208.192 - /**
208.193 - * This constant contains the value of the standard
208.194 - * {@linkplain javax.management.ObjectName#getKeyPropertyListString() key
208.195 - * property list string} for JMXDomain MBean object names.
208.196 - * By definition, a standard JMXDomain MBean object name must be of
208.197 - * the form:
208.198 - * <pre>
208.199 - * {@code <domain>}+":"+{@value javax.management.namespace.JMXDomain#TYPE_ASSIGNMENT}
208.200 - * </pre>
208.201 - */
208.202 - public static final String TYPE_ASSIGNMENT = "type="+TYPE;
208.203 -
208.204 -
208.205 -
208.206 - /**
208.207 - * Creates a new instance of JMXDomain. The MBeans contained in this
208.208 - * domain are handled by the {@code virtualServer} object given to
208.209 - * this constructor. Frequently, this will be an instance of
208.210 - * {@link MBeanServerSupport}.
208.211 - * @param virtualServer The virtual server that acts as a container for
208.212 - * the MBeans handled by this JMXDomain object. Frequently, this will
208.213 - * be an instance of {@link MBeanServerSupport}
208.214 - * @see JMXNamespace#JMXNamespace(MBeanServer)
208.215 - */
208.216 - public JMXDomain(MBeanServer virtualServer) {
208.217 - super(virtualServer);
208.218 - }
208.219 -
208.220 - /**
208.221 - * Return the name of domain handled by this JMXDomain.
208.222 - * @return the domain handled by this JMXDomain.
208.223 - * @throws IOException - if the domain cannot be determined,
208.224 - * for instance, if the MBean is not registered yet.
208.225 - */
208.226 - @Override
208.227 - public final String getDefaultDomain() {
208.228 - final ObjectName name = getObjectName();
208.229 - if (name == null)
208.230 - throw new IllegalStateException("DefaultDomain is not yet known");
208.231 - final String dom = name.getDomain();
208.232 - return dom;
208.233 - }
208.234 -
208.235 - /**
208.236 - * Returns a singleton array, containing the only domain handled by
208.237 - * this JMXDomain object. This is
208.238 - * {@code new String[] {getDefaultDomain()}}.
208.239 - * @return the only domain handled by this JMXDomain.
208.240 - * @throws IOException if the domain cannot be determined,
208.241 - * for instance, if the MBean is not registered yet.
208.242 - * @see #getDefaultDomain()
208.243 - */
208.244 - @Override
208.245 - public final String[] getDomains() {
208.246 - return new String[] {getDefaultDomain()};
208.247 - }
208.248 -
208.249 - /**
208.250 - * This method returns the number of MBeans in the domain handled
208.251 - * by this JMXDomain object. The default implementation is:
208.252 - * <pre>
208.253 - * getSourceServer().queryNames(
208.254 - * new ObjectName(getObjectName().getDomain()+":*"), null).size();
208.255 - * </pre>
208.256 - * If this JMXDomain is not yet registered, this method returns 0.
208.257 - * Subclasses can override the above behavior and provide a better
208.258 - * implementation.
208.259 - * <p>
208.260 - * The getMBeanCount() method is called when computing the number
208.261 - * of MBeans in the {@linkplain #getMBeanServer() containing MBeanServer}.
208.262 - * @return the number of MBeans in this domain, or 0.
208.263 - */
208.264 - @Override
208.265 - public Integer getMBeanCount() {
208.266 - final ObjectName name = getObjectName();
208.267 - if (name == null) return 0;
208.268 - try {
208.269 - return getSourceServer().
208.270 - queryNames(ObjectName.WILDCARD.withDomain(name.getDomain()),
208.271 - null).size();
208.272 - } catch (RuntimeException x) {
208.273 - throw x;
208.274 - } catch (Exception x) {
208.275 - throw new RuntimeException("Unexpected exception: "+x,x);
208.276 - }
208.277 - }
208.278 -
208.279 -
208.280 -
208.281 - /**
208.282 - * Return a canonical handler name for the provided local
208.283 - * <var>domain</var> name, or null if the provided domain name is
208.284 - * {@code null}.
208.285 - * If not null, the handler name returned will be
208.286 - * {@code domain+":type="+}{@link #TYPE TYPE}, for example
208.287 - * {@code foo:type=JMXDomain}.
208.288 - * @param domain A domain name
208.289 - * @return a canonical ObjectName for a domain handler.
208.290 - * @throws IllegalArgumentException if the provided
208.291 - * <var>domain</var> is not valid - e.g it contains "//".
208.292 - */
208.293 - public static ObjectName getDomainObjectName(String domain) {
208.294 - if (domain == null) return null;
208.295 - if (domain.contains(NAMESPACE_SEPARATOR))
208.296 - throw new IllegalArgumentException("domain contains " +
208.297 - NAMESPACE_SEPARATOR+": "+domain);
208.298 - return ObjectName.valueOf(domain, "type", TYPE);
208.299 - }
208.300 -
208.301 -
208.302 - /**
208.303 - * Validate the ObjectName supplied to preRegister.
208.304 - * This method is introduced to allow standard subclasses to use
208.305 - * an alternate naming scheme. For instance - if we want to
208.306 - * reuse JMXNamespace in order to implement sessions...
208.307 - * It is however only available for subclasses in this package.
208.308 - **/
208.309 - @Override
208.310 - ObjectName validateHandlerName(ObjectName suppliedName) {
208.311 - if (suppliedName == null)
208.312 - throw new IllegalArgumentException("Must supply a valid name");
208.313 - final String dirName = JMXNamespaces.
208.314 - normalizeNamespaceName(suppliedName.getDomain());
208.315 - final ObjectName handlerName = getDomainObjectName(dirName);
208.316 - if (!suppliedName.equals(handlerName))
208.317 - throw new IllegalArgumentException("invalid name space name: "+
208.318 - suppliedName);
208.319 -
208.320 - return suppliedName;
208.321 - }
208.322 -
208.323 - /**
208.324 - * This method is called by the JMX framework to register a
208.325 - * NotificationListener that will forward {@linkplain
208.326 - * javax.management.MBeanServerNotification mbean server notifications}
208.327 - * through the delegate of the {@linkplain #getMBeanServer()
208.328 - * containing MBeanServer}.
208.329 - * The default implementation of this method is to call
208.330 - * <pre>
208.331 - * getSourceServer().addNotificationListener(
208.332 - * MBeanServerDelegate.DELEGATE_NAME, listener, filter, null);
208.333 - * </pre>
208.334 - * Subclasses can redefine this behavior if needed. In particular,
208.335 - * subclasses can send their own instances of {@link
208.336 - * javax.management.MBeanServerNotification} by calling
208.337 - * {@code listener.handleNotification()}.
208.338 - *
208.339 - * @param listener The MBeanServerNotification listener for this domain.
208.340 - * @param filter A notification filter.
208.341 - */
208.342 - public void addMBeanServerNotificationListener(
208.343 - NotificationListener listener, NotificationFilter filter) {
208.344 - try {
208.345 - getSourceServer().addNotificationListener(
208.346 - MBeanServerDelegate.DELEGATE_NAME, listener, filter, null);
208.347 - } catch(InstanceNotFoundException x) {
208.348 - throw new UnsupportedOperationException(
208.349 - "Unexpected exception: " +
208.350 - "Emission of MBeanServerNotification disabled.", x);
208.351 - }
208.352 - }
208.353 -
208.354 - /**
208.355 - * This method is called by the JMX framework to remove the
208.356 - * NotificationListener that was added with {@link
208.357 - * #addMBeanServerNotificationListener addMBeanServerNotificationListener}.
208.358 - * The default implementation of this method is to call
208.359 - * <pre>
208.360 - * getSourceServer().removeNotificationListener(
208.361 - * MBeanServerDelegate.DELEGATE_NAME, listener);
208.362 - * </pre>
208.363 - * Subclasses can redefine this behavior if needed.
208.364 - *
208.365 - * @param listener The MBeanServerNotification listener for this domain.
208.366 - * @throws ListenerNotFoundException if the listener is not found.
208.367 - */
208.368 - public void removeMBeanServerNotificationListener(
208.369 - NotificationListener listener)
208.370 - throws ListenerNotFoundException {
208.371 - try {
208.372 - getSourceServer().removeNotificationListener(
208.373 - MBeanServerDelegate.DELEGATE_NAME, listener);
208.374 - } catch(InstanceNotFoundException x) {
208.375 - throw new UnsupportedOperationException(
208.376 - "Unexpected exception: " +
208.377 - "Emission of MBeanServerNotification disabled.", x);
208.378 - }
208.379 - }
208.380 -
208.381 -}
209.1 --- a/src/share/classes/javax/management/namespace/JMXNamespace.java Mon Nov 23 10:04:47 2009 +0000
209.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
209.3 @@ -1,666 +0,0 @@
209.4 -/*
209.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
209.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
209.7 - *
209.8 - * This code is free software; you can redistribute it and/or modify it
209.9 - * under the terms of the GNU General Public License version 2 only, as
209.10 - * published by the Free Software Foundation. Sun designates this
209.11 - * particular file as subject to the "Classpath" exception as provided
209.12 - * by Sun in the LICENSE file that accompanied this code.
209.13 - *
209.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
209.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
209.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
209.17 - * version 2 for more details (a copy is included in the LICENSE file that
209.18 - * accompanied this code).
209.19 - *
209.20 - * You should have received a copy of the GNU General Public License version
209.21 - * 2 along with this work; if not, write to the Free Software Foundation,
209.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
209.23 - *
209.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
209.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
209.26 - * have any questions.
209.27 - */
209.28 -
209.29 -package javax.management.namespace;
209.30 -
209.31 -
209.32 -import java.io.IOException;
209.33 -
209.34 -import java.util.UUID;
209.35 -import javax.management.MBeanRegistration;
209.36 -import javax.management.MBeanServer;
209.37 -import javax.management.ObjectName;
209.38 -
209.39 -/**
209.40 - * MBean Servers can be federated into a single hierarchical name space:
209.41 - * A JMXNamespace is an MBean that handles a sub name space in that
209.42 - * hierarchical name space.
209.43 - * <p>
209.44 - * A name space is created simply by registering a {@code JMXNamespace}
209.45 - * MBean in the MBean Server. The name of the created name space is defined
209.46 - * by the {@linkplain JMXNamespaces#getNamespaceObjectName name of the JMXNamespace}
209.47 - * that handles it. A name space is equivalent to
209.48 - * an MBean Server within an MBean Server. When creating a {@code JMXNamespace},
209.49 - * the MBean Server within is passed to the constructor.
209.50 - * </p>
209.51 - * <p>
209.52 - * The {@code JMXNamespace} class is the base class for implementing
209.53 - * all name space handlers. All name space handlers must be instances of
209.54 - * {@code JMXNamespace} or a subclass of it.
209.55 - * </p>
209.56 - * <p>
209.57 - * A concrete example of a {@code JMXNamespace} MBean subclass
209.58 - * is the {@link JMXRemoteNamespace JMXRemoteNamespace} MBean which
209.59 - * is able to mirror all MBeans contained in a remote MBean server known by its
209.60 - * {@link javax.management.remote.JMXServiceURL}.
209.61 - * </p>
209.62 - * <p>
209.63 - * You can create a local namespace by supplying a newly created MBean Server
209.64 - * to an instance of {@code JMXNamespace}. For instance:
209.65 - * <pre>
209.66 - * final String namespace = "foo";
209.67 - * final ObjectName namespaceName = {@link JMXNamespaces#getNamespaceObjectName
209.68 - * JMXNamespaces.getNamespaceObjectName(namespace)};
209.69 - * server.registerMBean(new JMXNamespace(MBeanServerFactory.newMBeanServer()),
209.70 - * namespaceName);
209.71 - * </pre>
209.72 - * </p>
209.73 - * <p>
209.74 - * <u>Note:</u> A JMXNamespace MBean cannot be registered
209.75 - * simultaneously in two different
209.76 - * MBean servers, or indeed in the same MBean Server with two
209.77 - * different names. It is however possible to give the same MBeanServer
209.78 - * instance to two different JMXNamespace MBeans, and thus create a graph
209.79 - * rather than a tree.
209.80 - * </p>
209.81 - *
209.82 - * <p>To view the content of a namespace, you will usually use an
209.83 - * instance of {@link JMXNamespaceView}. For instance, given the
209.84 - * namespace {@code "foo"} created above, you would do:
209.85 - * </p>
209.86 - * <pre>
209.87 - * final JMXNamespaceView view = new JMXNamespaceView(server);
209.88 - * System.out.println("List of namespaces: "+Arrays.toString({@link JMXNamespaceView#list() view.list()}));
209.89 - *
209.90 - * final JMXNamespaceView foo = {@link JMXNamespaceView#down view.down("foo")};
209.91 - * System.out.println({@link JMXNamespaceView#where() foo.where()}+" contains: " +
209.92 - * {@link JMXNamespaceView#getMBeanServerConnection foo.getMBeanServerConnection()}.queryNames(null,null));
209.93 - * </pre>
209.94 - *
209.95 - * <h2 id="PermissionChecks">JMX Namespace Permission Checks</h2>
209.96 - *
209.97 - * <p>A special {@link JMXNamespacePermission} is defined to check access
209.98 - * to MBean within namespaces.</p>
209.99 - * <p>When a JMXNamespace MBean is registered in an
209.100 - * MBean server created through the default {@link
209.101 - * javax.management.MBeanServerBuilder}, and if a {@link
209.102 - * SecurityManager SecurityManager} is
209.103 - * {@linkplain System#getSecurityManager() present}, the MBeanServer will
209.104 - * check a {@link JMXNamespacePermission} before invoking
209.105 - * any method on the {@linkplain #getSourceServer source MBeanServer} of the
209.106 - * JMXNamespace.
209.107 - * {@linkplain JMXNamespacePermission JMX Namespace Permissions} are similar to
209.108 - * {@linkplain javax.management.MBeanPermission MBean Permissions}, except
209.109 - * that you usually cannot specify an MBean class name. You can however
209.110 - * specify object name patterns - which will allow you for example to only grant
209.111 - * permissions for MBeans having a specific {@code type=<MBeanType>} key
209.112 - * in their object name.
209.113 - * <p>
209.114 - * Another difference is that {@link JMXNamespacePermission
209.115 - * JMXNamespacePermission} also specifies from which namespace and which
209.116 - * MBean server the permission is granted.
209.117 - * </p>
209.118 - * <p>In the rest of this document, the following terms are used:</p>
209.119 - * <ul>
209.120 - * <li id="MBeanServerName"><p>{@code server name} is the
209.121 - * <a href="../MBeanServerFactory.html#MBeanServerName">name of the
209.122 - * MBeanServer</a> in which the permission is granted.
209.123 - * The name of an {@code MBeanServer} can be obtained by calling {@link
209.124 - * javax.management.MBeanServerFactory#getMBeanServerName
209.125 - * MBeanServerFactory.getMBeanServerName(mbeanServer)}
209.126 - * </p>
209.127 - * <li id="NamespaceName"><p>{@code namespace} is the name of the namespace
209.128 - * in the <a href="#MBeanServerName">named MBean server</a> for which the
209.129 - * permission is granted. It doesn't contain any
209.130 - * {@link JMXNamespaces#NAMESPACE_SEPARATOR namespace separator}.
209.131 - * </p>
209.132 - * <li id="MBeanName"><p>{@code mbean} is the name
209.133 - * of the MBean in that {@code namespace}. This is the name of the MBean
209.134 - * in the namespace's {@link JMXNamespace#getSourceServer() source mbean server}.
209.135 - * It might contain no, one, or several {@link
209.136 - * JMXNamespaces#NAMESPACE_SEPARATOR namespace separators}.
209.137 - * </p>
209.138 - * </ul>
209.139 - *
209.140 - * <p>For instance let's assume that some piece of code calls:</p>
209.141 - * <pre>
209.142 - * final MBeanServer mbeanServer = ...;
209.143 - * final ObjectName name = new ObjectName("a//b//c//D:k=v");
209.144 - * mbeanServer.getAttribute(name,"Foo");
209.145 - * </pre>
209.146 - * <p>
209.147 - * Assuming that there is a security manager, or that the
209.148 - * implementation chooses to make checks anyway, the checks that will
209.149 - * be made in that case are:
209.150 - * </p>
209.151 - * <ol>
209.152 - * <li id="check1">
209.153 - * <code>JMXNamespacePermission(mbeanServerName, "Foo", "<b>a//</b>b//c//D:k=v",
209.154 - * "getAttribute")</code>
209.155 - * (where {@code mbeanServerName=MBeanServerFactory.getMBeanServerName(mbeanServer)},
209.156 - * <code>namespace="<b>a</b>"</code>, and {@code mbean="b//c//D:k=v"})
209.157 - * </li>
209.158 - * <li id="check2">and in addition if namespace {@code "a"} is local,
209.159 - * <code>JMXNamespacePermission(aSourceServerName,"Foo","<b>b//</b>c//D:k=v",
209.160 - * "getAttribute")}</code>
209.161 - * (where
209.162 - * {@code aSourceServerName=MBeanServerFactory.getMBeanServerName(sourceServer(a))},
209.163 - * <code>namespace="<b>b</b>"</code>, and {@code mbean="c//D:k=v"}),
209.164 - * </li>
209.165 - * <li id="check3">and in addition if namespace {@code "b"} is also local,
209.166 - * <code>JMXNamespacePermission(bSourceServerName,"Foo","<b>c//</b>D:k=v",
209.167 - * "getAttribute")}</code>
209.168 - * (where
209.169 - * {@code bSourceServerName=MBeanServerFactory.getMBeanServerName(sourceServer(b))},
209.170 - * <code>namespace="<b>c</b>"</code>, and {@code mbean="D:k=v"}),
209.171 - * </li>
209.172 - * <li id="check4">and in addition if the source mbean server of namespace
209.173 - * {@code "c"} is a also a local MBeanServer in this JVM,
209.174 - * {@code MBeanPermission(cSourceServerName,<className(D:k=v)>,"Foo","D:k=v","getAttrinute")},
209.175 - * (where
209.176 - * {@code cSourceServerName=MBeanServerFactory.getMBeanServerName(sourceServer(c))}).
209.177 - * </li>
209.178 - * </ol>
209.179 - * <p>For any of these MBean servers, if no name was supplied when
209.180 - * creating that MBeanServer the {@link JMXNamespacePermission} is
209.181 - * created with an {@code mbeanServerName} equal to
209.182 - * {@value javax.management.MBeanServerFactory#DEFAULT_MBEANSERVER_NAME}.
209.183 - * </p>
209.184 - * <p>If the namespace {@code a} is in fact a remote {@code MBeanServer},
209.185 - * for instance because namespace {@code a} is implemented by a {@link
209.186 - * JMXRemoteNamespace} pointing to a distant MBeanServer located in
209.187 - * another JMX agent, then checks <a href="#check2">2</a>,
209.188 - * <a href="#check3">3</a>, and <a href="#check4">4</a> will not
209.189 - * be performed in the local JVM. They might or might not be performed in
209.190 - * the remote agent, depending on how access control and permission
209.191 - * checking are configured in the remote agent, and how authentication
209.192 - * is configured in the connector used by the {@link
209.193 - * JMXRemoteNamespace}.
209.194 - * </p>
209.195 - * <p>In all cases, {@linkplain JMXNamespacePermission JMX Namespace Permissions}
209.196 - * are checked as follows:</p>
209.197 - * <p>First, if there is no security manager ({@link
209.198 - * System#getSecurityManager()} is null), then an implementation of
209.199 - * of MBeanServer that supports JMX namespaces is free not to make any
209.200 - * checks.</p>
209.201 - *
209.202 - * <p>Assuming that there is a security manager, or that the
209.203 - * implementation chooses to make checks anyway, the checks are made
209.204 - * as detailed below.</p>
209.205 - *
209.206 - * <p>If a security check fails, the method throws {@link
209.207 - * SecurityException}.</p>
209.208 - *
209.209 - * <ul>
209.210 - *
209.211 - * <li><p>For the {@link MBeanServer#invoke invoke} method, the caller's
209.212 - * permissions must imply {@link
209.213 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.214 - * JMXNamespacePermission(<mbean server name>, <operation name>, <namespace>//<mbean>, "invoke")},
209.215 - * where <a href="#MBeanServerName">mbean server name</a> is the name of the
209.216 - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
209.217 - * <a href="#NamespaceName">namespace</a> is registered, and
209.218 - * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
209.219 - * is performed, in that namespace.
209.220 - * </p>
209.221 - *
209.222 - * <li><p>For the {@link MBeanServer#getAttribute getAttribute} method, the
209.223 - * caller's permissions must imply {@link
209.224 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.225 - * JMXNamespacePermission(<mbean server name>, <attribute>, <namespace>//<mbean>, "getAttribute")}.
209.226 - * </p>
209.227 - *
209.228 - * <li><p>For the {@link MBeanServer#getAttributes getAttributes} method, the
209.229 - * caller's permissions must imply {@link
209.230 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.231 - * JMXNamespacePermission(<mbean server name>, <null>, <namespace>//<mbean>, "getAttribute")},
209.232 - * where <a href="#MBeanServerName">mbean server name</a> is the name of the
209.233 - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
209.234 - * <a href="#NamespaceName">namespace</a> is registered, and
209.235 - * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
209.236 - * is performed, in that namespace.
209.237 - * Additionally, for each attribute <em>att</em> in the {@link
209.238 - * javax.management.AttributeList}, if the caller's permissions do not
209.239 - * imply {@link
209.240 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.241 - * JMXNamespacePermission(<mbean server name>, <em>att</em>,
209.242 - * <namespace>//<mbean>, "getAttribute")}, the
209.243 - * MBean server will behave as if that attribute had not been in the
209.244 - * supplied list.</p>
209.245 - *
209.246 - * <li><p>For the {@link MBeanServer#setAttribute setAttribute} method, the
209.247 - * caller's permissions must imply {@link
209.248 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.249 - * JMXNamespacePermission(<mbean server name>, <attrName>, <namespace>//<mbean>, "setAttribute")},
209.250 - * where <a href="#MBeanServerName">mbean server name</a> is the name of the
209.251 - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
209.252 - * <a href="#NamespaceName">namespace</a> is registered, and
209.253 - * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
209.254 - * is performed, in that namespace, and
209.255 - * <code>attrName</code> is {@link javax.management.Attribute#getName()
209.256 - * attribute.getName()}.</p>
209.257 - *
209.258 - * <li><p>For the {@link MBeanServer#setAttributes setAttributes} method, the
209.259 - * caller's permissions must imply {@link
209.260 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.261 - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>, "setAttribute")},
209.262 - * where <a href="#MBeanServerName">mbean server name</a> is the name of the
209.263 - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
209.264 - * <a href="#NamespaceName">namespace</a> is registered, and
209.265 - * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
209.266 - * is performed, in that namespace.
209.267 - * Additionally, for each attribute <em>att</em> in the {@link
209.268 - * javax.management.AttributeList}, if the caller's permissions do not
209.269 - * imply {@link
209.270 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.271 - * JMXNamespacePermission(<mbean server name>, <em>att</em>, <namespace>//<mbean>, "setAttribute")},
209.272 - * the MBean server will behave as if that attribute had not been in the
209.273 - * supplied list.</p>
209.274 - *
209.275 - * <li><p>For the <code>addNotificationListener</code> methods,
209.276 - * the caller's permissions must imply {@link
209.277 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.278 - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
209.279 - * "addNotificationListener")},
209.280 - * where <a href="#MBeanServerName">mbean server name</a> is the name of the
209.281 - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
209.282 - * <a href="#NamespaceName">namespace</a> is registered, and
209.283 - * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
209.284 - * is performed, in that namespace.
209.285 - * </p>
209.286 - *
209.287 - * <li><p>For the <code>removeNotificationListener</code> methods,
209.288 - * the caller's permissions must imply {@link
209.289 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.290 - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
209.291 - * "removeNotificationListener")},
209.292 - * where <a href="#MBeanServerName">mbean server name</a> is the name of the
209.293 - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
209.294 - * <a href="#NamespaceName">namespace</a> is registered, and
209.295 - * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
209.296 - * is performed, in that namespace.
209.297 - * </p>
209.298 - *
209.299 - * <li><p>For the {@link MBeanServer#getMBeanInfo getMBeanInfo} method, the
209.300 - * caller's permissions must imply {@link
209.301 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.302 - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
209.303 - * "getMBeanInfo")},
209.304 - * where <a href="#MBeanServerName">mbean server name</a> is the name of the
209.305 - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
209.306 - * <a href="#NamespaceName">namespace</a> is registered, and
209.307 - * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
209.308 - * is performed, in that namespace.
209.309 - * </p>
209.310 - *
209.311 - * <li><p>For the {@link MBeanServer#getObjectInstance getObjectInstance} method,
209.312 - * the caller's permissions must imply {@link
209.313 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.314 - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
209.315 - * "getObjectInstance")},
209.316 - * where <a href="#MBeanServerName">mbean server name/a> is the name of the
209.317 - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
209.318 - * <a href="#NamespaceName">namespace</a> is registered, and
209.319 - * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
209.320 - * is performed, in that namespace.
209.321 - * </p>
209.322 - *
209.323 - * <li><p>For the {@link MBeanServer#isInstanceOf isInstanceOf} method, the
209.324 - * caller's permissions must imply {@link
209.325 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.326 - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
209.327 - * "isInstanceOf")},
209.328 - * where <a href="#MBeanServerName">mbean server name</a> is the name of the
209.329 - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
209.330 - * <a href="#NamespaceName">namespace</a> is registered, and
209.331 - * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
209.332 - * is performed, in that namespace.
209.333 - * </p>
209.334 - *
209.335 - * <li><p>For the {@link MBeanServer#queryMBeans queryMBeans} method, the
209.336 - * caller's permissions must imply {@link
209.337 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.338 - * JMXNamespacePermission(<mbean server name>, null, null,
209.339 - * "queryMBeans")}.
209.340 - * Additionally, for each MBean {@code mbean} that matches {@code pattern},
209.341 - * if the caller's permissions do not imply {@link
209.342 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.343 - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
209.344 - * "queryMBeans")}, the
209.345 - * MBean server will behave as if that MBean did not exist.</p>
209.346 - *
209.347 - * <p>Certain query elements perform operations on the MBean server.
209.348 - * However these operations are usually performed by the MBeanServer at the
209.349 - * bottom of the namespace path, and therefore, do not involve any
209.350 - * {@link JMXNamespacePermission} permission check. They might involve
209.351 - * {@link javax.management.MBeanPermission} checks depending on how security
209.352 - * in the JVM in which the bottom MBeanServer resides is implemented.
209.353 - * See {@link javax.management.MBeanServer} for more details.
209.354 - * </p>
209.355 - *
209.356 - * <li><p>For the {@link MBeanServer#queryNames queryNames} method, the checks
209.357 - * are the same as for <code>queryMBeans</code> except that
209.358 - * <code>"queryNames"</code> is used instead of
209.359 - * <code>"queryMBeans"</code> in the <code>JMXNamespacePermission</code>
209.360 - * objects. Note that a <code>"queryMBeans"</code> permission implies
209.361 - * the corresponding <code>"queryNames"</code> permission.</p>
209.362 - *
209.363 - * <li><p>For the {@link MBeanServer#getClassLoader getClassLoader} method, the
209.364 - * caller's permissions must imply {@link
209.365 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.366 - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<loaderName>,
209.367 - * "getClassLoader")},
209.368 - * where <a href="#MBeanServerName">mbean server name/a> is the name of the
209.369 - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
209.370 - * <a href="#NamespaceName">namespace</a> is registered, and
209.371 - * <a href="#MBeanName">loaderName</a> is the name of the ClassLoader MBean
209.372 - * which is accessed, in that namespace.
209.373 - * </p>
209.374 - *
209.375 - * <li><p>For the {@link MBeanServer#getClassLoaderFor getClassLoaderFor} method,
209.376 - * the caller's permissions must imply {@link
209.377 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.378 - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
209.379 - * "getClassLoaderFor")},
209.380 - * where <a href="#MBeanServerName">mbean server name</a> is the name of the
209.381 - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
209.382 - * <a href="#NamespaceName">namespace</a> is registered, and
209.383 - * <a href="#MBeanName">mbean</a> is the name of the MBean on which the action
209.384 - * is performed, in that namespace.
209.385 - * </p>
209.386 - *
209.387 - * <li><p>For the {@link MBeanServer#registerMBean registerMBean} method, the
209.388 - * caller's permissions must imply {@link
209.389 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.390 - * JMXNamespacePermission(<mbean server name>, <class name>, <namespace>//<mbean>,
209.391 - * "registerMBean")}. Here
209.392 - * <code>class name</code> is the string returned by {@code
209.393 - * obj.getClass().getName()} where {@code obj} is the mbean reference,
209.394 - * <a href="#MBeanServerName"mbean server name/a> is the name of the
209.395 - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
209.396 - * <a href="#NamespaceName">namespace</a> is registered, and
209.397 - * <a href="#MBeanName">mbean</a> is the name of the MBean which is being
209.398 - * registered, relative to that namespace.
209.399 - *
209.400 - * <li><p>For the <code>createMBean</code> methods, the caller's
209.401 - * permissions must imply {@link
209.402 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.403 - * JMXNamespacePermission(<mbean server name>, <class name>, <namespace>//<mbean>,
209.404 - * "instantiate")} and
209.405 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.406 - * JMXNamespacePermission(<mbean server name>, <class name>, <namespace>//<mbean>,
209.407 - * "registerMBean")}, where
209.408 - * <code>class name</code> is the string passed as first argument to the {@code
209.409 - * createMBean} method,
209.410 - * <a href="#MBeanServerName">mbean server name</a> is the name of the
209.411 - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
209.412 - * <a href="#NamespaceName">namespace</a> is registered, and
209.413 - * <a href="#MBeanName">mbean</a> is the name of the MBean which is being
209.414 - * created, relative to that namespace.
209.415 - *
209.416 - * <li><p>For the {@link MBeanServer#unregisterMBean unregisterMBean} method,
209.417 - * the caller's permissions must imply {@link
209.418 - * JMXNamespacePermission#JMXNamespacePermission(String,String,ObjectName,String)
209.419 - * JMXNamespacePermission(<mbean server name>, null, <namespace>//<mbean>,
209.420 - * "unregisterMBean")},
209.421 - * where <a href="#MBeanServerName">mbean server name</a> is the name of the
209.422 - * {@code MBeanServer} in which the {@code JMXNamespace} MBean in charge of
209.423 - * <a href="#NamespaceName">namespace</a> is registered, and
209.424 - * <a href="#MBeanName">mbean</a> is the name of the MBean on which is
209.425 - * being unregistered, relative to that namespace.
209.426 - * </p>
209.427 - * </ul>
209.428 - * </p>
209.429 - * <p>It must be noted that if all namespaces are local, and all
209.430 - * local namespaces are implemented by regular MBean servers, that is, there
209.431 - * are no {@linkplain MBeanServerSupport Virtual Namespaces}, then
209.432 - * simple {@linkplain javax.management.MBeanPermission MBean Permission}
209.433 - * checks might be enough to secure an application.
209.434 - * In that case, it is possible to specify the following {@link
209.435 - * JMXNamespacePermission} permission in the policy file, which implies all
209.436 - * other JMX namespace permissions:
209.437 - * </p>
209.438 - * <pre>
209.439 - * permission javax.management.namespace.JMXNamespacePermission "*::*[]", "*";
209.440 - * </pre>
209.441 - *
209.442 - * @since 1.7
209.443 - */
209.444 -public class JMXNamespace
209.445 - implements JMXNamespaceMBean, MBeanRegistration {
209.446 -
209.447 - /**
209.448 - * The standard value of the {@code type}
209.449 - * property key that must be used to construct valid {@link
209.450 - * JMXNamespaceMBean} ObjectNames.<br>
209.451 - * This is {@value #TYPE}.
209.452 - **/
209.453 - public static final String TYPE = "JMXNamespace";
209.454 -
209.455 - /**
209.456 - * The {@link ObjectName#getKeyPropertyListString keyPropertyListString}
209.457 - * that must be used to construct valid {@link JMXNamespaceMBean}
209.458 - * ObjectNames.<br>
209.459 - * This is
209.460 - * <code>{@value #TYPE_ASSIGNMENT}</code>.
209.461 - **/
209.462 - public static final String TYPE_ASSIGNMENT = "type="+TYPE;
209.463 -
209.464 - private volatile MBeanServer mbeanServer; // the mbean server in which
209.465 - // this MBean is registered.
209.466 - private volatile ObjectName objectName; // the ObjectName of this MBean.
209.467 - private final MBeanServer sourceServer; // the MBeanServer within = the
209.468 - // name space (or the MBean server
209.469 - // that contains it).
209.470 - private final String uuid;
209.471 -
209.472 - /**
209.473 - * Creates a new JMXNamespace implemented by means of an MBean Server.
209.474 - * A namespace is equivalent to an MBeanServer within an MBean Server.
209.475 - * The {@code sourceServer} provided to this constructor is the MBean Server
209.476 - * within.
209.477 - * @param sourceServer the MBean server that implemented by this namespace.
209.478 - * @see #getSourceServer
209.479 - */
209.480 - public JMXNamespace(MBeanServer sourceServer) {
209.481 - this.sourceServer = sourceServer;
209.482 - this.uuid = UUID.randomUUID().toString();
209.483 - }
209.484 -
209.485 - /**
209.486 - * This method is part of the {@link MBeanRegistration} interface.
209.487 - * The {@link JMXNamespace} class uses the {@link MBeanRegistration}
209.488 - * interface in order to get a reference to the MBean server in which it is
209.489 - * registered. It also checks the validity of its own ObjectName.
209.490 - * <p>
209.491 - * This method is called by the MBean server.
209.492 - * Application classes should never call this method directly.
209.493 - * <p>
209.494 - * If this method is overridden, the overriding method should call
209.495 - * {@code super.preRegister(server,name)}.
209.496 - * @see MBeanRegistration#preRegister MBeanRegistration
209.497 - * @see JMXNamespaces#getNamespaceObjectName getNamespaceObjectName
209.498 - * @param name The object name of the MBean. <var>name</var> must be a
209.499 - * syntactically valid JMXNamespace name, as returned by
209.500 - * {@link JMXNamespaces#getNamespaceObjectName(java.lang.String)
209.501 - * getNamespaceObjectName(namespace)}.
209.502 - * @return The name under which the MBean is to be registered.
209.503 - * @throws IllegalArgumentException if the name supplied is not valid.
209.504 - * @throws Exception can be thrown by subclasses.
209.505 - */
209.506 - public ObjectName preRegister(MBeanServer server, ObjectName name)
209.507 - throws Exception {
209.508 - // need to synchronize to protect against multiple registration.
209.509 - synchronized(this) {
209.510 - if (objectName != null && ! objectName.equals(name))
209.511 - throw new IllegalStateException(
209.512 - "Already registered under another name: " + objectName);
209.513 - objectName = validateHandlerName(name);
209.514 - mbeanServer = server;
209.515 - }
209.516 - return name;
209.517 - }
209.518 -
209.519 - /**
209.520 - * Validate the ObjectName supplied to preRegister.
209.521 - * This method is introduced to allow standard subclasses to use
209.522 - * an alternate naming scheme. For instance - if we want to
209.523 - * reuse JMXNamespace in order to implement sessions...
209.524 - * It is however only available for subclasses in this package.
209.525 - **/
209.526 - ObjectName validateHandlerName(ObjectName suppliedName) {
209.527 - if (suppliedName == null)
209.528 - throw new IllegalArgumentException("Must supply a valid name");
209.529 - final String dirName = JMXNamespaces.
209.530 - normalizeNamespaceName(suppliedName.getDomain());
209.531 - final ObjectName handlerName =
209.532 - JMXNamespaces.getNamespaceObjectName(dirName);
209.533 - if (!suppliedName.equals(handlerName))
209.534 - throw new IllegalArgumentException("invalid name space name: "+
209.535 - suppliedName);
209.536 - return suppliedName;
209.537 - }
209.538 -
209.539 - /**
209.540 - * This method is part of the {@link MBeanRegistration} interface.
209.541 - * The {@link JMXNamespace} class uses the {@link MBeanRegistration}
209.542 - * interface in order to get a reference to the MBean server in which it is
209.543 - * registered.
209.544 - * <p>
209.545 - * This method is called by the MBean server. Application classes should
209.546 - * not call this method directly. Subclasses are free to override this
209.547 - * method with their own specific behavior - but the overriding method
209.548 - * shoud still call {@code super.postRegister(registrationDone)}.
209.549 - * @see MBeanRegistration#postRegister MBeanRegistration
209.550 - */
209.551 - public void postRegister(Boolean registrationDone) {
209.552 - // nothing to do
209.553 - }
209.554 -
209.555 - /**
209.556 - * This method is part of the {@link MBeanRegistration} interface.
209.557 - * The {@link JMXNamespace} class uses the {@link MBeanRegistration}
209.558 - * interface in order to get a reference to the MBean server in which it is
209.559 - * registered.
209.560 - * <p>
209.561 - * This method is called by the MBean server. Application classes should
209.562 - * not call this method directly. Subclasses are free to override this
209.563 - * method with their own specific behavior - but the overriding method
209.564 - * shoud still call {@code super.preDeregister()}.
209.565 - * @see MBeanRegistration#preDeregister MBeanRegistration
209.566 - */
209.567 - public void preDeregister() throws Exception {
209.568 - // nothing to do
209.569 - }
209.570 -
209.571 - /**
209.572 - * This method is part of the {@link MBeanRegistration} interface.
209.573 - * It allows the {@code JMXNamespace} MBean to perform any operations
209.574 - * needed after having been unregistered in the MBean server.
209.575 - * <p>
209.576 - * This method is called by the MBean server. Application classes should
209.577 - * not call this method directly. If a subclass overrides this
209.578 - * method, the overriding method shoud call {@code super.postDeregister()}.
209.579 - * @see MBeanRegistration#postDeregister MBeanRegistration
209.580 - */
209.581 - public void postDeregister() {
209.582 - // need to synchronize to protect against multiple registration.
209.583 - synchronized(this) {
209.584 - mbeanServer = null;
209.585 - objectName = null;
209.586 - }
209.587 - }
209.588 -
209.589 -
209.590 - /**
209.591 - * Returns the MBeanServer in which this MBean is registered,
209.592 - * or null. Chiefly of interest for subclasses.
209.593 - * @return the MBeanServer supplied to {@link #preRegister}.
209.594 - **/
209.595 - public final MBeanServer getMBeanServer() {
209.596 - return mbeanServer;
209.597 - }
209.598 -
209.599 - /**
209.600 - * Returns the MBeanServer that contains or emulates the source
209.601 - * namespace. When a JMXNamespace MBean is registered in an
209.602 - * MBean server created through the default {@link
209.603 - * javax.management.MBeanServerBuilder}, the MBeanServer will
209.604 - * check {@link JMXNamespacePermission} before invoking
209.605 - * any method on the source MBeanServer of the JMXNamespace.
209.606 - * See <a href="#PermissionChecks">JMX Namespace Permission Checks</a>
209.607 - * above.
209.608 - * @return an MBeanServer view of the source namespace
209.609 - **/
209.610 - public MBeanServer getSourceServer() {
209.611 - return sourceServer;
209.612 - }
209.613 -
209.614 - /**
209.615 - * Returns the ObjectName with which this MBean was registered,
209.616 - * or null. Chiefly of interest for subclasses.
209.617 - * @return the ObjectName supplied to {@link #preRegister}.
209.618 - **/
209.619 - public final ObjectName getObjectName() {
209.620 - return objectName;
209.621 - }
209.622 -
209.623 - /**
209.624 - * HandlerName used in traces.
209.625 - **/
209.626 - String getHandlerName() {
209.627 - final ObjectName name = getObjectName();
209.628 - if (name != null) return name.toString();
209.629 - return this.toString();
209.630 - }
209.631 -
209.632 - /**
209.633 - * In this class, this method returns {@link #getSourceServer
209.634 - * getSourceServer()}.{@link javax.management.MBeanServer#getMBeanCount
209.635 - * getMBeanCount()}.
209.636 - * <br>This default behaviour may be redefined in subclasses.
209.637 - * @throws java.io.IOException can be thrown by subclasses.
209.638 - */
209.639 - public Integer getMBeanCount() throws IOException {
209.640 - return getSourceServer().getMBeanCount();
209.641 - }
209.642 -
209.643 - /**
209.644 - * In this class, this method returns {@link #getSourceServer
209.645 - * getSourceServer()}.{@link javax.management.MBeanServer#getDomains
209.646 - * getDomains()}.
209.647 - * <br>This default behaviour may be redefined in subclasses.
209.648 - * @throws java.io.IOException can be thrown by subclasses.
209.649 - */
209.650 - public String[] getDomains() throws IOException {
209.651 - return getSourceServer().getDomains();
209.652 - }
209.653 -
209.654 - /**
209.655 - * In this class, this method returns {@link #getSourceServer
209.656 - * getSourceServer()}.{@link javax.management.MBeanServer#getDefaultDomain
209.657 - * getDefaultDomain()}.
209.658 - * <br>This default behaviour may be redefined in subclasses.
209.659 - * @throws java.io.IOException can be thrown by subclasses.
209.660 - */
209.661 - public String getDefaultDomain() throws IOException {
209.662 - return getSourceServer().getDefaultDomain();
209.663 - }
209.664 -
209.665 - public final String getUUID() {
209.666 - return uuid;
209.667 - }
209.668 -
209.669 -}
210.1 --- a/src/share/classes/javax/management/namespace/JMXNamespaceMBean.java Mon Nov 23 10:04:47 2009 +0000
210.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
210.3 @@ -1,96 +0,0 @@
210.4 -/*
210.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
210.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
210.7 - *
210.8 - * This code is free software; you can redistribute it and/or modify it
210.9 - * under the terms of the GNU General Public License version 2 only, as
210.10 - * published by the Free Software Foundation. Sun designates this
210.11 - * particular file as subject to the "Classpath" exception as provided
210.12 - * by Sun in the LICENSE file that accompanied this code.
210.13 - *
210.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
210.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
210.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
210.17 - * version 2 for more details (a copy is included in the LICENSE file that
210.18 - * accompanied this code).
210.19 - *
210.20 - * You should have received a copy of the GNU General Public License version
210.21 - * 2 along with this work; if not, write to the Free Software Foundation,
210.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
210.23 - *
210.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
210.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
210.26 - * have any questions.
210.27 - */
210.28 -
210.29 -package javax.management.namespace;
210.30 -
210.31 -import java.io.IOException;
210.32 -import java.util.UUID;
210.33 -
210.34 -/**
210.35 - * A {@link JMXNamespace} is an MBean that handles a name space in the
210.36 - * MBeanServer hierarchical name space.
210.37 - * @see JMXNamespace
210.38 - * @since 1.7
210.39 - */
210.40 -public interface JMXNamespaceMBean {
210.41 -
210.42 - // Note: since getDomains(), getDefaultDomain(), and getMBeanCount()
210.43 - // don't take any ObjectName parameters, the only efficient way
210.44 - // to get these data is to call the corresponding method on the
210.45 - // JMXNamespaceMBean that handles the name space.
210.46 - //
210.47 - // We need these methods to implement 'cd' (JMXNamespaces.narrowToNamespace)
210.48 - // correctly.
210.49 - //
210.50 -
210.51 - /**
210.52 - * Returns the list of domains currently implemented in the name space
210.53 - * handled by this {@link JMXNamespace}.
210.54 - * @throws IOException if the domain list cannot be obtained due to
210.55 - * I/O problems (communication failures etc...).
210.56 - * @return the list of domains currently implemented in the name space
210.57 - * handled by this {@link JMXNamespace}.
210.58 - * @see javax.management.MBeanServerConnection#getDomains
210.59 - * MBeanServerConnection.getDomains
210.60 - **/
210.61 - public String[] getDomains() throws IOException;
210.62 -
210.63 - /**
210.64 - * Returns the default domain for the name space handled by
210.65 - * this {@link JMXNamespace}.
210.66 - * @throws IOException if the default domain cannot be obtained due to
210.67 - * I/O problems (communication failures etc...).
210.68 - * @return the default domain for the name space handled by
210.69 - * this {@link JMXNamespace}.
210.70 - * @see javax.management.MBeanServerConnection#getDefaultDomain
210.71 - * MBeanServerConnection.getDefaultDomain
210.72 - **/
210.73 - public String getDefaultDomain() throws IOException;
210.74 -
210.75 - /**
210.76 - * Returns the number of MBeans registered in the name space handled by
210.77 - * this {@link JMXNamespace}.
210.78 - *
210.79 - * @return the number of MBeans registered in the name space handled by
210.80 - * this {@link JMXNamespace}.
210.81 - *
210.82 - * @throws IOException if the MBean count cannot be obtained due to
210.83 - * I/O problems (communication failures etc...).
210.84 - * @see javax.management.MBeanServerConnection#getMBeanCount
210.85 - * MBeanServerConnection.getMBeanCount
210.86 - */
210.87 - public Integer getMBeanCount() throws IOException;
210.88 -
210.89 - /**
210.90 - * Returns a {@link java.util.UUID UUID string} which uniquely identifies
210.91 - * this {@linkplain JMXNamespace} MBean.
210.92 - * This information can be used to detect loops in the JMX name space graph.
210.93 - * @return A unique ID identifying this MBean.
210.94 - * @throws IOException if the MBean UUID cannot be obtained due to
210.95 - * I/O problems (communication failures etc...).
210.96 - */
210.97 - public String getUUID() throws IOException;
210.98 -
210.99 -}
211.1 --- a/src/share/classes/javax/management/namespace/JMXNamespacePermission.java Mon Nov 23 10:04:47 2009 +0000
211.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
211.3 @@ -1,1446 +0,0 @@
211.4 -/*
211.5 - * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
211.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
211.7 - *
211.8 - * This code is free software; you can redistribute it and/or modify it
211.9 - * under the terms of the GNU General Public License version 2 only, as
211.10 - * published by the Free Software Foundation. Sun designates this
211.11 - * particular file as subject to the "Classpath" exception as provided
211.12 - * by Sun in the LICENSE file that accompanied this code.
211.13 - *
211.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
211.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
211.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
211.17 - * version 2 for more details (a copy is included in the LICENSE file that
211.18 - * accompanied this code).
211.19 - *
211.20 - * You should have received a copy of the GNU General Public License version
211.21 - * 2 along with this work; if not, write to the Free Software Foundation,
211.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
211.23 - *
211.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
211.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
211.26 - * have any questions.
211.27 - */
211.28 -
211.29 -package javax.management.namespace;
211.30 -
211.31 -import javax.management.*;
211.32 -import com.sun.jmx.mbeanserver.Util;
211.33 -import java.io.IOException;
211.34 -import java.io.ObjectInputStream;
211.35 -import java.security.Permission;
211.36 -
211.37 -/**
211.38 - * <p>A permission controlling access to MBeans located in namespaces.
211.39 - * If a security manager has been set using {@link
211.40 - * System#setSecurityManager}, most operations on an MBean mounted in a
211.41 - * namespace require that the caller's permissions imply a
211.42 - * JMXNamespacePermission appropriate for the operation.
211.43 - * This is described in detail in the
211.44 - * documentation for the
211.45 - * <a href="JMXNamespace.html#PermissionChecks">JMXNamespace</a>
211.46 - * class.</p>
211.47 - *
211.48 - * <p>As with other {@link Permission} objects,
211.49 - * a JMXNamespacePermission can represent either a permission that
211.50 - * you <em>have</em> or a permission that you <em>need</em>.
211.51 - * When a sensitive operation is being checked for permission,
211.52 - * a JMXNamespacePermission is constructed
211.53 - * representing the permission you need. The operation is only
211.54 - * allowed if the permissions you have {@linkplain #implies imply} the
211.55 - * permission you need.</p>
211.56 - *
211.57 - * <p>A JMXNamespacePermission contains four items of information:</p>
211.58 - *
211.59 - * <ul>
211.60 - *
211.61 - * <li id="Action"><p>The <em>action</em>.</p>
211.62 - * <p>For a permission you need,
211.63 - * this is one of the actions in the list <a
211.64 - * href="#action-list">below</a>. For a permission you have, this is
211.65 - * a comma-separated list of those actions, or <code>*</code>,
211.66 - * representing all actions.</p>
211.67 - *
211.68 - * <p>The action is returned by {@link #getActions()}.</p>
211.69 - *
211.70 - * <li id="MBeanServerName"><p>The <em>MBean Server name</em>.</p>
211.71 - *
211.72 - * <p>For a permission you need, this is the {@linkplain
211.73 - * javax.management.MBeanServerFactory#getMBeanServerName
211.74 - * name of the MBeanServer}
211.75 - * from which the <a href="#MBeanName">MBean</a> is accessed.</p>
211.76 - *
211.77 - * <p>For a permission you have, this is either the {@linkplain
211.78 - * javax.management.MBeanServerFactory#getMBeanServerName
211.79 - * name of the MBeanServer} from which the <a href="#MBeanName">MBean</a>
211.80 - * for which you have this permission is accessed,
211.81 - * or a pattern against which that MBean Server name will be matched.<br>
211.82 - * An {@code mbeanServername} pattern can also be empty, or the single
211.83 - * character {@code "*"}, both of which match any {@code MBeanServer} name.
211.84 - * The string {@code "-"} doesn't match any MBeanServer name.
211.85 - * </p>
211.86 - *
211.87 - * <p>Example:</p>
211.88 - * <pre>
211.89 - * // grant permission to invoke the operation "stop" on any MBean
211.90 - * // whose name matches "a//**//*:type=JMXConnectorServer" when
211.91 - * // accessed from any MBeanServer whose name matches myapp.*"
211.92 - * permission javax.management.namespace.JMXNamespacePermission "myapp.*::stop[a//**//*:type=JMXConnectorServer]", "invoke";
211.93 - * </pre>
211.94 - *
211.95 - * <li id="Member"><p>The <em>member</em>.</p>
211.96 - *
211.97 - * <p>For a permission you need, this is the name of the attribute or
211.98 - * operation you are accessing. For operations that do not reference
211.99 - * an attribute or operation, the member is null.</p>
211.100 - *
211.101 - * <p>For a permission you have, this is either the name of an attribute
211.102 - * or operation you can access, or it is empty or the single character
211.103 - * "<code>*</code>", both of which grant access to any member.</p>
211.104 - *
211.105 - * <p>There is a special case for actions {@code registerMBean} and
211.106 - * {@code instantiate}, where for a permission you need, {@code member}
211.107 - * indicates the name of the class for which you are trying
211.108 - * to create, instantiate, or register an MBean instance. For a
211.109 - * permission you have, it is a pattern that will be matched against
211.110 - * the full class name of the MBean being created, instantiated, or
211.111 - * registered.
211.112 - * </p>
211.113 - *
211.114 - *
211.115 - * <li id="MBeanName"><p>The <em>object name</em>.</p>
211.116 - *
211.117 - * <p>For a permission you need, this is the {@link ObjectName} of the
211.118 - * MBean you are accessing. It is of the form {@code <namespace>//<mbean name>}
211.119 - * where {@code <namespace>} is the name of the name space for which the
211.120 - * permission is checked, and {@code <mbean name>} is the name of the MBean
211.121 - * within that namespace.
211.122 - * <br>
211.123 - * For operations that do not reference a
211.124 - * single MBean, the <em>object name</em> is null. It is never an object
211.125 - * name pattern.
211.126 - * </p>
211.127 - *
211.128 - * <p>For a permission you have, this is the {@link ObjectName} of the
211.129 - * MBean or MBeans you can access. It is of the form
211.130 - * {@code <namespace>//<mbean name>}
211.131 - * where {@code <namespace>} is the name of the name space for which the
211.132 - * permission is checked, and
211.133 - * {@code <mbean name>} is the name of the MBean
211.134 - * within that namespace. Both {@code <namespace>} and {@code <mbean name>}
211.135 - * can be patterns. The <em>object name</em>
211.136 - * may also be empty, which grants access to all MBeans whatever their
211.137 - * name and namespace.
211.138 - * When included in a namespace path the special path element
211.139 - * <code>**</code> matches any number of sub namespaces
211.140 - * recursively, but only if used as a complete namespace path element,
211.141 - * as in <code>**//b//c//D:k=v</code> or <code>a//**//c//D:k=v</code>
211.142 - * - see ObjectName <a href="../ObjectName.html#metawildcard">documentation</a>
211.143 - * for more details.
211.144 - * </p>
211.145 - *
211.146 - *
211.147 - * </ul>
211.148 - *
211.149 - * <p>If you have a JMXNamespacePermission, it allows operations only
211.150 - * if all four of the items match.</p>
211.151 - *
211.152 - * <p>The <a href="#MBeanServerName">MBeanServer name</a>,
211.153 - * <a href="#Member">member</a>, and <a href="#MBeanName">object name</a>
211.154 - * can be written together
211.155 - * as a single string, which is the <em>name</em> of this permission.
211.156 - * The name of the permission is the string returned by {@link
211.157 - * java.security.Permission#getName() getName()}.
211.158 - * The format of the string is:</p>
211.159 - *
211.160 - * <blockquote>
211.161 - * {@code <mbean server name>::<member>[<namespace>//<mbean name>]}
211.162 - * </blockquote>
211.163 - *
211.164 - * <p>
211.165 - * The {@code <mbean server name>} is optional. If omitted, {@code "*"} is
211.166 - * assumed, and these three permission names
211.167 - * are thus equivalent:
211.168 - * </p>
211.169 - * <blockquote>
211.170 - * {@code *::<member>[<namespace>//<mbean name>]}<br>
211.171 - * {@code ::<member>[<namespace>//<mbean name>]}<br>
211.172 - * {@code <member>[<namespace>//<mbean name>]}<br>
211.173 - * </blockquote>
211.174 - * <p>
211.175 - * The {@code <namespace>//<mbean name>} string can be in the form
211.176 - * of a traditional ObjectName
211.177 - * pattern - meaning that <code>?</code> will match any single
211.178 - * character, and <code>*</code> will match any sequence of characters,
211.179 - * except {@value
211.180 - * javax.management.namespace.JMXNamespaces#NAMESPACE_SEPARATOR}
211.181 - * In addition, when included in a namespace path the special
211.182 - * path element <code>**</code> matches any number of sub namespaces
211.183 - * recursively.
211.184 - * A {@code <namespace>//<mbean name>} string of the form
211.185 - * <code>**//*:*</code> thus means that the permission is
211.186 - * granted for all MBeans in all namespaces, recursively (see
211.187 - * <a href="#metawildcard">below</a> for more details.
211.188 - * </p>
211.189 - * <p>Namespace permission checking may be tricky to configure, depending
211.190 - * on whether the namespaces crossed to reach the MBean are local or
211.191 - * remote.<br>
211.192 - * For instance, let <code>a//b//D:k=v</code> be an MBean exposing an
211.193 - * attribute <code>Foo</code>.
211.194 - * If namespace <code>a</code> is a plain JMXNamespace pointing to
211.195 - * a local MBeanServer in the same JVM, then the permissions you need
211.196 - * to get the attribute <code>Foo</code> will be:
211.197 - * </p>
211.198 - * <pre>
211.199 - * // granting permission to access attribute 'Foo' of MBean a//b//D:k=v
211.200 - * // from MBeanServer named 'srv1'
211.201 - * // This permission will be checked by the MBeanServer that contains 'a'.
211.202 - * srv1::Foo[a//b//D:k=v]
211.203 - *
211.204 - * // Since a is local, you also need the following additional permission,
211.205 - * // which will be checked by the MBeanServer 'srv2' that contains 'b':
211.206 - * //
211.207 - * // granting permission to access attribute 'Foo' of MBean b//D:k=v from
211.208 - * // 'srv2'
211.209 - * srv2::Foo[b//D:k=v]
211.210 - * </pre>
211.211 - * <p>On the other hand, if namespace <code>a</code> is a JMXRemoteNamespace
211.212 - * pointing to an MBeanServer in a remote JVM, then the only permission you
211.213 - * need to get the attribute <code>Foo</code> will be:
211.214 - * </p>
211.215 - * <pre>
211.216 - * // granting permission to access attribute 'Foo' of MBean a//b//D:k=v
211.217 - * // from 'srv1'
211.218 - * srv1::Foo[a//b//D:k=v]
211.219 - * </pre>
211.220 - * <p>The namespace <code>b</code> resides in the remote JVM, and
211.221 - * therefore the permissions concerning access to MBeans from
211.222 - * namespace 'b' will only be checked in the remote JVM, if that JVM is
211.223 - * configured to do so.
211.224 - * </p>
211.225 - *
211.226 - * <p>The {@code <mbean name>} is written using the usual syntax for {@link
211.227 - * ObjectName}. It may contain any legal characters, including
211.228 - * <code>]</code>. It is terminated by a <code>]</code> character
211.229 - * that is the last character in the string.
211.230 - * </p>
211.231 - * <p>Below are some examples of permission names:</p>
211.232 - * <pre>
211.233 - * // allows access to Foo in 'a//b//*:*' from any MBeanServer in the JVM.
211.234 - * Foo[a//b//*:*]
211.235 - *
211.236 - * // allows access to Foo in all subnamespaces of 'a//b', but only for
211.237 - * // MBeanServers whose name matches 'myapp.*'
211.238 - * myapp.*::Foo[a//b//**//*:*]
211.239 - *
211.240 - * // allows access to Foo from all namespaces in the MBeanServer named
211.241 - * // 'myapp.srv1' - but not recursively.
211.242 - * myapp.srv1::Foo[*//*:*]
211.243 - * </pre>
211.244 - * <p>For instance, the first two permissions listed above
211.245 - * will let through {@code getAttribute("a//b//D:k=v","Foo");} in
211.246 - * all MBeanServers, but will block access to
211.247 - * {@code getAttribute("a//b//c//D:k=v","Foo");} in MBeanServers whose
211.248 - * name do not start with {@code "myapp."}.
211.249 - * </p>
211.250 - * <p><a name="metawildcard">Depending on how your namespace hierarchy
211.251 - * is defined some of these wildcard permission names can be useful</a>:</p>
211.252 - * <pre>
211.253 - * // allows access to Foo in all namespaces, recursively.
211.254 - * //
211.255 - * *::Foo[**//*:*]
211.256 - *
211.257 - * // This permission name is the equivalent to the permission names above:
211.258 - * // Foo[**//*:*] and Foo[] are equivalent.
211.259 - * //
211.260 - * Foo[]
211.261 - *
211.262 - * // This permission name is the equivalent to the two permission names
211.263 - * // above:
211.264 - * // Foo[**//*:*], Foo[], Foo are equivalent.
211.265 - * //
211.266 - * Foo
211.267 - *
211.268 - * // allows access to Foo from all namespaces - but not recursively.
211.269 - * // This wildcard permission complements the previous one: it allows
211.270 - * // access to 'Foo' from an MBean directly registered in any local namespace.
211.271 - * //
211.272 - * Foo[*//*:*]
211.273 - *
211.274 - * </pre>
211.275 - * <p><b>Note on wildcards:</b> In an object name pattern, a path element
211.276 - * of exactly <code>**</code> corresponds to a meta
211.277 - * wildcard that will match any number of sub namespaces.
211.278 - * See ObjectName <a href="../ObjectName.html#metawildcard">documentation</a>
211.279 - * for more details.</p>
211.280 - *
211.281 - * <p>If {@code <mbean server name>::} is omitted, then one of
211.282 - * <code>member</code> or <code>object name</code> may be omitted.
211.283 - * If the <code>object name</code> is omitted,
211.284 - * the <code>[]</code> may be too (but does not have to be). It is
211.285 - * not legal to omit all items, that is to have a <em>name</em>
211.286 - * which is the empty string.</p>
211.287 - * <p>If {@code <mbean server name>} is present, it <b>must be followed</b> by
211.288 - * the {@code "::"} separator - otherwise it will be interpreted as
211.289 - * a {@code member name}.
211.290 - * </p>
211.291 - *
211.292 - * <p>
211.293 - * One or more of the <a href="#MBeanServerName">MBean Server name</a>,
211.294 - * <a href="#Member">member</a>
211.295 - * or <a href="#MBeanName">object name</a> may be the character "<code>-</code>",
211.296 - * which is equivalent to a null value. A null value is implied by
211.297 - * any value (including another null value) but does not imply any
211.298 - * other value.
211.299 - * </p>
211.300 - *
211.301 - * <p><a name="action-list">The possible actions are these:</a></p>
211.302 - *
211.303 - * <ul>
211.304 - * <li>addNotificationListener</li>
211.305 - * <li>getAttribute</li>
211.306 - * <li>getClassLoader</li>
211.307 - * <li>getClassLoaderFor</li>
211.308 - * <li>getClassLoaderRepository</li>
211.309 - * <li>getMBeanInfo</li>
211.310 - * <li>getObjectInstance</li>
211.311 - * <li>instantiate</li>
211.312 - * <li>invoke</li>
211.313 - * <li>isInstanceOf</li>
211.314 - * <li>queryMBeans</li>
211.315 - * <li>queryNames</li>
211.316 - * <li>registerMBean</li>
211.317 - * <li>removeNotificationListener</li>
211.318 - * <li>setAttribute</li>
211.319 - * <li>unregisterMBean</li>
211.320 - * </ul>
211.321 - *
211.322 - * <p>In a comma-separated list of actions, spaces are allowed before
211.323 - * and after each action.</p>
211.324 - *
211.325 - * @since 1.7
211.326 - */
211.327 -public class JMXNamespacePermission extends Permission {
211.328 -
211.329 - private static final long serialVersionUID = -2416928705275160661L;
211.330 -
211.331 - private static final String WILDPATH = "**" +
211.332 - JMXNamespaces.NAMESPACE_SEPARATOR + "*";
211.333 -
211.334 - /**
211.335 - * Actions list.
211.336 - */
211.337 - private static final int AddNotificationListener = 0x00001;
211.338 - private static final int GetAttribute = 0x00002;
211.339 - private static final int GetClassLoader = 0x00004;
211.340 - private static final int GetClassLoaderFor = 0x00008;
211.341 - private static final int GetClassLoaderRepository = 0x00010;
211.342 - // No GetDomains because it is not possible to route a call to
211.343 - // getDomains() on a NamespaceInterceptor - getDomains() doesn't
211.344 - // have any ObjectName.
211.345 - // private static final int GetDomains = 0x00020;
211.346 - private static final int GetMBeanInfo = 0x00040;
211.347 - private static final int GetObjectInstance = 0x00080;
211.348 - private static final int Instantiate = 0x00100;
211.349 - private static final int Invoke = 0x00200;
211.350 - private static final int IsInstanceOf = 0x00400;
211.351 - private static final int QueryMBeans = 0x00800;
211.352 - private static final int QueryNames = 0x01000;
211.353 - private static final int RegisterMBean = 0x02000;
211.354 - private static final int RemoveNotificationListener = 0x04000;
211.355 - private static final int SetAttribute = 0x08000;
211.356 - private static final int UnregisterMBean = 0x10000;
211.357 -
211.358 - /**
211.359 - * No actions.
211.360 - */
211.361 - private static final int NONE = 0x00000;
211.362 -
211.363 - /**
211.364 - * All actions.
211.365 - */
211.366 - // No GetDomains because it is not possible to route a call to
211.367 - // getDomains() on a NamespaceInterceptor - getDomains() doesn't
211.368 - // have any ObjectName.
211.369 - //
211.370 - private static final int ALL =
211.371 - AddNotificationListener |
211.372 - GetAttribute |
211.373 - GetClassLoader |
211.374 - GetClassLoaderFor |
211.375 - GetClassLoaderRepository |
211.376 - GetMBeanInfo |
211.377 - GetObjectInstance |
211.378 - Instantiate |
211.379 - Invoke |
211.380 - IsInstanceOf |
211.381 - QueryMBeans |
211.382 - QueryNames |
211.383 - RegisterMBean |
211.384 - RemoveNotificationListener |
211.385 - SetAttribute |
211.386 - UnregisterMBean;
211.387 -
211.388 - /**
211.389 - * The actions string.
211.390 - */
211.391 - private String actions;
211.392 -
211.393 - /**
211.394 - * The actions mask.
211.395 - */
211.396 - private transient int mask;
211.397 -
211.398 - /**
211.399 - * The name of the MBeanServer in which this permission is checked, or
211.400 - * granted. If null, is implied by any MBean server name
211.401 - * but does not imply any non-null MBean server name.
211.402 - */
211.403 - private transient String mbeanServerName;
211.404 -
211.405 - /**
211.406 - * The member that must match. If null, is implied by any member
211.407 - * but does not imply any non-null member.
211.408 - */
211.409 - private transient String member;
211.410 -
211.411 - /**
211.412 - * The objectName that must match. If null, is implied by any
211.413 - * objectName but does not imply any non-null objectName.
211.414 - */
211.415 - private transient ObjectName objectName;
211.416 -
211.417 - /**
211.418 - * If objectName is missing from name, then allnames will be
211.419 - * set to true.
211.420 - */
211.421 - private transient boolean allnames = false;
211.422 -
211.423 - /**
211.424 - * Parse <code>actions</code> parameter.
211.425 - */
211.426 - private void parseActions() {
211.427 -
211.428 - int amask;
211.429 -
211.430 - if (actions == null)
211.431 - throw new IllegalArgumentException("JMXNamespaceAccessPermission: " +
211.432 - "actions can't be null");
211.433 - if (actions.equals(""))
211.434 - throw new IllegalArgumentException("JMXNamespaceAccessPermission: " +
211.435 - "actions can't be empty");
211.436 -
211.437 - amask = getMask(actions);
211.438 -
211.439 - if ((amask & ALL) != amask)
211.440 - throw new IllegalArgumentException("Invalid actions mask");
211.441 - if (amask == NONE)
211.442 - throw new IllegalArgumentException("Invalid actions mask");
211.443 - this.mask = amask;
211.444 - }
211.445 -
211.446 - /**
211.447 - * Parse <code>name</code> parameter.
211.448 - */
211.449 - private void parseName() {
211.450 - String name = getName();
211.451 -
211.452 - if (name == null)
211.453 - throw new IllegalArgumentException("JMXNamespaceAccessPermission name " +
211.454 - "cannot be null");
211.455 -
211.456 - if (name.equals(""))
211.457 - throw new IllegalArgumentException("JMXNamespaceAccessPermission name " +
211.458 - "cannot be empty");
211.459 - final int sepIndex = name.indexOf("::");
211.460 - if (sepIndex < 0) {
211.461 - setMBeanServerName("*");
211.462 - } else {
211.463 - setMBeanServerName(name.substring(0,sepIndex));
211.464 - }
211.465 -
211.466 - /* The name looks like "mbeanServerName::member[objectname]".
211.467 - We subtract elements from the right as we parse, so after
211.468 - parsing the objectname we have "class#member" and after parsing the
211.469 - member we have "class". Each element is optional. */
211.470 -
211.471 - // Parse ObjectName
211.472 -
211.473 - final int start = (sepIndex<0)?0:sepIndex+2;
211.474 - int openingBracket = name.indexOf("[",start);
211.475 - if (openingBracket == -1) {
211.476 - // If "[on]" missing then ObjectName("*:*")
211.477 - //
211.478 - objectName = null;
211.479 - allnames = true;
211.480 - openingBracket=name.length();
211.481 - } else {
211.482 - if (!name.endsWith("]")) {
211.483 - throw new IllegalArgumentException("JMXNamespaceAccessPermission: " +
211.484 - "The ObjectName in the " +
211.485 - "target name must be " +
211.486 - "included in square " +
211.487 - "brackets");
211.488 - } else {
211.489 - // Create ObjectName
211.490 - //
211.491 - String on = name.substring(openingBracket + 1,
211.492 - name.length() - 1);
211.493 - try {
211.494 - // If "[]" then allnames are implied
211.495 - //
211.496 - final ObjectName target;
211.497 - final boolean all;
211.498 - if (on.equals("")) {
211.499 - target = null;
211.500 - all = true;
211.501 - } else if (on.equals("-")) {
211.502 - target = null;
211.503 - all = false;
211.504 - } else {
211.505 - target = new ObjectName(on);
211.506 - all = false;
211.507 - }
211.508 - setObjectName(target,all);
211.509 - } catch (MalformedObjectNameException e) {
211.510 - throw new IllegalArgumentException(
211.511 - "JMXNamespaceAccessPermission: " +
211.512 - "The target name does " +
211.513 - "not specify a valid " +
211.514 - "ObjectName", e);
211.515 - }
211.516 - }
211.517 - }
211.518 -
211.519 - final String memberName = name.substring(start,openingBracket);
211.520 - setMember(memberName);
211.521 - }
211.522 -
211.523 - private void setObjectName(ObjectName target, boolean all) {
211.524 - if (target != null &&
211.525 - !Util.wildpathmatch(target.getDomain(), WILDPATH)) {
211.526 - throw new IllegalArgumentException(
211.527 - "The target name does not contain " +
211.528 - "any namespace: "+String.valueOf(target));
211.529 - } else if (target != null) {
211.530 - final String domain = target.getDomain();
211.531 - final int seplen = JMXNamespaces.NAMESPACE_SEPARATOR.length();
211.532 - final int sepc = domain.indexOf(JMXNamespaces.NAMESPACE_SEPARATOR);
211.533 - if (sepc < 0 || (sepc+seplen)==domain.length()) {
211.534 - throw new IllegalArgumentException(String.valueOf(target)+
211.535 - ": no namespace in domain");
211.536 - }
211.537 - }
211.538 - objectName = target;
211.539 - allnames = all;
211.540 - }
211.541 -
211.542 - /**
211.543 - * Assign fields based on className, member, and objectName
211.544 - * parameters.
211.545 - */
211.546 -// private void initName(String namespaceName, String member,
211.547 -// ObjectName objectName, boolean allnames) {
211.548 -// setNamespace(namespaceName);
211.549 - private void initName(String mbeanServerName, String member,
211.550 - ObjectName mbeanName, boolean all) {
211.551 - setMBeanServerName(mbeanServerName);
211.552 - setMember(member);
211.553 - setObjectName(mbeanName, all);
211.554 - }
211.555 -
211.556 - private void setMBeanServerName(String mbeanServerName) {
211.557 - if (mbeanServerName == null || mbeanServerName.equals("-")) {
211.558 - this.mbeanServerName = null;
211.559 - } else if (mbeanServerName.equals("")) {
211.560 - this.mbeanServerName = "*";
211.561 - } else {
211.562 - this.mbeanServerName = mbeanServerName;
211.563 - }
211.564 - }
211.565 -
211.566 - private void setMember(String member) {
211.567 - if (member == null || member.equals("-"))
211.568 - this.member = null;
211.569 - else if (member.equals(""))
211.570 - this.member = "*";
211.571 - else
211.572 - this.member = member;
211.573 - }
211.574 -
211.575 - /**
211.576 - * <p>Create a new JMXNamespacePermission object with the
211.577 - * specified target name and actions.</p>
211.578 - *
211.579 - * <p>The target name is of the form
211.580 - * "<code>mbeanServerName::member[objectName]</code>" where each part is
211.581 - * optional. This target name must not be empty or null.
211.582 - * If <code>objectName</code> is present, it is of
211.583 - * the form <code>namespace//MBeanName</code>.
211.584 - * </p>
211.585 - * <p>
211.586 - * For a permission you need, {@code mbeanServerName} is the
211.587 - * <a href="#MBeanServerName">name of the MBeanServer</a> from
211.588 - * which {@code objectName} is being accessed.
211.589 - * </p>
211.590 - * <p>
211.591 - * For a permission you have, {@code mbeanServerName} is the
211.592 - * <a href="#MBeanServerName">name of the MBeanServer</a> from
211.593 - * which access to {@code objectName} is granted.
211.594 - * It can also be a pattern, and if omitted, {@code "*"} is assumed,
211.595 - * meaning that access to {@code objectName} is granted in all
211.596 - * MBean servers in the JVM.
211.597 - * </p>
211.598 - *
211.599 - * <p>The actions parameter contains a comma-separated list of the
211.600 - * desired actions granted on the target name. It must not be
211.601 - * empty or null.</p>
211.602 - *
211.603 - * @param name the triplet "mbeanServerName::member[objectName]".
211.604 - * If <code>objectName</code> is present, it is of
211.605 - * the form <code>namespace//MBeanName</code>.
211.606 - * @param actions the action string.
211.607 - *
211.608 - * @exception IllegalArgumentException if the <code>name</code> or
211.609 - * <code>actions</code> is invalid.
211.610 - */
211.611 - public JMXNamespacePermission(String name, String actions) {
211.612 - super(name);
211.613 -
211.614 - parseName();
211.615 -
211.616 - this.actions = actions;
211.617 - parseActions();
211.618 - }
211.619 -
211.620 - /**
211.621 - * <p>Create a new JMXNamespacePermission object with the specified
211.622 - * target name (namespace name, member, object name) and actions.</p>
211.623 - *
211.624 - * <p>The {@code MBeanServer} name, member and object name
211.625 - * parameters define a target name of the form
211.626 - * "<code>mbeanServerName::member[objectName]</code>" where each
211.627 - * part is optional. This will be the result of {@link #getName()} on the
211.628 - * resultant JMXNamespacePermission.
211.629 - * If the <code>mbeanServerName</code> is empty or exactly {@code "*"}, then
211.630 - * "{@code mbeanServerName::}" is omitted in that result.
211.631 - * </p>
211.632 - *
211.633 - * <p>The actions parameter contains a comma-separated list of the
211.634 - * desired actions granted on the target name. It must not be
211.635 - * empty or null.</p>
211.636 - *
211.637 - * @param mbeanServerName the name of the {@code MBeanServer} to which this
211.638 - * permission applies.
211.639 - * May be null or <code>"-"</code>, which represents an MBeanServer name
211.640 - * that is implied by any MBeanServer name but does not imply any other
211.641 - * MBeanServer name.
211.642 - * @param member the member to which this permission applies. May
211.643 - * be null or <code>"-"</code>, which represents a member that is
211.644 - * implied by any member but does not imply any other member.
211.645 - * @param objectName the object name to which this permission
211.646 - * applies.
211.647 - * May be null, which represents an object name that is
211.648 - * implied by any object name but does not imply any other object
211.649 - * name. If not null, the {@code objectName} must be of the
211.650 - * form {@code <namespace>//<mbean name>} - where {@code <namespace>}
211.651 - * can be a domain pattern, and {@code <mbean name>} can be an ObjectName
211.652 - * pattern.
211.653 - * For a permission you need, {@code <namespace>} is the name of the
211.654 - * name space for which the permission is checked, and {@code <mbean name>}
211.655 - * is the name of the MBean in that namespace.
211.656 - * The composed name {@code <namespace>//<mbean name>} thus represents the
211.657 - * name of the MBean as seen by the {@code mbeanServerName} containing
211.658 - * {@code <namespace>}.
211.659 - *
211.660 - * @param actions the action string.
211.661 - */
211.662 - public JMXNamespacePermission(
211.663 - String mbeanServerName,
211.664 - String member,
211.665 - ObjectName objectName,
211.666 - String actions) {
211.667 - this(mbeanServerName, member, objectName, false, actions);
211.668 -// this(member, objectName, false, actions);
211.669 - }
211.670 -
211.671 - /**
211.672 - * <p>Create a new JMXNamespacePermission object with the specified
211.673 - * MBean Server name, member, and actions.</p>
211.674 - *
211.675 - * <p>The {@code MBeanServer} name and member
211.676 - * parameters define a target name of the form
211.677 - * "<code>mbeanServerName::member[]</code>" where each
211.678 - * part is optional. This will be the result of {@link #getName()} on the
211.679 - * resultant JMXNamespacePermission.
211.680 - * If the <code>mbeanServerName</code> is empty or exactly {@code "*"}, then
211.681 - * "{@code mbeanServerName::}" is omitted in that result.
211.682 - * </p>
211.683 - *
211.684 - * <p>The actions parameter contains a comma-separated list of the
211.685 - * desired actions granted on the target name. It must not be
211.686 - * empty or null.</p>
211.687 - *
211.688 - * @param mbeanServerName the name of the {@code MBeanServer} to which this
211.689 - * permission applies.
211.690 - * May be null or <code>"-"</code>, which represents an MBeanServer name
211.691 - * that is implied by any MBeanServer name but does not imply any other
211.692 - * MBeanServer name.
211.693 - * @param member the member to which this permission applies. May
211.694 - * be null or <code>"-"</code>, which represents a member that is
211.695 - * implied by any member but does not imply any other member.
211.696 - * @param actions the action string.
211.697 - */
211.698 - public JMXNamespacePermission(String mbeanServerName,
211.699 - String member,
211.700 - String actions) {
211.701 - this(mbeanServerName,member,null,true,actions);
211.702 - // this(member,null,allnames,actions);
211.703 - }
211.704 -
211.705 - /**
211.706 - * <p>Create a new JMXNamespacePermission object with the specified
211.707 - * target name (namespace name, member, object name) and actions.</p>
211.708 - *
211.709 - * <p>The MBean Server name, member and object name parameters define a
211.710 - * target name of the form
211.711 - * "<code>mbeanServerName::member[objectName]</code>" where each part is
211.712 - * optional. This will be the result of {@link
211.713 - * java.security.Permission#getName() getName()} on the
211.714 - * resultant JMXNamespacePermission.</p>
211.715 - *
211.716 - * <p>The actions parameter contains a comma-separated list of the
211.717 - * desired actions granted on the target name. It must not be
211.718 - * empty or null.</p>
211.719 - *
211.720 - * @param mbeanServerName the name of the {@code MBeanServer} to which this
211.721 - * permission applies.
211.722 - * May be null or <code>"-"</code>, which represents an MBeanServer name
211.723 - * that is implied by any MBeanServer name but does not imply any other
211.724 - * MBeanServer name.
211.725 - * @param member the member to which this permission applies. May
211.726 - * be null or <code>"-"</code>, which represents a member that is
211.727 - * implied by any member but does not imply any other member.
211.728 - * @param objectName the object name to which this permission
211.729 - * applies. If null, and allnames is false, represents an object
211.730 - * name that is implied by any object name but does not imply any
211.731 - * other object name. Otherwise, if allnames is true, it represents
211.732 - * a meta wildcard that matches all object names. It is equivalent to
211.733 - * a missing objectName ("[]") in the {@link
211.734 - * java.security.Permission#getName() name} property.
211.735 - * @param allnames represent a meta wildcard indicating that the
211.736 - * objectName was not specified. This implies all objectnames
211.737 - * that match "*:*" and all object names that match
211.738 - * "**//*:*"
211.739 - * @param actions the action string.
211.740 - */
211.741 - private JMXNamespacePermission(String mbeanServerName,
211.742 - String member,
211.743 - ObjectName objectName,
211.744 - boolean allnames,
211.745 - String actions) {
211.746 -
211.747 - super(makeName(mbeanServerName,
211.748 - member, objectName, allnames));
211.749 - initName(mbeanServerName,
211.750 - member, objectName, allnames);
211.751 -
211.752 - this.actions = actions;
211.753 - parseActions();
211.754 - }
211.755 -
211.756 - private static String makeName(String mbeanServerName,
211.757 - String memberName, ObjectName objName, boolean allMBeans) {
211.758 - final StringBuilder name = new StringBuilder();
211.759 - if (mbeanServerName == null)
211.760 - mbeanServerName = "-";
211.761 - if (!mbeanServerName.equals("") && !mbeanServerName.equals("*"))
211.762 - name.append(mbeanServerName).append("::");
211.763 - if (memberName == null)
211.764 - memberName = "-";
211.765 - name.append(memberName);
211.766 - if (objName == null) {
211.767 - if (allMBeans)
211.768 - name.append("[]");
211.769 - else
211.770 - name.append("[-]");
211.771 - } else {
211.772 - final String domain = objName.getDomain();
211.773 - final int seplen = JMXNamespaces.NAMESPACE_SEPARATOR.length();
211.774 - final int sepc = domain.indexOf(JMXNamespaces.NAMESPACE_SEPARATOR);
211.775 - if (sepc < 0 || (sepc+seplen)==domain.length()) {
211.776 - throw new IllegalArgumentException(String.valueOf(objName)+
211.777 - ": no namespace in domain");
211.778 - }
211.779 - final String can = objName.getCanonicalName();
211.780 - name.append("[").append(can).append("]");
211.781 - }
211.782 - return name.toString();
211.783 - }
211.784 -
211.785 - /**
211.786 - * Returns the "canonical string representation" of the actions. That is,
211.787 - * this method always returns actions in alphabetical order.
211.788 - *
211.789 - * @return the canonical string representation of the actions.
211.790 - */
211.791 - public String getActions() {
211.792 -
211.793 - if (actions == null)
211.794 - actions = getActions(this.mask);
211.795 -
211.796 - return actions;
211.797 - }
211.798 -
211.799 - /**
211.800 - * Returns the "canonical string representation"
211.801 - * of the actions from the mask.
211.802 - */
211.803 - private static String getActions(int mask) {
211.804 - final StringBuilder sb = new StringBuilder();
211.805 - boolean comma = false;
211.806 -
211.807 - if ((mask & AddNotificationListener) == AddNotificationListener) {
211.808 - comma = true;
211.809 - sb.append("addNotificationListener");
211.810 - }
211.811 -
211.812 - if ((mask & GetAttribute) == GetAttribute) {
211.813 - if (comma) sb.append(',');
211.814 - else comma = true;
211.815 - sb.append("getAttribute");
211.816 - }
211.817 -
211.818 - if ((mask & GetClassLoader) == GetClassLoader) {
211.819 - if (comma) sb.append(',');
211.820 - else comma = true;
211.821 - sb.append("getClassLoader");
211.822 - }
211.823 -
211.824 - if ((mask & GetClassLoaderFor) == GetClassLoaderFor) {
211.825 - if (comma) sb.append(',');
211.826 - else comma = true;
211.827 - sb.append("getClassLoaderFor");
211.828 - }
211.829 -
211.830 - if ((mask & GetClassLoaderRepository) == GetClassLoaderRepository) {
211.831 - if (comma) sb.append(',');
211.832 - else comma = true;
211.833 - sb.append("getClassLoaderRepository");
211.834 - }
211.835 -
211.836 - if ((mask & GetMBeanInfo) == GetMBeanInfo) {
211.837 - if (comma) sb.append(',');
211.838 - else comma = true;
211.839 - sb.append("getMBeanInfo");
211.840 - }
211.841 -
211.842 - if ((mask & GetObjectInstance) == GetObjectInstance) {
211.843 - if (comma) sb.append(',');
211.844 - else comma = true;
211.845 - sb.append("getObjectInstance");
211.846 - }
211.847 -
211.848 - if ((mask & Instantiate) == Instantiate) {
211.849 - if (comma) sb.append(',');
211.850 - else comma = true;
211.851 - sb.append("instantiate");
211.852 - }
211.853 -
211.854 - if ((mask & Invoke) == Invoke) {
211.855 - if (comma) sb.append(',');
211.856 - else comma = true;
211.857 - sb.append("invoke");
211.858 - }
211.859 -
211.860 - if ((mask & IsInstanceOf) == IsInstanceOf) {
211.861 - if (comma) sb.append(',');
211.862 - else comma = true;
211.863 - sb.append("isInstanceOf");
211.864 - }
211.865 -
211.866 - if ((mask & QueryMBeans) == QueryMBeans) {
211.867 - if (comma) sb.append(',');
211.868 - else comma = true;
211.869 - sb.append("queryMBeans");
211.870 - }
211.871 -
211.872 - if ((mask & QueryNames) == QueryNames) {
211.873 - if (comma) sb.append(',');
211.874 - else comma = true;
211.875 - sb.append("queryNames");
211.876 - }
211.877 -
211.878 - if ((mask & RegisterMBean) == RegisterMBean) {
211.879 - if (comma) sb.append(',');
211.880 - else comma = true;
211.881 - sb.append("registerMBean");
211.882 - }
211.883 -
211.884 - if ((mask & RemoveNotificationListener) == RemoveNotificationListener) {
211.885 - if (comma) sb.append(',');
211.886 - else comma = true;
211.887 - sb.append("removeNotificationListener");
211.888 - }
211.889 -
211.890 - if ((mask & SetAttribute) == SetAttribute) {
211.891 - if (comma) sb.append(',');
211.892 - else comma = true;
211.893 - sb.append("setAttribute");
211.894 - }
211.895 -
211.896 - if ((mask & UnregisterMBean) == UnregisterMBean) {
211.897 - if (comma) sb.append(',');
211.898 - else comma = true;
211.899 - sb.append("unregisterMBean");
211.900 - }
211.901 -
211.902 - // No GetDomains because it is not possible to route a call to
211.903 - // getDomains() on a NamespaceInterceptor - getDomains() doesn't
211.904 - // have any ObjectName.
211.905 -
211.906 - return sb.toString();
211.907 - }
211.908 -
211.909 - @Override
211.910 - public int hashCode() {
211.911 - return this.getName().hashCode() + this.getActions().hashCode();
211.912 - }
211.913 -
211.914 - /**
211.915 - * Converts an action String to an integer action mask.
211.916 - *
211.917 - * @param action the action string.
211.918 - * @return the action mask.
211.919 - */
211.920 - private static int getMask(String action) {
211.921 -
211.922 - /*
211.923 - * BE CAREFUL HERE! PARSING ORDER IS IMPORTANT IN THIS ALGORITHM.
211.924 - *
211.925 - * The 'string length' test must be performed for the lengthiest
211.926 - * strings first.
211.927 - *
211.928 - * In this permission if the "unregisterMBean" string length test is
211.929 - * performed after the "registerMBean" string length test the algorithm
211.930 - * considers the 'unregisterMBean' action as being the 'registerMBean'
211.931 - * action and a parsing error is returned.
211.932 - */
211.933 -
211.934 - int mask = NONE;
211.935 -
211.936 - if (action == null) {
211.937 - return mask;
211.938 - }
211.939 -
211.940 - if (action.equals("*")) {
211.941 - return ALL;
211.942 - }
211.943 -
211.944 - char[] a = action.toCharArray();
211.945 -
211.946 - int i = a.length - 1;
211.947 - if (i < 0)
211.948 - return mask;
211.949 -
211.950 - while (i != -1) {
211.951 - char c;
211.952 -
211.953 - // skip whitespace
211.954 - while ((i!=-1) && ((c = a[i]) == ' ' ||
211.955 - c == '\r' ||
211.956 - c == '\n' ||
211.957 - c == '\f' ||
211.958 - c == '\t'))
211.959 - i--;
211.960 -
211.961 - // check for the known strings
211.962 - int matchlen;
211.963 -
211.964 - // No GetDomains because it is not possible to route a call to
211.965 - // getDomains() on a NamespaceInterceptor - getDomains() doesn't
211.966 - // have any ObjectName.
211.967 -
211.968 - if (i >= 25 && /* removeNotificationListener */
211.969 - (a[i-25] == 'r') &&
211.970 - (a[i-24] == 'e') &&
211.971 - (a[i-23] == 'm') &&
211.972 - (a[i-22] == 'o') &&
211.973 - (a[i-21] == 'v') &&
211.974 - (a[i-20] == 'e') &&
211.975 - (a[i-19] == 'N') &&
211.976 - (a[i-18] == 'o') &&
211.977 - (a[i-17] == 't') &&
211.978 - (a[i-16] == 'i') &&
211.979 - (a[i-15] == 'f') &&
211.980 - (a[i-14] == 'i') &&
211.981 - (a[i-13] == 'c') &&
211.982 - (a[i-12] == 'a') &&
211.983 - (a[i-11] == 't') &&
211.984 - (a[i-10] == 'i') &&
211.985 - (a[i-9] == 'o') &&
211.986 - (a[i-8] == 'n') &&
211.987 - (a[i-7] == 'L') &&
211.988 - (a[i-6] == 'i') &&
211.989 - (a[i-5] == 's') &&
211.990 - (a[i-4] == 't') &&
211.991 - (a[i-3] == 'e') &&
211.992 - (a[i-2] == 'n') &&
211.993 - (a[i-1] == 'e') &&
211.994 - (a[i] == 'r')) {
211.995 - matchlen = 26;
211.996 - mask |= RemoveNotificationListener;
211.997 - } else if (i >= 23 && /* getClassLoaderRepository */
211.998 - (a[i-23] == 'g') &&
211.999 - (a[i-22] == 'e') &&
211.1000 - (a[i-21] == 't') &&
211.1001 - (a[i-20] == 'C') &&
211.1002 - (a[i-19] == 'l') &&
211.1003 - (a[i-18] == 'a') &&
211.1004 - (a[i-17] == 's') &&
211.1005 - (a[i-16] == 's') &&
211.1006 - (a[i-15] == 'L') &&
211.1007 - (a[i-14] == 'o') &&
211.1008 - (a[i-13] == 'a') &&
211.1009 - (a[i-12] == 'd') &&
211.1010 - (a[i-11] == 'e') &&
211.1011 - (a[i-10] == 'r') &&
211.1012 - (a[i-9] == 'R') &&
211.1013 - (a[i-8] == 'e') &&
211.1014 - (a[i-7] == 'p') &&
211.1015 - (a[i-6] == 'o') &&
211.1016 - (a[i-5] == 's') &&
211.1017 - (a[i-4] == 'i') &&
211.1018 - (a[i-3] == 't') &&
211.1019 - (a[i-2] == 'o') &&
211.1020 - (a[i-1] == 'r') &&
211.1021 - (a[i] == 'y')) {
211.1022 - matchlen = 24;
211.1023 - mask |= GetClassLoaderRepository;
211.1024 - } else if (i >= 22 && /* addNotificationListener */
211.1025 - (a[i-22] == 'a') &&
211.1026 - (a[i-21] == 'd') &&
211.1027 - (a[i-20] == 'd') &&
211.1028 - (a[i-19] == 'N') &&
211.1029 - (a[i-18] == 'o') &&
211.1030 - (a[i-17] == 't') &&
211.1031 - (a[i-16] == 'i') &&
211.1032 - (a[i-15] == 'f') &&
211.1033 - (a[i-14] == 'i') &&
211.1034 - (a[i-13] == 'c') &&
211.1035 - (a[i-12] == 'a') &&
211.1036 - (a[i-11] == 't') &&
211.1037 - (a[i-10] == 'i') &&
211.1038 - (a[i-9] == 'o') &&
211.1039 - (a[i-8] == 'n') &&
211.1040 - (a[i-7] == 'L') &&
211.1041 - (a[i-6] == 'i') &&
211.1042 - (a[i-5] == 's') &&
211.1043 - (a[i-4] == 't') &&
211.1044 - (a[i-3] == 'e') &&
211.1045 - (a[i-2] == 'n') &&
211.1046 - (a[i-1] == 'e') &&
211.1047 - (a[i] == 'r')) {
211.1048 - matchlen = 23;
211.1049 - mask |= AddNotificationListener;
211.1050 - } else if (i >= 16 && /* getClassLoaderFor */
211.1051 - (a[i-16] == 'g') &&
211.1052 - (a[i-15] == 'e') &&
211.1053 - (a[i-14] == 't') &&
211.1054 - (a[i-13] == 'C') &&
211.1055 - (a[i-12] == 'l') &&
211.1056 - (a[i-11] == 'a') &&
211.1057 - (a[i-10] == 's') &&
211.1058 - (a[i-9] == 's') &&
211.1059 - (a[i-8] == 'L') &&
211.1060 - (a[i-7] == 'o') &&
211.1061 - (a[i-6] == 'a') &&
211.1062 - (a[i-5] == 'd') &&
211.1063 - (a[i-4] == 'e') &&
211.1064 - (a[i-3] == 'r') &&
211.1065 - (a[i-2] == 'F') &&
211.1066 - (a[i-1] == 'o') &&
211.1067 - (a[i] == 'r')) {
211.1068 - matchlen = 17;
211.1069 - mask |= GetClassLoaderFor;
211.1070 - } else if (i >= 16 && /* getObjectInstance */
211.1071 - (a[i-16] == 'g') &&
211.1072 - (a[i-15] == 'e') &&
211.1073 - (a[i-14] == 't') &&
211.1074 - (a[i-13] == 'O') &&
211.1075 - (a[i-12] == 'b') &&
211.1076 - (a[i-11] == 'j') &&
211.1077 - (a[i-10] == 'e') &&
211.1078 - (a[i-9] == 'c') &&
211.1079 - (a[i-8] == 't') &&
211.1080 - (a[i-7] == 'I') &&
211.1081 - (a[i-6] == 'n') &&
211.1082 - (a[i-5] == 's') &&
211.1083 - (a[i-4] == 't') &&
211.1084 - (a[i-3] == 'a') &&
211.1085 - (a[i-2] == 'n') &&
211.1086 - (a[i-1] == 'c') &&
211.1087 - (a[i] == 'e')) {
211.1088 - matchlen = 17;
211.1089 - mask |= GetObjectInstance;
211.1090 - } else if (i >= 14 && /* unregisterMBean */
211.1091 - (a[i-14] == 'u') &&
211.1092 - (a[i-13] == 'n') &&
211.1093 - (a[i-12] == 'r') &&
211.1094 - (a[i-11] == 'e') &&
211.1095 - (a[i-10] == 'g') &&
211.1096 - (a[i-9] == 'i') &&
211.1097 - (a[i-8] == 's') &&
211.1098 - (a[i-7] == 't') &&
211.1099 - (a[i-6] == 'e') &&
211.1100 - (a[i-5] == 'r') &&
211.1101 - (a[i-4] == 'M') &&
211.1102 - (a[i-3] == 'B') &&
211.1103 - (a[i-2] == 'e') &&
211.1104 - (a[i-1] == 'a') &&
211.1105 - (a[i] == 'n')) {
211.1106 - matchlen = 15;
211.1107 - mask |= UnregisterMBean;
211.1108 - } else if (i >= 13 && /* getClassLoader */
211.1109 - (a[i-13] == 'g') &&
211.1110 - (a[i-12] == 'e') &&
211.1111 - (a[i-11] == 't') &&
211.1112 - (a[i-10] == 'C') &&
211.1113 - (a[i-9] == 'l') &&
211.1114 - (a[i-8] == 'a') &&
211.1115 - (a[i-7] == 's') &&
211.1116 - (a[i-6] == 's') &&
211.1117 - (a[i-5] == 'L') &&
211.1118 - (a[i-4] == 'o') &&
211.1119 - (a[i-3] == 'a') &&
211.1120 - (a[i-2] == 'd') &&
211.1121 - (a[i-1] == 'e') &&
211.1122 - (a[i] == 'r')) {
211.1123 - matchlen = 14;
211.1124 - mask |= GetClassLoader;
211.1125 - } else if (i >= 12 && /* registerMBean */
211.1126 - (a[i-12] == 'r') &&
211.1127 - (a[i-11] == 'e') &&
211.1128 - (a[i-10] == 'g') &&
211.1129 - (a[i-9] == 'i') &&
211.1130 - (a[i-8] == 's') &&
211.1131 - (a[i-7] == 't') &&
211.1132 - (a[i-6] == 'e') &&
211.1133 - (a[i-5] == 'r') &&
211.1134 - (a[i-4] == 'M') &&
211.1135 - (a[i-3] == 'B') &&
211.1136 - (a[i-2] == 'e') &&
211.1137 - (a[i-1] == 'a') &&
211.1138 - (a[i] == 'n')) {
211.1139 - matchlen = 13;
211.1140 - mask |= RegisterMBean;
211.1141 - } else if (i >= 11 && /* getAttribute */
211.1142 - (a[i-11] == 'g') &&
211.1143 - (a[i-10] == 'e') &&
211.1144 - (a[i-9] == 't') &&
211.1145 - (a[i-8] == 'A') &&
211.1146 - (a[i-7] == 't') &&
211.1147 - (a[i-6] == 't') &&
211.1148 - (a[i-5] == 'r') &&
211.1149 - (a[i-4] == 'i') &&
211.1150 - (a[i-3] == 'b') &&
211.1151 - (a[i-2] == 'u') &&
211.1152 - (a[i-1] == 't') &&
211.1153 - (a[i] == 'e')) {
211.1154 - matchlen = 12;
211.1155 - mask |= GetAttribute;
211.1156 - } else if (i >= 11 && /* getMBeanInfo */
211.1157 - (a[i-11] == 'g') &&
211.1158 - (a[i-10] == 'e') &&
211.1159 - (a[i-9] == 't') &&
211.1160 - (a[i-8] == 'M') &&
211.1161 - (a[i-7] == 'B') &&
211.1162 - (a[i-6] == 'e') &&
211.1163 - (a[i-5] == 'a') &&
211.1164 - (a[i-4] == 'n') &&
211.1165 - (a[i-3] == 'I') &&
211.1166 - (a[i-2] == 'n') &&
211.1167 - (a[i-1] == 'f') &&
211.1168 - (a[i] == 'o')) {
211.1169 - matchlen = 12;
211.1170 - mask |= GetMBeanInfo;
211.1171 - } else if (i >= 11 && /* isInstanceOf */
211.1172 - (a[i-11] == 'i') &&
211.1173 - (a[i-10] == 's') &&
211.1174 - (a[i-9] == 'I') &&
211.1175 - (a[i-8] == 'n') &&
211.1176 - (a[i-7] == 's') &&
211.1177 - (a[i-6] == 't') &&
211.1178 - (a[i-5] == 'a') &&
211.1179 - (a[i-4] == 'n') &&
211.1180 - (a[i-3] == 'c') &&
211.1181 - (a[i-2] == 'e') &&
211.1182 - (a[i-1] == 'O') &&
211.1183 - (a[i] == 'f')) {
211.1184 - matchlen = 12;
211.1185 - mask |= IsInstanceOf;
211.1186 - } else if (i >= 11 && /* setAttribute */
211.1187 - (a[i-11] == 's') &&
211.1188 - (a[i-10] == 'e') &&
211.1189 - (a[i-9] == 't') &&
211.1190 - (a[i-8] == 'A') &&
211.1191 - (a[i-7] == 't') &&
211.1192 - (a[i-6] == 't') &&
211.1193 - (a[i-5] == 'r') &&
211.1194 - (a[i-4] == 'i') &&
211.1195 - (a[i-3] == 'b') &&
211.1196 - (a[i-2] == 'u') &&
211.1197 - (a[i-1] == 't') &&
211.1198 - (a[i] == 'e')) {
211.1199 - matchlen = 12;
211.1200 - mask |= SetAttribute;
211.1201 - } else if (i >= 10 && /* instantiate */
211.1202 - (a[i-10] == 'i') &&
211.1203 - (a[i-9] == 'n') &&
211.1204 - (a[i-8] == 's') &&
211.1205 - (a[i-7] == 't') &&
211.1206 - (a[i-6] == 'a') &&
211.1207 - (a[i-5] == 'n') &&
211.1208 - (a[i-4] == 't') &&
211.1209 - (a[i-3] == 'i') &&
211.1210 - (a[i-2] == 'a') &&
211.1211 - (a[i-1] == 't') &&
211.1212 - (a[i] == 'e')) {
211.1213 - matchlen = 11;
211.1214 - mask |= Instantiate;
211.1215 - } else if (i >= 10 && /* queryMBeans */
211.1216 - (a[i-10] == 'q') &&
211.1217 - (a[i-9] == 'u') &&
211.1218 - (a[i-8] == 'e') &&
211.1219 - (a[i-7] == 'r') &&
211.1220 - (a[i-6] == 'y') &&
211.1221 - (a[i-5] == 'M') &&
211.1222 - (a[i-4] == 'B') &&
211.1223 - (a[i-3] == 'e') &&
211.1224 - (a[i-2] == 'a') &&
211.1225 - (a[i-1] == 'n') &&
211.1226 - (a[i] == 's')) {
211.1227 - matchlen = 11;
211.1228 - mask |= QueryMBeans;
211.1229 - } else if (i >= 9 && /* queryNames */
211.1230 - (a[i-9] == 'q') &&
211.1231 - (a[i-8] == 'u') &&
211.1232 - (a[i-7] == 'e') &&
211.1233 - (a[i-6] == 'r') &&
211.1234 - (a[i-5] == 'y') &&
211.1235 - (a[i-4] == 'N') &&
211.1236 - (a[i-3] == 'a') &&
211.1237 - (a[i-2] == 'm') &&
211.1238 - (a[i-1] == 'e') &&
211.1239 - (a[i] == 's')) {
211.1240 - matchlen = 10;
211.1241 - mask |= QueryNames;
211.1242 - } else if (i >= 5 && /* invoke */
211.1243 - (a[i-5] == 'i') &&
211.1244 - (a[i-4] == 'n') &&
211.1245 - (a[i-3] == 'v') &&
211.1246 - (a[i-2] == 'o') &&
211.1247 - (a[i-1] == 'k') &&
211.1248 - (a[i] == 'e')) {
211.1249 - matchlen = 6;
211.1250 - mask |= Invoke;
211.1251 - } else {
211.1252 - // parse error
211.1253 - throw new IllegalArgumentException("Invalid permission: " +
211.1254 - action);
211.1255 - }
211.1256 -
211.1257 - // make sure we didn't just match the tail of a word
211.1258 - // like "ackbarfaccept". Also, skip to the comma.
211.1259 - boolean seencomma = false;
211.1260 - while (i >= matchlen && !seencomma) {
211.1261 - switch(a[i-matchlen]) {
211.1262 - case ',':
211.1263 - seencomma = true;
211.1264 - break;
211.1265 - case ' ': case '\r': case '\n':
211.1266 - case '\f': case '\t':
211.1267 - break;
211.1268 - default:
211.1269 - throw new IllegalArgumentException("Invalid permission: " +
211.1270 - action);
211.1271 - }
211.1272 - i--;
211.1273 - }
211.1274 -
211.1275 - // point i at the location of the comma minus one (or -1).
211.1276 - i -= matchlen;
211.1277 - }
211.1278 -
211.1279 - return mask;
211.1280 - }
211.1281 -
211.1282 - /**
211.1283 - * <p>Checks if this JMXNamespacePermission object "implies" the
211.1284 - * specified permission.</p>
211.1285 - *
211.1286 - * <p>More specifically, this method returns true if:</p>
211.1287 - *
211.1288 - * <ul>
211.1289 - *
211.1290 - * <li> <i>p</i> is an instance of JMXNamespacePermission; and</li>
211.1291 - *
211.1292 - * <li> <i>p</i> has a null mbeanServerName or <i>p</i>'s mbeanServerName
211.1293 - * matches this object's mbeanServerName; and</li>
211.1294 - *
211.1295 - * <li> <i>p</i> has a null member or <i>p</i>'s member matches this
211.1296 - * object's member; and</li>
211.1297 - *
211.1298 - * <li> <i>p</i> has a null object name or <i>p</i>'s
211.1299 - * object name matches this object's object name; and</li>
211.1300 - *
211.1301 - * <li> <i>p</i>'s actions are a subset of this object's actions</li>
211.1302 - *
211.1303 - * </ul>
211.1304 - *
211.1305 - * <p>If this object's mbeanServerName is a pattern, then <i>p</i>'s
211.1306 - * mbeanServerName is matched against that pattern. An empty
211.1307 - * mbeanServerName is equivalent to "{@code *}". A null
211.1308 - * mbeanServerName is equivalent to "{@code -}".</p>
211.1309 - * <p>If this object's mbeanServerName is "<code>*</code>" or is
211.1310 - * empty, <i>p</i>'s mbeanServerName always matches it.</p>
211.1311 - *
211.1312 - * <p>If this object's member is "<code>*</code>", <i>p</i>'s
211.1313 - * member always matches it.</p>
211.1314 - *
211.1315 - * <p>If this object's objectName <i>n1</i> is an object name pattern,
211.1316 - * <i>p</i>'s objectName <i>n2</i> matches it if
211.1317 - * {@link ObjectName#equals <i>n1</i>.equals(<i>n2</i>)} or if
211.1318 - * {@link ObjectName#apply <i>n1</i>.apply(<i>n2</i>)}.</p>
211.1319 - *
211.1320 - * <p>A permission that includes the <code>queryMBeans</code> action
211.1321 - * is considered to include <code>queryNames</code> as well.</p>
211.1322 - *
211.1323 - * @param p the permission to check against.
211.1324 - * @return true if the specified permission is implied by this object,
211.1325 - * false if not.
211.1326 - */
211.1327 - public boolean implies(Permission p) {
211.1328 - if (!(p instanceof JMXNamespacePermission))
211.1329 - return false;
211.1330 -
211.1331 - JMXNamespacePermission that = (JMXNamespacePermission) p;
211.1332 -
211.1333 - // Actions
211.1334 - //
211.1335 - // The actions in 'this' permission must be a
211.1336 - // superset of the actions in 'that' permission
211.1337 - //
211.1338 -
211.1339 - /* "queryMBeans" implies "queryNames" */
211.1340 - if ((this.mask & QueryMBeans) == QueryMBeans) {
211.1341 - if (((this.mask | QueryNames) & that.mask) != that.mask) {
211.1342 - //System.out.println("action [with QueryNames] does not imply");
211.1343 - return false;
211.1344 - }
211.1345 - } else {
211.1346 - if ((this.mask & that.mask) != that.mask) {
211.1347 - //System.out.println("action does not imply");
211.1348 - return false;
211.1349 - }
211.1350 - }
211.1351 -
211.1352 - // Target name
211.1353 - //
211.1354 - // The 'mbeanServerName' check is true iff:
211.1355 - // 1) the mbeanServerName in 'this' permission is omitted or "*", or
211.1356 - // 2) the mbeanServerName in 'that' permission is omitted or "*", or
211.1357 - // 3) the mbeanServerName in 'this' permission does pattern
211.1358 - // matching with the mbeanServerName in 'that' permission.
211.1359 - //
211.1360 - // The 'member' check is true iff:
211.1361 - // 1) the member in 'this' member is omitted or "*", or
211.1362 - // 2) the member in 'that' member is omitted or "*", or
211.1363 - // 3) the member in 'this' permission equals the member in
211.1364 - // 'that' permission.
211.1365 - //
211.1366 - // The 'object name' check is true iff:
211.1367 - // 1) the object name in 'this' permission is omitted, or
211.1368 - // 2) the object name in 'that' permission is omitted, or
211.1369 - // 3) the object name in 'this' permission does pattern
211.1370 - // matching with the object name in 'that' permission.
211.1371 - //
211.1372 -
211.1373 - if (that.mbeanServerName == null) {
211.1374 - // bottom is implied
211.1375 - } else if (this.mbeanServerName == null) {
211.1376 - // bottom implies nothing but itself
211.1377 - return false;
211.1378 - } else if (that.mbeanServerName.equals(this.mbeanServerName)) {
211.1379 - // exact match
211.1380 - } else if (!Util.wildmatch(that.mbeanServerName,this.mbeanServerName)) {
211.1381 - return false; // no match
211.1382 - }
211.1383 -
211.1384 - /* Check if this.member implies that.member */
211.1385 -
211.1386 - if (that.member == null) {
211.1387 - // bottom is implied
211.1388 - } else if (this.member == null) {
211.1389 - // bottom implies nothing but itself
211.1390 - return false;
211.1391 - } else if (this.member.equals("*")) {
211.1392 - // wildcard implies everything (including itself)
211.1393 - } else if (this.member.equals(that.member)) {
211.1394 - // exact match
211.1395 - } else if (!Util.wildmatch(that.member,this.member)) {
211.1396 - return false; // no match
211.1397 - }
211.1398 -
211.1399 - /* Check if this.objectName implies that.objectName */
211.1400 -
211.1401 - if (that.objectName == null) {
211.1402 - // bottom is implied
211.1403 - } else if (this.objectName == null) {
211.1404 - // bottom implies nothing but itself
211.1405 - if (allnames == false) return false;
211.1406 - } else if (!this.objectName.apply(that.objectName)) {
211.1407 - /* ObjectName.apply returns false if that.objectName is a
211.1408 - wildcard so we also allow equals for that case. This
211.1409 - never happens during real permission checks, but means
211.1410 - the implies relation is reflexive. */
211.1411 - if (!this.objectName.equals(that.objectName))
211.1412 - return false;
211.1413 - }
211.1414 -
211.1415 - return true;
211.1416 - }
211.1417 -
211.1418 - /**
211.1419 - * Checks two JMXNamespacePermission objects for equality. Checks
211.1420 - * that <i>obj</i> is an JMXNamespacePermission, and has the same
211.1421 - * name and actions as this object.
211.1422 - * <P>
211.1423 - * @param obj the object we are testing for equality with this object.
211.1424 - * @return true if obj is an JMXNamespacePermission, and has the
211.1425 - * same name and actions as this JMXNamespacePermission object.
211.1426 - */
211.1427 - public boolean equals(Object obj) {
211.1428 - if (obj == this)
211.1429 - return true;
211.1430 -
211.1431 - if (! (obj instanceof JMXNamespacePermission))
211.1432 - return false;
211.1433 -
211.1434 - JMXNamespacePermission that = (JMXNamespacePermission) obj;
211.1435 -
211.1436 - return (this.mask == that.mask) &&
211.1437 - (this.getName().equals(that.getName()));
211.1438 - }
211.1439 -
211.1440 - /**
211.1441 - * Deserialize this object based on its name and actions.
211.1442 - */
211.1443 - private void readObject(ObjectInputStream in)
211.1444 - throws IOException, ClassNotFoundException {
211.1445 - in.defaultReadObject();
211.1446 - parseName();
211.1447 - parseActions();
211.1448 - }
211.1449 -}
212.1 --- a/src/share/classes/javax/management/namespace/JMXNamespaceView.java Mon Nov 23 10:04:47 2009 +0000
212.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
212.3 @@ -1,300 +0,0 @@
212.4 -/*
212.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
212.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
212.7 - *
212.8 - * This code is free software; you can redistribute it and/or modify it
212.9 - * under the terms of the GNU General Public License version 2 only, as
212.10 - * published by the Free Software Foundation. Sun designates this
212.11 - * particular file as subject to the "Classpath" exception as provided
212.12 - * by Sun in the LICENSE file that accompanied this code.
212.13 - *
212.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
212.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
212.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
212.17 - * version 2 for more details (a copy is included in the LICENSE file that
212.18 - * accompanied this code).
212.19 - *
212.20 - * You should have received a copy of the GNU General Public License version
212.21 - * 2 along with this work; if not, write to the Free Software Foundation,
212.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
212.23 - *
212.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
212.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
212.26 - * have any questions.
212.27 - */
212.28 -
212.29 -package javax.management.namespace;
212.30 -
212.31 -import java.io.IOException;
212.32 -import java.util.Set;
212.33 -import javax.management.MBeanServer;
212.34 -import javax.management.MBeanServerConnection;
212.35 -import javax.management.MalformedObjectNameException;
212.36 -import javax.management.ObjectName;
212.37 -
212.38 -/**
212.39 - * This class makes it possible to navigate easily within a hierarchical
212.40 - * namespace view.
212.41 - *
212.42 - * <pre>
212.43 - * MBeanServerConnnection rootConnection = ...;
212.44 - *
212.45 - * // create a view at the local root of the namespace hierarchy.
212.46 - * //
212.47 - * JMXNamespaceView view = new JMXNamespaceView(rootConnection);
212.48 - *
212.49 - * // list all top level namespaces
212.50 - * String[] list = view.list();
212.51 - *
212.52 - * // select one namespace from the list
212.53 - * String whereToGo = ... ;
212.54 - *
212.55 - * // go down to the selected namespace:
212.56 - * view = view.down(whereToGo);
212.57 - * System.out.println("I am now in: " + view.where());
212.58 - * System.out.println("I can see these MBeans:" +
212.59 - * view.getMBeanServerConnection().queryNames(null,null));
212.60 - *
212.61 - * // list sub namespaces in current view ('whereToGo')
212.62 - * list = view.list();
212.63 - * System.out.println("Here are the sub namespaces of "+view.where()+": "+
212.64 - * Arrays.toString(list));
212.65 - *
212.66 - * // go up one level
212.67 - * view = view.up();
212.68 - * System.out.println("I am now back to: " +
212.69 - * (view.isRoot() ? "root namespace" : view.where()));
212.70 - * </pre>
212.71 - * @since 1.7
212.72 - */
212.73 -public class JMXNamespaceView {
212.74 -
212.75 - private static final ObjectName ALL_NAMESPACES;
212.76 - static {
212.77 - try {
212.78 - ALL_NAMESPACES = ObjectName.getInstance("*" +
212.79 - JMXNamespaces.NAMESPACE_SEPARATOR + ":"+
212.80 - JMXNamespace.TYPE_ASSIGNMENT);
212.81 - } catch (MalformedObjectNameException x) {
212.82 - throw new ExceptionInInitializerError(x);
212.83 - }
212.84 - }
212.85 - private static final int NAMESPACE_SEPARATOR_LENGTH =
212.86 - JMXNamespaces.NAMESPACE_SEPARATOR.length();
212.87 -
212.88 - private final JMXNamespaceView parent;
212.89 - private final MBeanServerConnection here;
212.90 - private final String where;
212.91 -
212.92 - private static MBeanServerConnection checkRoot(MBeanServerConnection root) {
212.93 - if (root == null)
212.94 - throw new IllegalArgumentException(
212.95 - "namespaceRoot: null is not a valid value");
212.96 - return root;
212.97 - }
212.98 -
212.99 - /**
212.100 - * Creates a view at the top of a JMX namespace hierarchy.
212.101 - * @param namespaceRoot The {@code MBeanServerConnection} at the
212.102 - * top of the hierarchy.
212.103 - */
212.104 - public JMXNamespaceView(MBeanServerConnection namespaceRoot) {
212.105 - this(null,checkRoot(namespaceRoot),"");
212.106 - }
212.107 -
212.108 - // This constructor should remain private. A user can only create
212.109 - // JMXNamespaceView at the top of the hierarchy.
212.110 - // JMXNamespaceView sub nodes are created by their parent nodes.
212.111 - private JMXNamespaceView(JMXNamespaceView parent,
212.112 - MBeanServerConnection here, String where) {
212.113 - this.parent = parent;
212.114 - this.here = here;
212.115 - this.where = where;
212.116 - }
212.117 -
212.118 - /**
212.119 - * Returns the path leading to the namespace in this view, from
212.120 - * the top of the hierarchy.
212.121 - * @return The path to the namespace in this view.
212.122 - */
212.123 - public String where() {
212.124 - return where;
212.125 - }
212.126 -
212.127 - /**
212.128 - * Lists all direct sub namespaces in this view. The returned strings
212.129 - * do not contain the {@code //} separator.
212.130 - *
212.131 - * @return A list of direct sub name spaces accessible from this
212.132 - * namespace.
212.133 - * @throws IOException if the attempt to list the namespaces fails because
212.134 - * of a communication problem.
212.135 - */
212.136 - public String[] list() throws IOException {
212.137 - final Set<ObjectName> names =
212.138 - here.queryNames(ALL_NAMESPACES,null);
212.139 - final String[] res = new String[names.size()];
212.140 - int i = 0;
212.141 - for (ObjectName dirName : names) {
212.142 - final String dir = dirName.getDomain();
212.143 - res[i++]=dir.substring(0,dir.length()-NAMESPACE_SEPARATOR_LENGTH);
212.144 - }
212.145 - return res;
212.146 - }
212.147 -
212.148 - /**
212.149 - * Go down into a sub namespace.
212.150 - * @param namespace the namespace to go down to. It can contain one or
212.151 - * more {@code //} separators, to traverse intermediate namespaces, but
212.152 - * it must not begin or end with {@code //} or contain an empty
212.153 - * intermediate namespace. If it is the empty string, then {@code this} is
212.154 - * returned.
212.155 - * @return A view of the named sub namespace.
212.156 - * @throws IllegalArgumentException if the {@code namespace} begins or
212.157 - * ends with {@code //}.
212.158 - */
212.159 - public JMXNamespaceView down(String namespace) {
212.160 - if (namespace.equals("")) return this;
212.161 - if (namespace.startsWith(JMXNamespaces.NAMESPACE_SEPARATOR))
212.162 - throw new IllegalArgumentException(namespace+": can't start with "+
212.163 - JMXNamespaces.NAMESPACE_SEPARATOR);
212.164 -
212.165 - // This is a convenience to handle paths like xxx//yyy
212.166 - final String[] elts =
212.167 - namespace.split(JMXNamespaces.NAMESPACE_SEPARATOR);
212.168 -
212.169 - // Go down the path, creating all sub namespaces along the way.
212.170 - // Usually there will be a single element in the given namespace
212.171 - // name, but we don't want to forbid things like
212.172 - // down("xxx//yyy/www");
212.173 - //
212.174 - JMXNamespaceView previous = this;
212.175 - String cursor = where;
212.176 - for (String elt : elts) {
212.177 - // empty path elements are not allowed. It means we
212.178 - // had something like "xxx////yyy"
212.179 - if (elt.equals(""))
212.180 - throw new IllegalArgumentException(namespace+
212.181 - ": invalid path element");
212.182 -
212.183 - // compute the "where" for the child.
212.184 - cursor = JMXNamespaces.concat(cursor, elt);
212.185 -
212.186 - // create the child...
212.187 - final JMXNamespaceView next =
212.188 - makeJMXNamespaceView(root(), previous, cursor);
212.189 -
212.190 - // the current child will be the parent of the next child...
212.191 - previous = next;
212.192 - }
212.193 -
212.194 - // We return the last child that was created.
212.195 - return previous;
212.196 - }
212.197 -
212.198 - /**
212.199 - * Go back up one level. If this view is at the root of the
212.200 - * hierarchy, returns {@code null}.
212.201 - * @return A view of the parent namespace, or {@code null} if we're at
212.202 - * the root of the hierarchy.
212.203 - */
212.204 - public JMXNamespaceView up() {
212.205 - return parent;
212.206 - }
212.207 -
212.208 - /**
212.209 - * Tells whether this view is at the root of the hierarchy.
212.210 - * @return {@code true} if this view is at the root of the hierachy.
212.211 - */
212.212 - public boolean isRoot() {
212.213 - return parent == null;
212.214 - }
212.215 -
212.216 - /**
212.217 - * Returns the view at the root of the hierarchy.
212.218 - * If we are already at the root, this is {@code this}.
212.219 - * @return the view at the root of the hierarchy.
212.220 - */
212.221 - public JMXNamespaceView root() {
212.222 - if (parent == null) return this;
212.223 - return parent.root();
212.224 - }
212.225 -
212.226 - /**
212.227 - * A MBeanServerConnection to the namespace shown by this view.
212.228 - * This is what would have been obtained by doing:
212.229 - * <pre>
212.230 - * JMX.narrowToNamespace(this.root().getMBeanServerConnection(),
212.231 - * this.where());
212.232 - * </pre>
212.233 - * @return A MBeanServerConnection to the namespace shown by this view.
212.234 - */
212.235 - public MBeanServerConnection getMBeanServerConnection() {
212.236 - return here;
212.237 - }
212.238 -
212.239 - /**
212.240 - * <p>Get the name of the JMXNamespaceMBean handling the namespace shown by
212.241 - * this view, relative to the root of the hierarchy. If we are at the root
212.242 - * of the hierarchy, this method returns {@code null}.</p>
212.243 - *
212.244 - * <p>You can use this method to make a proxy for the JMXNamespaceMBean
212.245 - * as follows:</p>
212.246 - *
212.247 - * <pre>
212.248 - * JMXNamespaceView view = ...;
212.249 - * ObjectName namespaceMBeanName = view.getJMXNamespaceMBeanName();
212.250 - * JMXNamespaceMBean namespaceMBean = JMX.newMBeanProxy(
212.251 - * view.root().getMBeanServerConnection(), namespaceMBeanName,
212.252 - * JMXNamespaceMBean.class);
212.253 - * </pre>
212.254 - *
212.255 - * @return The name of the {@code JMXNamespaceMBean} handling the namespace
212.256 - * shown by this view, or {@code null}.
212.257 - */
212.258 - public ObjectName getJMXNamespaceMBeanName() {
212.259 - if (parent == null)
212.260 - return null;
212.261 - else
212.262 - return JMXNamespaces.getNamespaceObjectName(where);
212.263 - }
212.264 -
212.265 - @Override
212.266 - public int hashCode() {
212.267 - return where.hashCode();
212.268 - }
212.269 -
212.270 - /**
212.271 - * Returns true if this object is equal to the given object. The
212.272 - * two objects are equal if the other object is also a {@code
212.273 - * JMXNamespaceView} and both objects have the same {@linkplain #root root}
212.274 - * MBeanServerConnection and the same {@linkplain #where path}.
212.275 - * @param o the other object to compare to.
212.276 - * @return true if both objects are equal.
212.277 - */
212.278 - @Override
212.279 - public boolean equals(Object o) {
212.280 - if (o==this) return true;
212.281 - if (! (o instanceof JMXNamespaceView)) return false;
212.282 - if (!where.equals(((JMXNamespaceView)o).where)) return false;
212.283 - return root().getMBeanServerConnection().equals(
212.284 - ((JMXNamespaceView)o).root().getMBeanServerConnection());
212.285 - }
212.286 -
212.287 - private JMXNamespaceView makeJMXNamespaceView(final JMXNamespaceView root,
212.288 - final JMXNamespaceView directParent, final String pathFromRoot) {
212.289 - if (pathFromRoot.equals("")) return root;
212.290 -
212.291 - return new JMXNamespaceView(directParent,
212.292 - narrowToNamespace(root.getMBeanServerConnection(),
212.293 - pathFromRoot),pathFromRoot);
212.294 - }
212.295 -
212.296 - private MBeanServerConnection narrowToNamespace(MBeanServerConnection root,
212.297 - String path) {
212.298 - if (root instanceof MBeanServer)
212.299 - return JMXNamespaces.narrowToNamespace((MBeanServer)root, path);
212.300 - return JMXNamespaces.narrowToNamespace(root, path);
212.301 - }
212.302 -
212.303 -}
213.1 --- a/src/share/classes/javax/management/namespace/JMXNamespaces.java Mon Nov 23 10:04:47 2009 +0000
213.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
213.3 @@ -1,360 +0,0 @@
213.4 -/*
213.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
213.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
213.7 - *
213.8 - * This code is free software; you can redistribute it and/or modify it
213.9 - * under the terms of the GNU General Public License version 2 only, as
213.10 - * published by the Free Software Foundation. Sun designates this
213.11 - * particular file as subject to the "Classpath" exception as provided
213.12 - * by Sun in the LICENSE file that accompanied this code.
213.13 - *
213.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
213.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
213.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
213.17 - * version 2 for more details (a copy is included in the LICENSE file that
213.18 - * accompanied this code).
213.19 - *
213.20 - * You should have received a copy of the GNU General Public License version
213.21 - * 2 along with this work; if not, write to the Free Software Foundation,
213.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
213.23 - *
213.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
213.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
213.26 - * have any questions.
213.27 - */
213.28 -
213.29 -package javax.management.namespace;
213.30 -
213.31 -import com.sun.jmx.defaults.JmxProperties;
213.32 -import com.sun.jmx.namespace.ObjectNameRouter;
213.33 -import com.sun.jmx.namespace.serial.RewritingProcessor;
213.34 -import com.sun.jmx.namespace.RoutingConnectionProxy;
213.35 -import com.sun.jmx.namespace.RoutingServerProxy;
213.36 -
213.37 -import java.util.logging.Level;
213.38 -import java.util.logging.Logger;
213.39 -
213.40 -import javax.management.InstanceNotFoundException;
213.41 -import javax.management.MBeanServer;
213.42 -import javax.management.MBeanServerConnection;
213.43 -import javax.management.MalformedObjectNameException;
213.44 -import javax.management.ObjectName;
213.45 -
213.46 -/**
213.47 - * Static constants and utility methods to help work with
213.48 - * JMX name spaces. There are no instances of this class.
213.49 - * @since 1.7
213.50 - */
213.51 -public class JMXNamespaces {
213.52 -
213.53 - /**
213.54 - * A logger for this class.
213.55 - **/
213.56 - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
213.57 -
213.58 - /** Creates a new instance of JMXNamespaces */
213.59 - private JMXNamespaces() {
213.60 - }
213.61 -
213.62 - /**
213.63 - * The name space separator. This is an alias for {@link
213.64 - * ObjectName#NAMESPACE_SEPARATOR}.
213.65 - **/
213.66 - public static final String NAMESPACE_SEPARATOR =
213.67 - ObjectName.NAMESPACE_SEPARATOR;
213.68 - private static final int NAMESPACE_SEPARATOR_LENGTH =
213.69 - NAMESPACE_SEPARATOR.length();
213.70 -
213.71 -
213.72 - /**
213.73 - * Creates a new {@code MBeanServerConnection} proxy on a
213.74 - * {@linkplain javax.management.namespace sub name space}
213.75 - * of the given parent.
213.76 - *
213.77 - * @param parent The parent {@code MBeanServerConnection} that contains
213.78 - * the name space.
213.79 - * @param namespace The {@linkplain javax.management.namespace
213.80 - * name space} in which to narrow.
213.81 - * @return A new {@code MBeanServerConnection} proxy that shows the content
213.82 - * of that name space.
213.83 - * @throws IllegalArgumentException if either argument is null,
213.84 - * or the name space does not exist, or if a proxy for that name space
213.85 - * cannot be created. The {@linkplain Throwable#getCause() cause} of
213.86 - * this exception will be an {@link InstanceNotFoundException} if and only
213.87 - * if the name space is found not to exist.
213.88 - */
213.89 - public static MBeanServerConnection narrowToNamespace(
213.90 - MBeanServerConnection parent,
213.91 - String namespace) {
213.92 - if (LOG.isLoggable(Level.FINER))
213.93 - LOG.finer("Making MBeanServerConnection for: " +namespace);
213.94 - return RoutingConnectionProxy.cd(parent, namespace, true);
213.95 - }
213.96 -
213.97 - /**
213.98 - * Creates a new {@code MBeanServer} proxy on a
213.99 - * {@linkplain javax.management.namespace sub name space}
213.100 - * of the given parent.
213.101 - *
213.102 - * @param parent The parent {@code MBeanServer} that contains
213.103 - * the name space.
213.104 - * @param namespace The {@linkplain javax.management.namespace
213.105 - * name space} in which to narrow.
213.106 - * @return A new {@code MBeanServer} proxy that shows the content
213.107 - * of that name space.
213.108 - * @throws IllegalArgumentException if either argument is null,
213.109 - * or the name space does not exist, or if a proxy for that name space
213.110 - * cannot be created. The {@linkplain Throwable#getCause() cause} of
213.111 - * this exception will be an {@link InstanceNotFoundException} if and only
213.112 - * if the name space is found not to exist.
213.113 - */
213.114 - public static MBeanServer narrowToNamespace(MBeanServer parent,
213.115 - String namespace) {
213.116 - if (LOG.isLoggable(Level.FINER))
213.117 - LOG.finer("Making MBeanServer for: " +namespace);
213.118 - return RoutingServerProxy.cd(parent, namespace, true);
213.119 - }
213.120 -
213.121 - /**
213.122 - * Returns an object that is the same as the given object except that
213.123 - * any {@link ObjectName} it might contain has its domain modified.
213.124 - * The returned object might be identical to the given object if it
213.125 - * does not contain any {@code ObjectName} values or if none of them
213.126 - * were modified.
213.127 - * This method will replace a prefix ({@code toRemove}) from the path of
213.128 - * the ObjectNames contained in {@code obj} by another prefix
213.129 - * ({@code toAdd}).
213.130 - * Therefore, all contained ObjectNames must have a path that start with
213.131 - * the given {@code toRemove} prefix. If one of them doesn't, an {@link
213.132 - * IllegalArgumentException} is thrown.
213.133 - * <p>
213.134 - * For instance, if {@code obj} contains the ObjectName
213.135 - * {@code x//y//z//d:k=x}, and {@code toAdd} is {@code v//w}, and
213.136 - * {@code toRemove}
213.137 - * is {@code x//y} this method will return a copy of {@code obj} that
213.138 - * contains {@code v//w//z//d:k=x}.<br>
213.139 - * On the other hand, if {@code obj} contains the ObjectName
213.140 - * {@code x//y//z//d:k=x}, and {@code toAdd} is {@code v//w}, and
213.141 - * {@code toRemove} is {@code v} this method
213.142 - * will raise an exception, because {@code x//y//z//d:k=x} doesn't start
213.143 - * with {@code v}
213.144 - * </p>
213.145 - * <p>Note: the default implementation of this method can use the
213.146 - * Java serialization framework to clone and replace ObjectNames in the
213.147 - * provided {@code obj}. It will usually fail if {@code obj} is not
213.148 - * Java serializable, or contains objects which are not Java
213.149 - * serializable.
213.150 - * </p>
213.151 - * @param obj The object to deep-rewrite
213.152 - * @param toRemove a prefix already present in contained ObjectNames.
213.153 - * If {@code toRemove} is the empty string {@code ""}, nothing
213.154 - * will be removed from the contained ObjectNames.
213.155 - * @param toAdd the prefix that will replace (@code toRemove} in contained
213.156 - * ObjectNames.
213.157 - * If {@code toAdd} is the empty string {@code ""}, nothing
213.158 - * will be added to the contained ObjectNames.
213.159 - * @return the rewritten object, or possibly {@code obj} if nothing needed
213.160 - * to be changed.
213.161 - * @throws IllegalArgumentException if {@code obj} couldn't be rewritten or
213.162 - * if {@code toRemove} or {@code toAdd} is null.
213.163 - **/
213.164 - public static <T> T deepReplaceHeadNamespace(T obj, String toRemove, String toAdd) {
213.165 - final RewritingProcessor processor =
213.166 - RewritingProcessor.newRewritingProcessor(toAdd,toRemove);
213.167 - return processor.rewriteOutput(obj);
213.168 - }
213.169 -
213.170 - /**
213.171 - * Appends {@code namespace} to {@code path}.
213.172 - * This methods appends {@code namespace} to {@code path} to obtain a
213.173 - * a <i>full path</i>, and normalizes the result thus obtained:
213.174 - * <ul>
213.175 - * <li>If {@code path} is empty, the full path is
213.176 - * {@code namespace}.</li>
213.177 - * <li>Otherwise, if {@code namespace} is empty,
213.178 - * the full path is {@code path}</li>
213.179 - * <li>Otherwise, and this is the regular case, the full path is the
213.180 - * result of the concatenation of
213.181 - * {@code path}+{@value #NAMESPACE_SEPARATOR}+{@code namespace}</li>
213.182 - * <li>finally, the full path is normalized: multiple consecutive
213.183 - * occurrences of {@value #NAMESPACE_SEPARATOR} are replaced by a
213.184 - * single {@value #NAMESPACE_SEPARATOR} in the result, and trailing
213.185 - * occurences of {@value #NAMESPACE_SEPARATOR} are removed.
213.186 - * </li>
213.187 - * </ul>
213.188 - * @param path a name space path prefix
213.189 - * @param namespace a name space name to append to the path
213.190 - * @return a syntactically valid name space path, or "" if both parameters
213.191 - * are null or empty.
213.192 - * @throws IllegalArgumentException if either argument is null or ends with
213.193 - * an odd number of {@code /} characters.
213.194 - **/
213.195 - public static String concat(String path, String namespace) {
213.196 - if (path == null || namespace == null)
213.197 - throw new IllegalArgumentException("Null argument");
213.198 - checkTrailingSlashes(path);
213.199 - checkTrailingSlashes(namespace);
213.200 - final String result;
213.201 - if (path.equals("")) result=namespace;
213.202 - else if (namespace.equals("")) result=path;
213.203 - else result=path+NAMESPACE_SEPARATOR+namespace;
213.204 - return ObjectNameRouter.normalizeNamespacePath(result,false,true,false);
213.205 - }
213.206 -
213.207 - /**
213.208 - * Returns a syntactically valid name space path.
213.209 - * If the provided {@code namespace} ends with {@code "//"},
213.210 - * recursively strips trailing {@code "//"}. Each sequence of an
213.211 - * even number of {@code "/"} characters is also replaced by {@code "//"},
213.212 - * for example {@code "foo//bar////baz/////buh"} will become
213.213 - * {@code "foo//bar//baz///buh"}.
213.214 - *
213.215 - * @param namespace A name space path
213.216 - * @return {@code ""} - if the provided {@code namespace} resolves to
213.217 - * the empty string; otherwise a syntactically valid name space string
213.218 - * stripped of trailing and redundant {@code "//"}.
213.219 - * @throws IllegalArgumentException if {@code namespace} is null or
213.220 - * is not syntactically valid (e.g. it contains
213.221 - * invalid characters like ':', or it ends with an odd
213.222 - * number of '/').
213.223 - */
213.224 - public static String normalizeNamespaceName(String namespace) {
213.225 - if (namespace == null)
213.226 - throw new IllegalArgumentException("Null namespace");
213.227 - final String sourcePath =
213.228 - ObjectNameRouter.normalizeNamespacePath(namespace,false,true,false);
213.229 - if (sourcePath.equals("")) return sourcePath;
213.230 -
213.231 - // Will throw an IllegalArgumentException if the namespace name
213.232 - // is not syntactically valid...
213.233 - //
213.234 - getNamespaceObjectName(sourcePath);
213.235 - return sourcePath;
213.236 - }
213.237 -
213.238 -
213.239 - /**
213.240 - * Return a canonical handler name for the provided {@code namespace},
213.241 - * The handler name returned will be
213.242 - * {@link #normalizeNamespaceName normalizeNamespaceName}{@code (namespace) +
213.243 - * "//:type=JMXNamespace"}.
213.244 - *
213.245 - * @param namespace A name space path
213.246 - * @return a canonical ObjectName for a name space handler.
213.247 - * @see #normalizeNamespaceName
213.248 - * @throws IllegalArgumentException if the provided
213.249 - * {@code namespace} is null or not valid.
213.250 - */
213.251 - public static ObjectName getNamespaceObjectName(String namespace) {
213.252 - if (namespace == null || namespace.equals(""))
213.253 - throw new IllegalArgumentException("Null or empty namespace");
213.254 - final String sourcePath =
213.255 - ObjectNameRouter.normalizeNamespacePath(namespace,false,
213.256 - true,false);
213.257 - try {
213.258 - // We could use ObjectName.valueOf here - but throwing an
213.259 - // IllegalArgumentException that contains just the supplied
213.260 - // namespace instead of the whole ObjectName seems preferable.
213.261 - return ObjectName.getInstance(sourcePath+
213.262 - NAMESPACE_SEPARATOR+":"+
213.263 - JMXNamespace.TYPE_ASSIGNMENT);
213.264 - } catch (MalformedObjectNameException x) {
213.265 - throw new IllegalArgumentException("Invalid namespace: " +
213.266 - namespace,x);
213.267 - }
213.268 - }
213.269 -
213.270 - /**
213.271 - * Returns an ObjectName pattern that can be used to query for all MBeans
213.272 - * contained in the given name space.
213.273 - * For instance, if {@code namespace="foo//bar"}, this method will
213.274 - * return {@code "foo//bar//*:*"}
213.275 - * @return an ObjectName pattern that selects all MBeans in the given
213.276 - * name space.
213.277 - **/
213.278 - public static ObjectName getWildcardFor(String namespace) {
213.279 - return insertPath(namespace,ObjectName.WILDCARD);
213.280 - }
213.281 -
213.282 -
213.283 - /**
213.284 - * Returns an ObjectName that can be used to access an MBean
213.285 - * contained in the given name space.
213.286 - * For instance, if {@code path="foo//bar"}, and
213.287 - * {@code to="domain:type=Thing"} this method will
213.288 - * return {@code "foo//bar//domain:type=Thing"}
213.289 - * @return an ObjectName that can be used to invoke an MBean located in a
213.290 - * sub name space.
213.291 - * @throws IllegalArgumentException if {@code path} ends with an
213.292 - * odd number of {@code /} characters.
213.293 - **/
213.294 - public static ObjectName insertPath(String path, ObjectName to) {
213.295 - if (path == null || to == null)
213.296 - throw new IllegalArgumentException("Null argument");
213.297 - checkTrailingSlashes(path);
213.298 - String prefix = path;
213.299 - if (!prefix.equals(""))
213.300 - prefix = ObjectNameRouter.normalizeNamespacePath(
213.301 - prefix + NAMESPACE_SEPARATOR,false,false,false);
213.302 - return to.withDomain(
213.303 - ObjectNameRouter.normalizeDomain(
213.304 - prefix+to.getDomain(),false));
213.305 - }
213.306 -
213.307 - /**
213.308 - * Returns the normalized name space path of the name space expected to
213.309 - * contain {@code ObjectName}.
213.310 - * For instance, for {@code "foo//domain:type=Thing"} this will be
213.311 - * {@code "foo"}. For {@code "//foo//bar//domain:type=Thing"} this will be
213.312 - * {@code "foo//bar"}. For {@code //foo//bar//baz//domain:type=Thing}
213.313 - * this will be {@code "foo//bar//baz"}. For
213.314 - * {@code //foo//bar//baz//:type=JMXNamespace}
213.315 - * this will be {@code "foo//bar"}.
213.316 - *
213.317 - * @param name an {@code ObjectName}
213.318 - * @return the name space path of the name space that could contain such
213.319 - * a name. If {@code name} has no name space, returns {@code ""}.
213.320 - * @throws IllegalArgumentException if {@code name} is null.
213.321 - **/
213.322 - public static String getContainingNamespace(ObjectName name) {
213.323 - return getNormalizedPath(name,true);
213.324 - }
213.325 -
213.326 -
213.327 - static String getNormalizedPath(ObjectName name,
213.328 - boolean removeLeadingSep) {
213.329 - if (name == null)
213.330 - throw new IllegalArgumentException("Null name");
213.331 - String domain =
213.332 - ObjectNameRouter.normalizeDomain(name.getDomain(),removeLeadingSep);
213.333 - int end = domain.length();
213.334 -
213.335 - // special case of domain part being a single '/'
213.336 - //
213.337 - if (domain.endsWith(NAMESPACE_SEPARATOR+"/"))
213.338 - return domain.substring(0,end-NAMESPACE_SEPARATOR_LENGTH-1);
213.339 -
213.340 - // special case of namespace handler
213.341 - //
213.342 - if (domain.endsWith(NAMESPACE_SEPARATOR))
213.343 - domain = domain.substring(0,end-NAMESPACE_SEPARATOR_LENGTH);
213.344 -
213.345 - int last = domain.lastIndexOf(NAMESPACE_SEPARATOR);
213.346 - if (last < 0) return "";
213.347 - if (last == 0) return domain;
213.348 -
213.349 - // special case of domain part starting with '/'
213.350 - // last=0 is not possible - we took care of this above.
213.351 - if (domain.charAt(last-1) == '/') last--;
213.352 -
213.353 - return domain.substring(0,last);
213.354 - }
213.355 -
213.356 - private static void checkTrailingSlashes(String path) {
213.357 - int i;
213.358 - for (i = path.length() - 1; i >= 0 && path.charAt(i) == '/'; i--)
213.359 - continue;
213.360 - if (path.length() - i % 2 == 0)
213.361 - throw new IllegalArgumentException("Path ends with odd number of /");
213.362 - }
213.363 -}
214.1 --- a/src/share/classes/javax/management/namespace/JMXRemoteNamespace.java Mon Nov 23 10:04:47 2009 +0000
214.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
214.3 @@ -1,809 +0,0 @@
214.4 -/*
214.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
214.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
214.7 - *
214.8 - * This code is free software; you can redistribute it and/or modify it
214.9 - * under the terms of the GNU General Public License version 2 only, as
214.10 - * published by the Free Software Foundation. Sun designates this
214.11 - * particular file as subject to the "Classpath" exception as provided
214.12 - * by Sun in the LICENSE file that accompanied this code.
214.13 - *
214.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
214.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
214.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
214.17 - * version 2 for more details (a copy is included in the LICENSE file that
214.18 - * accompanied this code).
214.19 - *
214.20 - * You should have received a copy of the GNU General Public License version
214.21 - * 2 along with this work; if not, write to the Free Software Foundation,
214.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
214.23 - *
214.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
214.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
214.26 - * have any questions.
214.27 - */
214.28 -
214.29 -package javax.management.namespace;
214.30 -
214.31 -import com.sun.jmx.defaults.JmxProperties;
214.32 -import com.sun.jmx.mbeanserver.Util;
214.33 -import com.sun.jmx.remote.util.EnvHelp;
214.34 -
214.35 -import java.io.IOException;
214.36 -import java.util.Collections;
214.37 -import java.util.HashMap;
214.38 -import java.util.Map;
214.39 -import java.util.concurrent.atomic.AtomicLong;
214.40 -import java.util.logging.Level;
214.41 -import java.util.logging.Logger;
214.42 -
214.43 -import javax.management.AttributeChangeNotification;
214.44 -
214.45 -import javax.management.ClientContext;
214.46 -import javax.management.InstanceNotFoundException;
214.47 -import javax.management.ListenerNotFoundException;
214.48 -import javax.management.MBeanNotificationInfo;
214.49 -import javax.management.MBeanServerConnection;
214.50 -import javax.management.Notification;
214.51 -import javax.management.NotificationBroadcasterSupport;
214.52 -import javax.management.NotificationEmitter;
214.53 -import javax.management.NotificationFilter;
214.54 -import javax.management.NotificationListener;
214.55 -import javax.management.ObjectName;
214.56 -import javax.management.event.EventClient;
214.57 -import javax.management.remote.JMXConnectionNotification;
214.58 -import javax.management.remote.JMXConnector;
214.59 -import javax.management.remote.JMXConnectorFactory;
214.60 -import javax.management.remote.JMXServiceURL;
214.61 -
214.62 -/**
214.63 - * A {@link JMXNamespace} that will connect to a remote MBeanServer
214.64 - * by creating a {@link javax.management.remote.JMXConnector} from a
214.65 - * {@link javax.management.remote.JMXServiceURL}.
214.66 - * <p>
214.67 - * You can call {@link #connect() connect()} and {@link #close close()}
214.68 - * several times. This MBean will emit an {@link AttributeChangeNotification}
214.69 - * when the value of its {@link #isConnected Connected} attribute changes.
214.70 - * </p>
214.71 - * <p>
214.72 - * The JMX Remote Namespace MBean is not connected until {@link
214.73 - * #connect() connect()} is explicitly called. The usual sequence of code to
214.74 - * create a JMX Remote Namespace is thus:
214.75 - * </p>
214.76 - * <pre>
214.77 - * final String namespace = "mynamespace";
214.78 - * final ObjectName name = {@link JMXNamespaces#getNamespaceObjectName
214.79 - * JMXNamespaces.getNamespaceObjectName(namespace)};
214.80 - * final JMXServiceURL remoteServerURL = .... ;
214.81 - * final Map<String,Object> optionsMap = .... ;
214.82 - * final MBeanServer masterMBeanServer = .... ;
214.83 - * final JMXRemoteNamespace namespaceMBean = {@link #newJMXRemoteNamespace
214.84 - * JMXRemoteNamespace.newJMXRemoteNamespace(remoteServerURL, optionsMap)};
214.85 - * masterMBeanServer.registerMBean(namespaceMBean, name);
214.86 - * namespaceMBean.connect();
214.87 - * // or: masterMBeanServer.invoke(name, {@link #connect() "connect"}, null, null);
214.88 - * </pre>
214.89 - * <p>
214.90 - * The JMX Remote Namespace MBean will register for {@linkplain
214.91 - * JMXConnectionNotification JMX Connection Notifications} with its underlying
214.92 - * {@link JMXConnector}. When a JMX Connection Notification indicates that
214.93 - * the underlying connection has failed, the JMX Remote Namespace MBean
214.94 - * closes its underlying connector and switches its {@link #isConnected
214.95 - * Connected} attribute to false, emitting an {@link
214.96 - * AttributeChangeNotification}.
214.97 - * </p>
214.98 - * <p>
214.99 - * At this point, a managing application (or an administrator connected
214.100 - * through a management console) can attempt to reconnect the
214.101 - * JMX Remote Namespace MBean by calling its {@link #connect() connect()} method
214.102 - * again.
214.103 - * </p>
214.104 - * <p>Note that when the connection with the remote namespace fails, or when
214.105 - * {@link #close} is called, then any notification subscription to
214.106 - * MBeans registered in that namespace will be lost - unless a custom
214.107 - * {@linkplain javax.management.event event service} supporting connection-less
214.108 - * mode was used.
214.109 - * </p>
214.110 - * @since 1.7
214.111 - */
214.112 -public class JMXRemoteNamespace
214.113 - extends JMXNamespace
214.114 - implements JMXRemoteNamespaceMBean, NotificationEmitter {
214.115 -
214.116 - /**
214.117 - * A logger for this class.
214.118 - */
214.119 - private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
214.120 -
214.121 -
214.122 - // This connection listener is used to listen for connection events from
214.123 - // the underlying JMXConnector. It is used in particular to maintain the
214.124 - // "connected" state in this MBean.
214.125 - //
214.126 - private class ConnectionListener implements NotificationListener {
214.127 - private ConnectionListener() {
214.128 - }
214.129 - public void handleNotification(Notification notification,
214.130 - Object handback) {
214.131 - if (!(notification instanceof JMXConnectionNotification))
214.132 - return;
214.133 - final JMXConnectionNotification cn =
214.134 - (JMXConnectionNotification)notification;
214.135 - final String type = cn.getType();
214.136 - if (JMXConnectionNotification.CLOSED.equals(type)
214.137 - || JMXConnectionNotification.FAILED.equals(type)) {
214.138 - checkState(this,cn,(JMXConnector)handback);
214.139 - }
214.140 - }
214.141 - }
214.142 -
214.143 - // When the JMXRemoteNamespace is originally created, it is not connected,
214.144 - // which means that the source MBeanServer should be one that throws
214.145 - // exceptions for most methods. When it is subsequently connected,
214.146 - // the methods should be forwarded to the MBeanServerConnection.
214.147 - // We handle this using MBeanServerConnectionWrapper. The
214.148 - // MBeanServerConnection that is supplied to the constructor of
214.149 - // MBeanServerConnectionWrapper is ignored (and in fact it is null)
214.150 - // because the one that is actually used is the one supplied by the
214.151 - // override of getMBeanServerConnection().
214.152 - private static class JMXRemoteNamespaceDelegate
214.153 - extends MBeanServerConnectionWrapper {
214.154 - private volatile JMXRemoteNamespace parent=null;
214.155 -
214.156 - JMXRemoteNamespaceDelegate() {
214.157 - super(null,null);
214.158 - }
214.159 - @Override
214.160 - public MBeanServerConnection getMBeanServerConnection() {
214.161 - return parent.getMBeanServerConnection();
214.162 - }
214.163 - @Override
214.164 - public ClassLoader getDefaultClassLoader() {
214.165 - return parent.getDefaultClassLoader();
214.166 - }
214.167 -
214.168 - // Because this class is instantiated in the super() call from the
214.169 - // constructor of JMXRemoteNamespace, it cannot be an inner class.
214.170 - // This method achieves the effect that an inner class would have
214.171 - // had, of giving the class a reference to the outer "this".
214.172 - synchronized void initParentOnce(JMXRemoteNamespace parent) {
214.173 - if (this.parent != null)
214.174 - throw new UnsupportedOperationException("parent already set");
214.175 - this.parent=parent;
214.176 -
214.177 - }
214.178 -
214.179 - }
214.180 -
214.181 - private static final MBeanNotificationInfo connectNotification =
214.182 - new MBeanNotificationInfo(new String[] {
214.183 - AttributeChangeNotification.ATTRIBUTE_CHANGE},
214.184 - "Connected",
214.185 - "Emitted when the Connected state of this object changes");
214.186 -
214.187 - private static AtomicLong seqNumber = new AtomicLong(0);
214.188 -
214.189 - private final NotificationBroadcasterSupport broadcaster;
214.190 - private final ConnectionListener listener;
214.191 - private final JMXServiceURL jmxURL;
214.192 - private final Map<String,?> optionsMap;
214.193 -
214.194 - private volatile MBeanServerConnection server = null;
214.195 - private volatile JMXConnector conn = null;
214.196 - private volatile ClassLoader defaultClassLoader = null;
214.197 -
214.198 - /**
214.199 - * Creates a new instance of {@code JMXRemoteNamespace}.
214.200 - * <p>
214.201 - * This constructor is provided for subclasses.
214.202 - * To create a new instance of {@code JMXRemoteNamespace} call
214.203 - * {@link #newJMXRemoteNamespace
214.204 - * JMXRemoteNamespace.newJMXRemoteNamespace(sourceURL, optionsMap)}.
214.205 - * </p>
214.206 - * @param sourceURL a JMX service URL that can be used to {@linkplain
214.207 - * #connect() connect} to the
214.208 - * source MBean Server. The source MBean Server is the remote
214.209 - * MBean Server which contains the MBeans that will be mirrored
214.210 - * in this namespace.
214.211 - * @param optionsMap the options map that will be passed to the
214.212 - * {@link JMXConnectorFactory} when {@linkplain
214.213 - * JMXConnectorFactory#newJMXConnector creating} the
214.214 - * {@link JMXConnector} used to {@linkplain #connect() connect}
214.215 - * to the remote source MBean Server. Can be null, which is
214.216 - * equivalent to an empty map.
214.217 - * @see #newJMXRemoteNamespace JMXRemoteNamespace.newJMXRemoteNamespace
214.218 - * @see #connect
214.219 - */
214.220 - protected JMXRemoteNamespace(JMXServiceURL sourceURL,
214.221 - Map<String,?> optionsMap) {
214.222 - super(new JMXRemoteNamespaceDelegate());
214.223 - ((JMXRemoteNamespaceDelegate)super.getSourceServer()).
214.224 - initParentOnce(this);
214.225 -
214.226 - // URL must not be null.
214.227 - if (sourceURL == null)
214.228 - throw new IllegalArgumentException("Null URL");
214.229 - this.jmxURL = sourceURL;
214.230 - this.broadcaster =
214.231 - new NotificationBroadcasterSupport(connectNotification);
214.232 -
214.233 - // handles options
214.234 - this.optionsMap = unmodifiableMap(optionsMap);
214.235 -
214.236 - // handles (dis)connection events
214.237 - this.listener = new ConnectionListener();
214.238 - }
214.239 -
214.240 - // returns un unmodifiable view of a map.
214.241 - private static <K,V> Map<K,V> unmodifiableMap(Map<K,V> aMap) {
214.242 - if (aMap == null || aMap.isEmpty())
214.243 - return Collections.emptyMap();
214.244 - return Collections.unmodifiableMap(aMap);
214.245 - }
214.246 -
214.247 - /**
214.248 - * Returns the {@code JMXServiceURL} that is (or will be) used to
214.249 - * connect to the remote name space. <p>
214.250 - * @see #connect
214.251 - * @return The {@code JMXServiceURL} used to connect to the remote
214.252 - * name space.
214.253 - */
214.254 - public JMXServiceURL getJMXServiceURL() {
214.255 - return jmxURL;
214.256 - }
214.257 -
214.258 - /**
214.259 - * In this class, this method never returns {@code null}, and the
214.260 - * address returned is the {@link #getJMXServiceURL JMXServiceURL}
214.261 - * that is used by this object to {@linkplain #connect} to the remote
214.262 - * name space. <p>
214.263 - * This behaviour might be overriden by subclasses, if needed.
214.264 - * For instance, a subclass might want to return {@code null} if it
214.265 - * doesn't want to expose that JMXServiceURL.
214.266 - */
214.267 - public JMXServiceURL getAddress() {
214.268 - return getJMXServiceURL();
214.269 - }
214.270 -
214.271 - private Map<String,?> getEnvMap() {
214.272 - return optionsMap;
214.273 - }
214.274 -
214.275 - public void addNotificationListener(NotificationListener listener,
214.276 - NotificationFilter filter, Object handback) {
214.277 - broadcaster.addNotificationListener(listener, filter, handback);
214.278 - }
214.279 -
214.280 - /**
214.281 - * A subclass that needs to send its own notifications must override
214.282 - * this method in order to return an {@link MBeanNotificationInfo
214.283 - * MBeanNotificationInfo[]} array containing both its own notification
214.284 - * infos and the notification infos of its super class. <p>
214.285 - * The implementation should probably look like:
214.286 - * <pre>
214.287 - * final MBeanNotificationInfo[] myOwnNotifs = { .... };
214.288 - * final MBeanNotificationInfo[] parentNotifs =
214.289 - * super.getNotificationInfo();
214.290 - * final Set<MBeanNotificationInfo> mergedResult =
214.291 - * new HashSet<MBeanNotificationInfo>();
214.292 - * mergedResult.addAll(Arrays.asList(myOwnNotifs));
214.293 - * mergedResult.addAll(Arrays.asList(parentNotifs));
214.294 - * return mergeResult.toArray(
214.295 - * new MBeanNotificationInfo[mergedResult.size()]);
214.296 - * </pre>
214.297 - */
214.298 - public MBeanNotificationInfo[] getNotificationInfo() {
214.299 - return broadcaster.getNotificationInfo();
214.300 - }
214.301 -
214.302 - public void removeNotificationListener(NotificationListener listener)
214.303 - throws ListenerNotFoundException {
214.304 - broadcaster.removeNotificationListener(listener);
214.305 - }
214.306 -
214.307 - public void removeNotificationListener(NotificationListener listener,
214.308 - NotificationFilter filter, Object handback)
214.309 - throws ListenerNotFoundException {
214.310 - broadcaster.removeNotificationListener(listener, filter, handback);
214.311 - }
214.312 -
214.313 - private static long getNextSeqNumber() {
214.314 - return seqNumber.getAndIncrement();
214.315 - }
214.316 -
214.317 -
214.318 - /**
214.319 - * Sends a notification to registered listeners. Before the notification
214.320 - * is sent, the following steps are performed:
214.321 - * <ul><li>
214.322 - * If {@code n.getSequenceNumber() <= 0} set it to the next available
214.323 - * sequence number.</li>
214.324 - * <li>If {@code n.getSource() == null}, set it to the value returned by {@link
214.325 - * #getObjectName getObjectName()}.
214.326 - * </li></ul>
214.327 - * <p>This method can be called by subclasses in order to send their own
214.328 - * notifications.
214.329 - * In that case, these subclasses might also need to override
214.330 - * {@link #getNotificationInfo} in order to declare their own
214.331 - * {@linkplain MBeanNotificationInfo notification types}.
214.332 - * </p>
214.333 - * @param n The notification to send to registered listeners.
214.334 - * @see javax.management.NotificationBroadcasterSupport
214.335 - * @see #getNotificationInfo
214.336 - **/
214.337 - protected void sendNotification(Notification n) {
214.338 - if (n.getSequenceNumber()<=0)
214.339 - n.setSequenceNumber(getNextSeqNumber());
214.340 - if (n.getSource()==null)
214.341 - n.setSource(getObjectName());
214.342 - broadcaster.sendNotification(n);
214.343 - }
214.344 -
214.345 - private void checkState(ConnectionListener listener,
214.346 - JMXConnectionNotification cn,
214.347 - JMXConnector emittingConnector) {
214.348 -
214.349 - // Due to the asynchronous handling of notifications, it is
214.350 - // possible that this method is called for a JMXConnector
214.351 - // (or connection) which is already closed and replaced by a newer
214.352 - // one.
214.353 - //
214.354 - // This method attempts to determine the real state of the
214.355 - // connection - which might be different from what the notification
214.356 - // says.
214.357 - //
214.358 - // This is quite complex logic - because we try not to hold any
214.359 - // lock while evaluating the true value of the connected state,
214.360 - // while anyone might also call close() or connect() from a
214.361 - // different thread.
214.362 - // The method switchConnection() (called from here too) also has the
214.363 - // same kind of complex logic:
214.364 - //
214.365 - // We use the JMXConnector has a handback to the notification listener
214.366 - // (emittingConnector) in order to be able to determine whether the
214.367 - // notification concerns the current connector in use, or an older
214.368 - // one. The 'emittingConnector' is the connector from which the
214.369 - // notification originated. This could be an 'old' connector - as
214.370 - // closed() and connect() could already have been called before the
214.371 - // notification arrived. So what we do is to compare the
214.372 - // 'emittingConnector' with the current connector, to see if the
214.373 - // notification actually comes from the curent connector.
214.374 - //
214.375 - boolean remove = false;
214.376 -
214.377 - // whether the emittingConnector is already 'removed'
214.378 - synchronized (this) {
214.379 - if (this.conn != emittingConnector ||
214.380 - JMXConnectionNotification.FAILED.equals(cn.getType()))
214.381 - remove = true;
214.382 - }
214.383 -
214.384 - // We need to unregister our listener from this 'removed' connector.
214.385 - // This is the only place where we remove the listener.
214.386 - //
214.387 - if (remove) {
214.388 - try {
214.389 - // This may fail if the connector is already closed.
214.390 - // But better unregister anyway...
214.391 - //
214.392 - emittingConnector.removeConnectionNotificationListener(
214.393 - listener,null,
214.394 - emittingConnector);
214.395 - } catch (Exception x) {
214.396 - LOG.log(Level.FINE,
214.397 - "Failed to unregister connection listener"+x);
214.398 - LOG.log(Level.FINEST,
214.399 - "Failed to unregister connection listener",x);
214.400 - }
214.401 - try {
214.402 - // This may fail if the connector is already closed.
214.403 - // But better call close twice and get an exception than
214.404 - // leaking...
214.405 - //
214.406 - emittingConnector.close();
214.407 - } catch (Exception x) {
214.408 - LOG.log(Level.FINEST,
214.409 - "Failed to close old connector " +
214.410 - "(failure was expected): "+x);
214.411 - }
214.412 - }
214.413 -
214.414 - // Now we checked whether our current connector is still alive.
214.415 - //
214.416 - boolean closed = false;
214.417 - final JMXConnector thisconn = this.conn;
214.418 - try {
214.419 - if (thisconn != null)
214.420 - thisconn.getConnectionId();
214.421 - } catch (IOException x) {
214.422 - LOG.finest("Connector already closed: "+x);
214.423 - closed = true;
214.424 - }
214.425 -
214.426 - // We got an IOException - the connector is not connected.
214.427 - // Need to forget it and switch our state to closed.
214.428 - //
214.429 - if (closed) {
214.430 - switchConnection(thisconn,null,null);
214.431 - try {
214.432 - // Usually this will fail... Better call close twice
214.433 - // and get an exception than leaking...
214.434 - //
214.435 - if (thisconn != emittingConnector || !remove)
214.436 - thisconn.close();
214.437 - } catch (IOException x) {
214.438 - LOG.log(Level.FINEST,
214.439 - "Failed to close connector (failure was expected): "
214.440 - +x);
214.441 - }
214.442 - }
214.443 - }
214.444 -
214.445 - private final void switchConnection(JMXConnector oldc,
214.446 - JMXConnector newc,
214.447 - MBeanServerConnection mbs) {
214.448 - boolean connect = false;
214.449 - boolean close = false;
214.450 - synchronized (this) {
214.451 - if (oldc != conn) {
214.452 - if (newc != null) {
214.453 - try {
214.454 - newc.close();
214.455 - } catch (IOException x) {
214.456 - LOG.log(Level.FINEST,
214.457 - "Failed to close connector",x);
214.458 - }
214.459 - }
214.460 - return;
214.461 - }
214.462 - if (conn == null && newc != null) connect=true;
214.463 - if (newc == null && conn != null) close = true;
214.464 - conn = newc;
214.465 - server = mbs;
214.466 - }
214.467 - if (connect || close) {
214.468 - boolean oldstate = close;
214.469 - boolean newstate = connect;
214.470 - final ObjectName myName = getObjectName();
214.471 -
214.472 - // In the uncommon case where the MBean is connected before
214.473 - // being registered, myName can be null...
214.474 - // If myName is null - we use 'this' as the source instead...
214.475 - //
214.476 - final Object source = (myName==null)?this:myName;
214.477 - final AttributeChangeNotification acn =
214.478 - new AttributeChangeNotification(source,
214.479 - getNextSeqNumber(),System.currentTimeMillis(),
214.480 - String.valueOf(source)+
214.481 - (newstate?" connected":" closed"),
214.482 - "Connected",
214.483 - "boolean",
214.484 - Boolean.valueOf(oldstate),
214.485 - Boolean.valueOf(newstate));
214.486 - sendNotification(acn);
214.487 - }
214.488 - }
214.489 -
214.490 - private void close(JMXConnector c) {
214.491 - try {
214.492 - if (c != null) c.close();
214.493 - } catch (Exception x) {
214.494 - // OK: we're gonna throw the original exception later.
214.495 - LOG.finest("Ignoring exception when closing connector: "+x);
214.496 - }
214.497 - }
214.498 -
214.499 - private JMXConnector connect(JMXServiceURL url, Map<String,?> env)
214.500 - throws IOException {
214.501 - final JMXConnector c = newJMXConnector(url, env);
214.502 - c.connect(env);
214.503 - return c;
214.504 - }
214.505 -
214.506 - /**
214.507 - * <p>Creates a new JMXConnector with the specified {@code url} and
214.508 - * {@code env} options map. The default implementation of this method
214.509 - * returns {@link JMXConnectorFactory#newJMXConnector
214.510 - * JMXConnectorFactory.newJMXConnector(jmxURL, env)}. Subclasses can
214.511 - * override this method to customize behavior.</p>
214.512 - *
214.513 - * @param url The JMXServiceURL of the remote server.
214.514 - * @param optionsMap An options map that will be passed to the
214.515 - * {@link JMXConnectorFactory} when {@linkplain
214.516 - * JMXConnectorFactory#newJMXConnector creating} the
214.517 - * {@link JMXConnector} that can connect to the remote source
214.518 - * MBean Server.
214.519 - * @return A JMXConnector to use to connect to the remote server
214.520 - * @throws IOException if the connector could not be created.
214.521 - * @see JMXConnectorFactory#newJMXConnector(javax.management.remote.JMXServiceURL, java.util.Map)
214.522 - * @see #JMXRemoteNamespace
214.523 - */
214.524 - protected JMXConnector newJMXConnector(JMXServiceURL url,
214.525 - Map<String,?> optionsMap) throws IOException {
214.526 - return JMXConnectorFactory.newJMXConnector(jmxURL, optionsMap);
214.527 - }
214.528 -
214.529 - /**
214.530 - * <p>Called when a new connection is established using {@link #connect}
214.531 - * so that subclasses can customize the connection. The default
214.532 - * implementation of this method effectively does the following:</p>
214.533 - *
214.534 - * <pre>
214.535 - * MBeanServerConnection mbsc = {@link JMXConnector#getMBeanServerConnection()
214.536 - * jmxc.getMBeanServerConnection()};
214.537 - * try {
214.538 - * return {@link ClientContext#withDynamicContext
214.539 - * ClientContext.withDynamicContext(mbsc)};
214.540 - * } catch (IllegalArgumentException e) {
214.541 - * return mbsc;
214.542 - * }
214.543 - * </pre>
214.544 - *
214.545 - * <p>In other words, it arranges for the client context to be forwarded
214.546 - * to the remote MBean Server if the remote MBean Server supports contexts;
214.547 - * otherwise it ignores the client context.</p>
214.548 - *
214.549 - * <h4>Example: connecting to a remote namespace</h4>
214.550 - *
214.551 - * <p>A subclass that wanted to narrow into a namespace of
214.552 - * the remote MBeanServer might look like this:</p>
214.553 - *
214.554 - * <pre>
214.555 - * class JMXRemoteSubNamespace extends JMXRemoteNamespace {
214.556 - * private final String subnamespace;
214.557 - *
214.558 - * JMXRemoteSubNamespace(
214.559 - * JMXServiceURL url, Map{@code <String, ?>} env, String subnamespace) {
214.560 - * super(url, env);
214.561 - * this.subnamespace = subnamespace;
214.562 - * }
214.563 - *
214.564 - * {@code @Override}
214.565 - * protected MBeanServerConnection getMBeanServerConnection(
214.566 - * JMXConnector jmxc) throws IOException {
214.567 - * MBeanServerConnection mbsc = super.getMBeanServerConnection(jmxc);
214.568 - * return {@link JMXNamespaces#narrowToNamespace(MBeanServerConnection,String)
214.569 - * JMXNamespaces.narrowToNamespace(mbsc, subnamespace)};
214.570 - * }
214.571 - * }
214.572 - * </pre>
214.573 - *
214.574 - * <h4>Example: using the Event Service for notifications</h4>
214.575 - *
214.576 - * <p>Some connectors may have been designed to work with an earlier
214.577 - * version of the JMX API, and may not have been upgraded to use
214.578 - * the {@linkplain javax.management.event Event Service} defined in
214.579 - * this version of the JMX API. In that case, and if the remote
214.580 - * server to which this JMXRemoteNamespace connects also contains
214.581 - * namespaces, it may be necessary to configure explicitly an {@linkplain
214.582 - * javax.management.event.EventClientDelegate#newForwarder Event Client
214.583 - * Forwarder} on the remote server side, and to force the use of an {@link
214.584 - * EventClient} on this client side.</p>
214.585 - *
214.586 - * <p>A subclass of {@link JMXRemoteNamespace} can provide an
214.587 - * implementation of {@code getMBeanServerConnection} that will force
214.588 - * notification subscriptions to flow through an {@link EventClient} over
214.589 - * a legacy protocol. It can do so by overriding this method in the
214.590 - * following way:</p>
214.591 - *
214.592 - * <pre>
214.593 - * class JMXRemoteEventClientNamespace extends JMXRemoteNamespace {
214.594 - * JMXRemoteEventClientNamespace(JMXServiceURL url, {@code Map<String,?>} env) {
214.595 - * super(url, env);
214.596 - * }
214.597 - *
214.598 - * {@code @Override}
214.599 - * protected MBeanServerConnection getMBeanServerConnection(JMXConnector jmxc)
214.600 - * throws IOException {
214.601 - * MBeanServerConnection mbsc = super.getMBeanServerConnection(jmxc);
214.602 - * return EventClient.getEventClientConnection(mbsc);
214.603 - * }
214.604 - * }
214.605 - * </pre>
214.606 - *
214.607 - * <p>
214.608 - * Note that the remote server also needs to provide an {@link
214.609 - * javax.management.event.EventClientDelegateMBean}: configuring only
214.610 - * the client side (this object) is not enough.</p>
214.611 - *
214.612 - * <p>In summary, this technique should be used if the remote server
214.613 - * supports JMX namespaces, but uses a JMX Connector Server whose
214.614 - * implementation does not transparently use the new Event Service
214.615 - * (as would be the case with the JMXMPConnectorServer implementation
214.616 - * from the reference implementation of the JMX Remote API 1.0
214.617 - * specification).</p>
214.618 - *
214.619 - * @param jmxc the newly-created {@code JMXConnector}.
214.620 - *
214.621 - * @return an {@code MBeanServerConnection} connected to the remote
214.622 - * MBeanServer.
214.623 - *
214.624 - * @throws IOException if the connection cannot be made. If this method
214.625 - * throws {@code IOException} then the calling {@link #connect()} method
214.626 - * will also fail with an {@code IOException}.
214.627 - *
214.628 - * @see #connect
214.629 - */
214.630 - protected MBeanServerConnection getMBeanServerConnection(JMXConnector jmxc)
214.631 - throws IOException {
214.632 - final MBeanServerConnection mbsc = jmxc.getMBeanServerConnection();
214.633 - try {
214.634 - return ClientContext.withDynamicContext(mbsc);
214.635 - } catch (IllegalArgumentException e) {
214.636 - LOG.log(Level.FINER, "ClientContext.withDynamicContext", e);
214.637 - return mbsc;
214.638 - }
214.639 - }
214.640 -
214.641 - /**
214.642 - * {@inheritDoc}
214.643 - *
214.644 - * <p>The sequence of events when this method is called includes,
214.645 - * effectively, the following code:</p>
214.646 - *
214.647 - * <pre>
214.648 - * JMXServiceURL url = {@link #getJMXServiceURL getJMXServiceURL}();
214.649 - * JMXConnector jmxc = {@link #newJMXConnector newJMXConnector}(url, env);
214.650 - * jmxc.connect();
214.651 - * MBeanServerConnection mbsc = {@link #getMBeanServerConnection(JMXConnector)
214.652 - * getMBeanServerConnection}(jmxc);
214.653 - * </pre>
214.654 - *
214.655 - * <p>Here, {@code env} is a {@code Map} containing the entries from the
214.656 - * {@code optionsMap} that was passed to the {@linkplain #JMXRemoteNamespace
214.657 - * constructor} or to the {@link #newJMXRemoteNamespace newJMXRemoteNamespace}
214.658 - * factory method.</p>
214.659 - *
214.660 - * <p>Subclasses can customize connection behavior by overriding the
214.661 - * {@code getJMXServiceURL}, {@code newJMXConnector}, or
214.662 - * {@code getMBeanServerConnection} methods.</p>
214.663 - */
214.664 - public void connect() throws IOException {
214.665 - LOG.fine("connecting...");
214.666 - final Map<String,Object> env =
214.667 - new HashMap<String,Object>(getEnvMap());
214.668 - try {
214.669 - // XXX: We should probably document this...
214.670 - // This allows to specify a loader name - which will be
214.671 - // retrieved from the parent MBeanServer.
214.672 - defaultClassLoader =
214.673 - EnvHelp.resolveServerClassLoader(env,getMBeanServer());
214.674 - } catch (InstanceNotFoundException x) {
214.675 - final IOException io =
214.676 - new IOException("ClassLoader not found");
214.677 - io.initCause(x);
214.678 - throw io;
214.679 - }
214.680 - env.put(JMXConnectorFactory.DEFAULT_CLASS_LOADER,defaultClassLoader);
214.681 - final JMXServiceURL url = getJMXServiceURL();
214.682 - final JMXConnector aconn = connect(url,env);
214.683 - final MBeanServerConnection msc;
214.684 - try {
214.685 - msc = getMBeanServerConnection(aconn);
214.686 - aconn.addConnectionNotificationListener(listener,null,aconn);
214.687 - } catch (IOException io) {
214.688 - close(aconn);
214.689 - throw io;
214.690 - } catch (RuntimeException x) {
214.691 - close(aconn);
214.692 - throw x;
214.693 - }
214.694 -
214.695 - switchConnection(conn,aconn,msc);
214.696 -
214.697 - LOG.fine("connected.");
214.698 - }
214.699 -
214.700 - public void close() throws IOException {
214.701 - if (conn == null) return;
214.702 - LOG.fine("closing...");
214.703 - // System.err.println(toString()+": closing...");
214.704 - conn.close();
214.705 - // System.err.println(toString()+": connector closed");
214.706 - switchConnection(conn,null,null);
214.707 - LOG.fine("closed.");
214.708 - // System.err.println(toString()+": closed");
214.709 - }
214.710 -
214.711 - MBeanServerConnection getMBeanServerConnection() {
214.712 - if (conn == null)
214.713 - throw newRuntimeIOException("getMBeanServerConnection: not connected");
214.714 - return server;
214.715 - }
214.716 -
214.717 - // Better than throwing UndeclaredThrowableException ...
214.718 - private RuntimeException newRuntimeIOException(String msg) {
214.719 - final IllegalStateException illegal = new IllegalStateException(msg);
214.720 - return Util.newRuntimeIOException(new IOException(msg,illegal));
214.721 - }
214.722 -
214.723 - /**
214.724 - * Returns the default class loader used by the underlying
214.725 - * {@link JMXConnector}.
214.726 - * @return the default class loader used when communicating with the
214.727 - * remote source MBean server.
214.728 - **/
214.729 - ClassLoader getDefaultClassLoader() {
214.730 - if (conn == null)
214.731 - throw newRuntimeIOException("getMBeanServerConnection: not connected");
214.732 - return defaultClassLoader;
214.733 - }
214.734 -
214.735 - public boolean isConnected() {
214.736 - // This is a pleonasm
214.737 - return (conn != null) && (server != null);
214.738 - }
214.739 -
214.740 -
214.741 - /**
214.742 - * This name space handler will automatically {@link #close} its
214.743 - * connection with the remote source in {@code preDeregister}.
214.744 - **/
214.745 - @Override
214.746 - public void preDeregister() throws Exception {
214.747 - try {
214.748 - close();
214.749 - } catch (IOException x) {
214.750 - LOG.fine("Failed to close properly - exception ignored: " + x);
214.751 - LOG.log(Level.FINEST,
214.752 - "Failed to close properly - exception ignored",x);
214.753 - }
214.754 - super.preDeregister();
214.755 - }
214.756 -
214.757 - /**
214.758 - * This method calls {@link
214.759 - * javax.management.MBeanServerConnection#getMBeanCount
214.760 - * getMBeanCount()} on the remote namespace.
214.761 - * @throws java.io.IOException if an {@link IOException} is raised when
214.762 - * communicating with the remote source namespace.
214.763 - */
214.764 - @Override
214.765 - public Integer getMBeanCount() throws IOException {
214.766 - return getMBeanServerConnection().getMBeanCount();
214.767 - }
214.768 -
214.769 - /**
214.770 - * This method returns the result of calling {@link
214.771 - * javax.management.MBeanServerConnection#getDomains
214.772 - * getDomains()} on the remote namespace.
214.773 - * @throws java.io.IOException if an {@link IOException} is raised when
214.774 - * communicating with the remote source namespace.
214.775 - */
214.776 - @Override
214.777 - public String[] getDomains() throws IOException {
214.778 - return getMBeanServerConnection().getDomains();
214.779 - }
214.780 -
214.781 - /**
214.782 - * This method returns the result of calling {@link
214.783 - * javax.management.MBeanServerConnection#getDefaultDomain
214.784 - * getDefaultDomain()} on the remote namespace.
214.785 - * @throws java.io.IOException if an {@link IOException} is raised when
214.786 - * communicating with the remote source namespace.
214.787 - */
214.788 - @Override
214.789 - public String getDefaultDomain() throws IOException {
214.790 - return getMBeanServerConnection().getDefaultDomain();
214.791 - }
214.792 -
214.793 - /**
214.794 - * Creates a new instance of {@code JMXRemoteNamespace}.
214.795 - * @param sourceURL a JMX service URL that can be used to connect to the
214.796 - * source MBean Server. The source MBean Server is the remote
214.797 - * MBean Server which contains the MBeans that will be mirrored
214.798 - * in this namespace.
214.799 - * @param optionsMap An options map that will be passed to the
214.800 - * {@link JMXConnectorFactory} when {@linkplain
214.801 - * JMXConnectorFactory#newJMXConnector creating} the
214.802 - * {@link JMXConnector} used to connect to the remote source
214.803 - * MBean Server. Can be null, which is equivalent to an empty map.
214.804 - * @see #JMXRemoteNamespace JMXRemoteNamespace(sourceURL,optionsMap)
214.805 - * @see JMXConnectorFactory#newJMXConnector(javax.management.remote.JMXServiceURL, java.util.Map)
214.806 - */
214.807 - public static JMXRemoteNamespace newJMXRemoteNamespace(
214.808 - JMXServiceURL sourceURL,
214.809 - Map<String,?> optionsMap) {
214.810 - return new JMXRemoteNamespace(sourceURL, optionsMap);
214.811 - }
214.812 -}
215.1 --- a/src/share/classes/javax/management/namespace/JMXRemoteNamespaceMBean.java Mon Nov 23 10:04:47 2009 +0000
215.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
215.3 @@ -1,96 +0,0 @@
215.4 -/*
215.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
215.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
215.7 - *
215.8 - * This code is free software; you can redistribute it and/or modify it
215.9 - * under the terms of the GNU General Public License version 2 only, as
215.10 - * published by the Free Software Foundation. Sun designates this
215.11 - * particular file as subject to the "Classpath" exception as provided
215.12 - * by Sun in the LICENSE file that accompanied this code.
215.13 - *
215.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
215.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
215.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
215.17 - * version 2 for more details (a copy is included in the LICENSE file that
215.18 - * accompanied this code).
215.19 - *
215.20 - * You should have received a copy of the GNU General Public License version
215.21 - * 2 along with this work; if not, write to the Free Software Foundation,
215.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
215.23 - *
215.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
215.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
215.26 - * have any questions.
215.27 - */
215.28 -
215.29 -package javax.management.namespace;
215.30 -
215.31 -import java.io.IOException;
215.32 -import javax.management.remote.JMXServiceURL;
215.33 -
215.34 -/**
215.35 - * A {@link JMXNamespaceMBean} that will connect to a remote MBeanServer
215.36 - * by creating a {@link javax.management.remote.JMXConnector} from a
215.37 - * {@link javax.management.remote.JMXServiceURL}.
215.38 - * You can call {@link #connect connect()} and {@link #close close()}
215.39 - * several times.
215.40 - * @since 1.7
215.41 - */
215.42 -public interface JMXRemoteNamespaceMBean
215.43 - extends JMXNamespaceMBean {
215.44 -
215.45 - /**
215.46 - * Connects to the underlying remote source name space, if not already
215.47 - * {@link #isConnected connected}.
215.48 - * If connected, do nothing. Otherwise, creates a new connector from the
215.49 - * {@link javax.management.remote.JMXServiceURL JMXServiceURL} provided at
215.50 - * creation time, and connects to the remote source name space.
215.51 - * <p>
215.52 - * The source MBeans will not appear in the target name space until the
215.53 - * JMXRemoteNamespaceMBean is connected.
215.54 - * </p><p>
215.55 - * It is possible to call {@code connect()}, {@link #close close()}, and
215.56 - * {@code connect()} again.
215.57 - * However, closing the connection with the remote name space may cause
215.58 - * notification listeners to be lost, unless the client explicitly uses
215.59 - * the new {@linkplain javax.management.event JMX event service}.
215.60 - * </p><p>
215.61 - * @throws IOException if connection to the remote source name space fails.
215.62 - * @see #isConnected isConnected
215.63 - **/
215.64 - public void connect()
215.65 - throws IOException;
215.66 -
215.67 - /**
215.68 - * Closes the connection with the remote source name space.
215.69 - * If the connection is already closed, do nothing.
215.70 - * Otherwise, closes the underlying {@link
215.71 - * javax.management.remote.JMXConnector}.
215.72 - * <p>Once closed, it is possible to reopen the connection by
215.73 - * calling {@link #connect connect}.
215.74 - * </p>
215.75 - * @throws IOException if the connection to the remote source name space
215.76 - * can't be closed properly.
215.77 - * @see #isConnected isConnected
215.78 - **/
215.79 - public void close()
215.80 - throws IOException;
215.81 -
215.82 - /**
215.83 - * Tells whether the connection to the remote source name space is opened.
215.84 - * @see #connect connect
215.85 - * @see #close close
215.86 - * @return {@code true} if connected.
215.87 - **/
215.88 - public boolean isConnected();
215.89 -
215.90 - /**
215.91 - * Returns the {@link JMXServiceURL} address that points to the remote name
215.92 - * space mirrored by this {@link JMXNamespaceMBean JMXNamespace MBean},
215.93 - * if available.
215.94 - * @return The {@link JMXServiceURL} address that points to the remote name
215.95 - * space mirrored by this {@link JMXNamespaceMBean JMXNamespace MBean},
215.96 - * or {@code null}.
215.97 - */
215.98 - public JMXServiceURL getAddress();
215.99 -}
216.1 --- a/src/share/classes/javax/management/namespace/MBeanServerConnectionWrapper.java Mon Nov 23 10:04:47 2009 +0000
216.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
216.3 @@ -1,702 +0,0 @@
216.4 -/*
216.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
216.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
216.7 - *
216.8 - * This code is free software; you can redistribute it and/or modify it
216.9 - * under the terms of the GNU General Public License version 2 only, as
216.10 - * published by the Free Software Foundation. Sun designates this
216.11 - * particular file as subject to the "Classpath" exception as provided
216.12 - * by Sun in the LICENSE file that accompanied this code.
216.13 - *
216.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
216.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
216.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
216.17 - * version 2 for more details (a copy is included in the LICENSE file that
216.18 - * accompanied this code).
216.19 - *
216.20 - * You should have received a copy of the GNU General Public License version
216.21 - * 2 along with this work; if not, write to the Free Software Foundation,
216.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
216.23 - *
216.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
216.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
216.26 - * have any questions.
216.27 - */
216.28 -
216.29 -package javax.management.namespace;
216.30 -
216.31 -import com.sun.jmx.mbeanserver.Util;
216.32 -import java.io.IOException;
216.33 -import java.io.ObjectInputStream;
216.34 -import java.util.Set;
216.35 -
216.36 -import javax.management.Attribute;
216.37 -import javax.management.AttributeList;
216.38 -import javax.management.AttributeNotFoundException;
216.39 -import javax.management.InstanceAlreadyExistsException;
216.40 -import javax.management.InstanceNotFoundException;
216.41 -import javax.management.IntrospectionException;
216.42 -import javax.management.InvalidAttributeValueException;
216.43 -import javax.management.ListenerNotFoundException;
216.44 -import javax.management.MBeanException;
216.45 -import javax.management.MBeanInfo;
216.46 -import javax.management.MBeanRegistrationException;
216.47 -import javax.management.MBeanServer;
216.48 -import javax.management.MBeanServerConnection;
216.49 -import javax.management.NotCompliantMBeanException;
216.50 -import javax.management.NotificationFilter;
216.51 -import javax.management.NotificationListener;
216.52 -import javax.management.ObjectInstance;
216.53 -import javax.management.ObjectName;
216.54 -import javax.management.OperationsException;
216.55 -import javax.management.QueryExp;
216.56 -import javax.management.ReflectionException;
216.57 -import javax.management.loading.ClassLoaderRepository;
216.58 -
216.59 -/**
216.60 - * <p>An object of this class implements the MBeanServer interface
216.61 - * and, for each of its methods forwards the request to a wrapped
216.62 - * {@link MBeanServerConnection} object.
216.63 - * Some methods of the {@link MBeanServer} interface do not have
216.64 - * any equivalent in {@link MBeanServerConnection}. In that case, an
216.65 - * {@link UnsupportedOperationException} will be thrown.
216.66 - *
216.67 - * <p>A typical use of this class is to apply a {@link QueryExp} object locally,
216.68 - * on an MBean that resides in a remote MBeanServer. Since an
216.69 - * MBeanServerConnection is not an MBeanServer, it cannot be passed
216.70 - * to the <code>setMBeanServer()</code> method of the {@link QueryExp}
216.71 - * object. However, this object can.</p>
216.72 - *
216.73 - * @since 1.7
216.74 - */
216.75 -public class MBeanServerConnectionWrapper
216.76 - implements MBeanServer {
216.77 -
216.78 - private final MBeanServerConnection wrapped;
216.79 - private final ClassLoader defaultCl;
216.80 -
216.81 - /**
216.82 - * Construct a new object that implements {@link MBeanServer} by
216.83 - * forwarding its methods to the given {@link MBeanServerConnection}.
216.84 - * This constructor is equivalent to {@link #MBeanServerConnectionWrapper(
216.85 - * MBeanServerConnection, ClassLoader) MBeanServerConnectionWrapper(wrapped,
216.86 - * null)}.
216.87 - *
216.88 - * @param wrapped the {@link MBeanServerConnection} to which methods
216.89 - * are to be forwarded. This parameter can be null, in which case the
216.90 - * {@code MBeanServerConnection} will typically be supplied by overriding
216.91 - * {@link #getMBeanServerConnection}.
216.92 - */
216.93 - public MBeanServerConnectionWrapper(MBeanServerConnection wrapped) {
216.94 - this(wrapped, null);
216.95 - }
216.96 -
216.97 - /**
216.98 - * Construct a new object that implements {@link MBeanServer} by
216.99 - * forwarding its methods to the given {@link MBeanServerConnection}.
216.100 - * The {@code defaultCl} parameter specifies the value to be returned
216.101 - * by {@link #getDefaultClassLoader}. A null value is equivalent to
216.102 - * {@link Thread#getContextClassLoader()}.
216.103 - *
216.104 - * @param wrapped the {@link MBeanServerConnection} to which methods
216.105 - * are to be forwarded. This parameter can be null, in which case the
216.106 - * {@code MBeanServerConnection} will typically be supplied by overriding
216.107 - * {@link #getMBeanServerConnection}.
216.108 - * @param defaultCl the value to be returned by {@link
216.109 - * #getDefaultClassLoader}. A null value is equivalent to the current
216.110 - * thread's {@linkplain Thread#getContextClassLoader()}.
216.111 - */
216.112 - public MBeanServerConnectionWrapper(MBeanServerConnection wrapped,
216.113 - ClassLoader defaultCl) {
216.114 - this.wrapped = wrapped;
216.115 - this.defaultCl = (defaultCl == null) ?
216.116 - Thread.currentThread().getContextClassLoader() : defaultCl;
216.117 - }
216.118 -
216.119 - /**
216.120 - * Returns an MBeanServerConnection. This method is called each time
216.121 - * an operation must be invoked on the underlying MBeanServerConnection.
216.122 - * The default implementation returns the MBeanServerConnection that
216.123 - * was supplied to the constructor of this MBeanServerConnectionWrapper.
216.124 - **/
216.125 - protected MBeanServerConnection getMBeanServerConnection() {
216.126 - return wrapped;
216.127 - }
216.128 -
216.129 - /**
216.130 - * Returns the default class loader passed to the constructor. If the
216.131 - * value passed was null, then the returned value will be the
216.132 - * {@linkplain Thread#getContextClassLoader() context class loader} at the
216.133 - * time this object was constructed.
216.134 - *
216.135 - * @return the ClassLoader that was passed to the constructor.
216.136 - **/
216.137 - public ClassLoader getDefaultClassLoader() {
216.138 - return defaultCl;
216.139 - }
216.140 -
216.141 - /**
216.142 - * <p>This method is called each time an IOException is raised when
216.143 - * trying to forward an operation to the underlying
216.144 - * MBeanServerConnection, as a result of calling
216.145 - * {@link #getMBeanServerConnection()} or as a result of invoking the
216.146 - * operation on the returned connection. Since the methods in
216.147 - * {@link MBeanServer} are not declared to throw {@code IOException},
216.148 - * this method must return a {@code RuntimeException} to be thrown
216.149 - * instead. Typically, the original {@code IOException} will be in the
216.150 - * {@linkplain Throwable#getCause() cause chain} of the {@code
216.151 - * RuntimeException}.</p>
216.152 - *
216.153 - * <p>Subclasses may redefine this method if they need to perform any
216.154 - * specific handling of IOException (logging etc...).</p>
216.155 - *
216.156 - * @param x The raised IOException.
216.157 - * @param method The name of the method in which the exception was
216.158 - * raised. This is one of the methods of the MBeanServer
216.159 - * interface.
216.160 - *
216.161 - * @return A RuntimeException that should be thrown by the caller.
216.162 - * In this default implementation, this is a
216.163 - * {@link RuntimeException} wrapping <var>x</var>.
216.164 - **/
216.165 - protected RuntimeException wrapIOException(IOException x, String method) {
216.166 - return Util.newRuntimeIOException(x);
216.167 - }
216.168 -
216.169 - // Take care of getMBeanServerConnection returning null.
216.170 - //
216.171 - private synchronized MBeanServerConnection connection()
216.172 - throws IOException {
216.173 - final MBeanServerConnection c = getMBeanServerConnection();
216.174 - if (c == null)
216.175 - throw new IOException("MBeanServerConnection unavailable");
216.176 - return c;
216.177 - }
216.178 -
216.179 - //--------------------------------------------
216.180 - //--------------------------------------------
216.181 - //
216.182 - // Implementation of the MBeanServer interface
216.183 - //
216.184 - //--------------------------------------------
216.185 - //--------------------------------------------
216.186 -
216.187 - /**
216.188 - * Forward this method to the
216.189 - * wrapped object.
216.190 - */
216.191 - public void addNotificationListener(ObjectName name,
216.192 - NotificationListener listener,
216.193 - NotificationFilter filter,
216.194 - Object handback)
216.195 - throws InstanceNotFoundException {
216.196 - try {
216.197 - connection().addNotificationListener(name, listener,
216.198 - filter, handback);
216.199 - } catch (IOException x) {
216.200 - throw wrapIOException(x,"addNotificationListener");
216.201 - }
216.202 - }
216.203 -
216.204 - /**
216.205 - * Forward this method to the
216.206 - * wrapped object.
216.207 - */
216.208 - public void addNotificationListener(ObjectName name,
216.209 - ObjectName listener,
216.210 - NotificationFilter filter,
216.211 - Object handback)
216.212 - throws InstanceNotFoundException {
216.213 - try {
216.214 - connection().addNotificationListener(name, listener,
216.215 - filter, handback);
216.216 - } catch (IOException x) {
216.217 - throw wrapIOException(x,"addNotificationListener");
216.218 - }
216.219 - }
216.220 -
216.221 - /**
216.222 - * Forward this method to the
216.223 - * wrapped object.
216.224 - */
216.225 - public ObjectInstance createMBean(String className, ObjectName name)
216.226 - throws
216.227 - ReflectionException,
216.228 - InstanceAlreadyExistsException,
216.229 - MBeanRegistrationException,
216.230 - MBeanException,
216.231 - NotCompliantMBeanException {
216.232 - try {
216.233 - return connection().createMBean(className, name);
216.234 - } catch (IOException x) {
216.235 - throw wrapIOException(x,"createMBean");
216.236 - }
216.237 - }
216.238 -
216.239 - /**
216.240 - * Forward this method to the
216.241 - * wrapped object.
216.242 - */
216.243 - public ObjectInstance createMBean(String className, ObjectName name,
216.244 - Object params[], String signature[])
216.245 - throws
216.246 - ReflectionException,
216.247 - InstanceAlreadyExistsException,
216.248 - MBeanRegistrationException,
216.249 - MBeanException,
216.250 - NotCompliantMBeanException {
216.251 - try {
216.252 - return connection().createMBean(className, name,
216.253 - params, signature);
216.254 - } catch (IOException x) {
216.255 - throw wrapIOException(x,"createMBean");
216.256 - }
216.257 - }
216.258 -
216.259 - /**
216.260 - * Forward this method to the
216.261 - * wrapped object.
216.262 - */
216.263 - public ObjectInstance createMBean(String className,
216.264 - ObjectName name,
216.265 - ObjectName loaderName)
216.266 - throws
216.267 - ReflectionException,
216.268 - InstanceAlreadyExistsException,
216.269 - MBeanRegistrationException,
216.270 - MBeanException,
216.271 - NotCompliantMBeanException,
216.272 - InstanceNotFoundException {
216.273 - try {
216.274 - return connection().createMBean(className, name, loaderName);
216.275 - } catch (IOException x) {
216.276 - throw wrapIOException(x,"createMBean");
216.277 - }
216.278 - }
216.279 -
216.280 - /**
216.281 - * Forward this method to the
216.282 - * wrapped object.
216.283 - */
216.284 - public ObjectInstance createMBean(String className,
216.285 - ObjectName name,
216.286 - ObjectName loaderName,
216.287 - Object params[],
216.288 - String signature[])
216.289 - throws
216.290 - ReflectionException,
216.291 - InstanceAlreadyExistsException,
216.292 - MBeanRegistrationException,
216.293 - MBeanException,
216.294 - NotCompliantMBeanException,
216.295 - InstanceNotFoundException {
216.296 - try {
216.297 - return connection().createMBean(className, name, loaderName,
216.298 - params, signature);
216.299 - } catch (IOException x) {
216.300 - throw wrapIOException(x,"createMBean");
216.301 - }
216.302 - }
216.303 -
216.304 - /**
216.305 - * Throws an {@link UnsupportedOperationException}. This behavior can
216.306 - * be changed by subclasses.
216.307 - * @deprecated see {@link MBeanServer#deserialize(ObjectName,byte[])
216.308 - * MBeanServer}
216.309 - */
216.310 - @Deprecated
216.311 - public ObjectInputStream deserialize(ObjectName name, byte[] data)
216.312 - throws InstanceNotFoundException, OperationsException {
216.313 - throw new UnsupportedOperationException("deserialize");
216.314 - }
216.315 -
216.316 - /**
216.317 - * Throws an {@link UnsupportedOperationException}. This behavior can
216.318 - * be changed by subclasses.
216.319 - * @deprecated see {@link MBeanServer#deserialize(String,byte[])
216.320 - * MBeanServer}
216.321 - */
216.322 - @Deprecated
216.323 - public ObjectInputStream deserialize(String className, byte[] data)
216.324 - throws OperationsException, ReflectionException {
216.325 - throw new UnsupportedOperationException("deserialize");
216.326 - }
216.327 -
216.328 - /**
216.329 - * Throws an {@link UnsupportedOperationException}. This behavior can
216.330 - * be changed by subclasses.
216.331 - * @deprecated see {@link MBeanServer#deserialize(String,ObjectName,byte[])
216.332 - * MBeanServer}
216.333 - */
216.334 - @Deprecated
216.335 - public ObjectInputStream deserialize(String className,
216.336 - ObjectName loaderName,
216.337 - byte[] data)
216.338 - throws
216.339 - InstanceNotFoundException,
216.340 - OperationsException,
216.341 - ReflectionException {
216.342 - throw new UnsupportedOperationException("deserialize");
216.343 - }
216.344 -
216.345 - /**
216.346 - * Forward this method to the
216.347 - * wrapped object.
216.348 - */
216.349 - public Object getAttribute(ObjectName name, String attribute)
216.350 - throws
216.351 - MBeanException,
216.352 - AttributeNotFoundException,
216.353 - InstanceNotFoundException,
216.354 - ReflectionException {
216.355 - try {
216.356 - return connection().getAttribute(name, attribute);
216.357 - } catch (IOException x) {
216.358 - throw wrapIOException(x,"getAttribute");
216.359 - }
216.360 - }
216.361 -
216.362 - /**
216.363 - * Forward this method to the
216.364 - * wrapped object.
216.365 - */
216.366 - public AttributeList getAttributes(ObjectName name, String[] attributes)
216.367 - throws InstanceNotFoundException, ReflectionException {
216.368 - try {
216.369 - return connection().getAttributes(name, attributes);
216.370 - } catch (IOException x) {
216.371 - throw wrapIOException(x,"getAttributes");
216.372 - }
216.373 - }
216.374 -
216.375 - /**
216.376 - * Throws an {@link UnsupportedOperationException}. This behavior can
216.377 - * be changed by subclasses.
216.378 - */
216.379 - public ClassLoader getClassLoader(ObjectName loaderName)
216.380 - throws InstanceNotFoundException {
216.381 - throw new UnsupportedOperationException("getClassLoader");
216.382 - }
216.383 -
216.384 - /**
216.385 - * Returns the {@linkplain #getDefaultClassLoader() default class loader}.
216.386 - * This behavior can be changed by subclasses.
216.387 - */
216.388 - public ClassLoader getClassLoaderFor(ObjectName mbeanName)
216.389 - throws InstanceNotFoundException {
216.390 - return getDefaultClassLoader();
216.391 - }
216.392 -
216.393 - /**
216.394 - * <p>Returns a {@link ClassLoaderRepository} based on the class loader
216.395 - * returned by {@link #getDefaultClassLoader()}.</p>
216.396 - * @return a {@link ClassLoaderRepository} that contains a single
216.397 - * class loader, returned by {@link #getDefaultClassLoader()}.
216.398 - **/
216.399 - public ClassLoaderRepository getClassLoaderRepository() {
216.400 - // We return a new ClassLoaderRepository each time this method is
216.401 - // called. This is by design, because there's no guarantee that
216.402 - // getDefaultClassLoader() will always return the same class loader.
216.403 - return Util.getSingleClassLoaderRepository(getDefaultClassLoader());
216.404 - }
216.405 -
216.406 - /**
216.407 - * Forward this method to the
216.408 - * wrapped object.
216.409 - */
216.410 - public String getDefaultDomain() {
216.411 - try {
216.412 - return connection().getDefaultDomain();
216.413 - } catch (IOException x) {
216.414 - throw wrapIOException(x,"getDefaultDomain");
216.415 - }
216.416 - }
216.417 -
216.418 - /**
216.419 - * Forward this method to the
216.420 - * wrapped object.
216.421 - */
216.422 - public String[] getDomains() {
216.423 - try {
216.424 - return connection().getDomains();
216.425 - } catch (IOException x) {
216.426 - throw wrapIOException(x,"getDomains");
216.427 - }
216.428 - }
216.429 -
216.430 - /**
216.431 - * Forward this method to the
216.432 - * wrapped object.
216.433 - */
216.434 - public Integer getMBeanCount() {
216.435 - try {
216.436 - return connection().getMBeanCount();
216.437 - } catch (IOException x) {
216.438 - throw wrapIOException(x,"getMBeanCount");
216.439 - }
216.440 - }
216.441 -
216.442 - /**
216.443 - * Forward this method to the
216.444 - * wrapped object.
216.445 - */
216.446 - public MBeanInfo getMBeanInfo(ObjectName name)
216.447 - throws
216.448 - InstanceNotFoundException,
216.449 - IntrospectionException,
216.450 - ReflectionException {
216.451 - try {
216.452 - return connection().getMBeanInfo(name);
216.453 - } catch (IOException x) {
216.454 - throw wrapIOException(x,"getMBeanInfo");
216.455 - }
216.456 - }
216.457 -
216.458 - /**
216.459 - * Forward this method to the
216.460 - * wrapped object.
216.461 - */
216.462 - public ObjectInstance getObjectInstance(ObjectName name)
216.463 - throws InstanceNotFoundException {
216.464 - try {
216.465 - return connection().getObjectInstance(name);
216.466 - } catch (IOException x) {
216.467 - throw wrapIOException(x,"getObjectInstance");
216.468 - }
216.469 - }
216.470 -
216.471 - /**
216.472 - * Throws an {@link UnsupportedOperationException}. This behavior can
216.473 - * be changed by subclasses.
216.474 - */
216.475 - public Object instantiate(String className)
216.476 - throws ReflectionException, MBeanException {
216.477 - throw new UnsupportedOperationException("instantiate");
216.478 - }
216.479 -
216.480 - /**
216.481 - * Throws an {@link UnsupportedOperationException}. This behavior can
216.482 - * be changed by subclasses.
216.483 - */
216.484 - public Object instantiate(String className,
216.485 - Object params[],
216.486 - String signature[])
216.487 - throws ReflectionException, MBeanException {
216.488 - throw new UnsupportedOperationException("instantiate");
216.489 - }
216.490 -
216.491 - /**
216.492 - * Throws an {@link UnsupportedOperationException}. This behavior can
216.493 - * be changed by subclasses.
216.494 - */
216.495 - public Object instantiate(String className, ObjectName loaderName)
216.496 - throws ReflectionException, MBeanException,
216.497 - InstanceNotFoundException {
216.498 - throw new UnsupportedOperationException("instantiate");
216.499 - }
216.500 -
216.501 - /**
216.502 - * Throws an {@link UnsupportedOperationException}. This behavior can
216.503 - * be changed by subclasses.
216.504 - */
216.505 - public Object instantiate(String className, ObjectName loaderName,
216.506 - Object params[], String signature[])
216.507 - throws ReflectionException, MBeanException,
216.508 - InstanceNotFoundException {
216.509 - throw new UnsupportedOperationException("instantiate");
216.510 - }
216.511 -
216.512 - /**
216.513 - * Forward this method to the
216.514 - * wrapped object.
216.515 - */
216.516 - public Object invoke(ObjectName name, String operationName,
216.517 - Object params[], String signature[])
216.518 - throws
216.519 - InstanceNotFoundException,
216.520 - MBeanException,
216.521 - ReflectionException {
216.522 - try {
216.523 - return connection().invoke(name,operationName,params,signature);
216.524 - } catch (IOException x) {
216.525 - throw wrapIOException(x,"invoke");
216.526 - }
216.527 - }
216.528 -
216.529 - /**
216.530 - * Forward this method to the
216.531 - * wrapped object.
216.532 - */
216.533 - public boolean isInstanceOf(ObjectName name, String className)
216.534 - throws InstanceNotFoundException {
216.535 - try {
216.536 - return connection().isInstanceOf(name, className);
216.537 - } catch (IOException x) {
216.538 - throw wrapIOException(x,"isInstanceOf");
216.539 - }
216.540 - }
216.541 -
216.542 - /**
216.543 - * Forward this method to the
216.544 - * wrapped object.
216.545 - */
216.546 - public boolean isRegistered(ObjectName name) {
216.547 - try {
216.548 - return connection().isRegistered(name);
216.549 - } catch (IOException x) {
216.550 - throw wrapIOException(x,"isRegistered");
216.551 - }
216.552 - }
216.553 -
216.554 - /**
216.555 - * Forward this method to the
216.556 - * wrapped object.
216.557 - * If an IOException is raised, returns an empty Set.
216.558 - */
216.559 - public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
216.560 - try {
216.561 - return connection().queryMBeans(name, query);
216.562 - } catch (IOException x) {
216.563 - throw wrapIOException(x,"queryMBeans");
216.564 - //return Collections.emptySet();
216.565 - }
216.566 - }
216.567 -
216.568 - /**
216.569 - * Forward this method to the
216.570 - * wrapped object.
216.571 - * If an IOException is raised, returns an empty Set.
216.572 - */
216.573 - public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
216.574 - try {
216.575 - return connection().queryNames(name, query);
216.576 - } catch (IOException x) {
216.577 - throw wrapIOException(x,"queryNames");
216.578 - //return Collections.emptySet();
216.579 - }
216.580 - }
216.581 -
216.582 - /**
216.583 - * Throws an {@link UnsupportedOperationException}. This behavior can
216.584 - * be changed by subclasses.
216.585 - */
216.586 - public ObjectInstance registerMBean(Object object, ObjectName name)
216.587 - throws
216.588 - InstanceAlreadyExistsException,
216.589 - MBeanRegistrationException,
216.590 - NotCompliantMBeanException {
216.591 - throw new UnsupportedOperationException("registerMBean");
216.592 - }
216.593 -
216.594 - /**
216.595 - * Forward this method to the
216.596 - * wrapped object.
216.597 - */
216.598 - public void removeNotificationListener(ObjectName name,
216.599 - NotificationListener listener)
216.600 - throws InstanceNotFoundException, ListenerNotFoundException {
216.601 - try {
216.602 - connection().removeNotificationListener(name, listener);
216.603 - } catch (IOException x) {
216.604 - throw wrapIOException(x,"removeNotificationListener");
216.605 - }
216.606 - }
216.607 -
216.608 - /**
216.609 - * Forward this method to the
216.610 - * wrapped object.
216.611 - */
216.612 - public void removeNotificationListener(ObjectName name,
216.613 - NotificationListener listener,
216.614 - NotificationFilter filter,
216.615 - Object handback)
216.616 - throws InstanceNotFoundException, ListenerNotFoundException {
216.617 - try {
216.618 - connection().removeNotificationListener(name, listener,
216.619 - filter, handback);
216.620 - } catch (IOException x) {
216.621 - throw wrapIOException(x,"removeNotificationListener");
216.622 - }
216.623 - }
216.624 -
216.625 - /**
216.626 - * Forward this method to the
216.627 - * wrapped object.
216.628 - */
216.629 - public void removeNotificationListener(ObjectName name,
216.630 - ObjectName listener)
216.631 - throws InstanceNotFoundException, ListenerNotFoundException {
216.632 - try {
216.633 - connection().removeNotificationListener(name, listener);
216.634 - } catch (IOException x) {
216.635 - throw wrapIOException(x,"removeNotificationListener");
216.636 - }
216.637 - }
216.638 -
216.639 - /**
216.640 - * Forward this method to the
216.641 - * wrapped object.
216.642 - */
216.643 - public void removeNotificationListener(ObjectName name,
216.644 - ObjectName listener,
216.645 - NotificationFilter filter,
216.646 - Object handback)
216.647 - throws InstanceNotFoundException, ListenerNotFoundException {
216.648 - try {
216.649 - connection().removeNotificationListener(name, listener,
216.650 - filter, handback);
216.651 - } catch (IOException x) {
216.652 - throw wrapIOException(x,"removeNotificationListener");
216.653 - }
216.654 - }
216.655 -
216.656 - /**
216.657 - * Forward this method to the
216.658 - * wrapped object.
216.659 - */
216.660 - public void setAttribute(ObjectName name, Attribute attribute)
216.661 - throws
216.662 - InstanceNotFoundException,
216.663 - AttributeNotFoundException,
216.664 - InvalidAttributeValueException,
216.665 - MBeanException,
216.666 - ReflectionException {
216.667 - try {
216.668 - connection().setAttribute(name, attribute);
216.669 - } catch (IOException x) {
216.670 - throw wrapIOException(x,"setAttribute");
216.671 - }
216.672 - }
216.673 -
216.674 - /**
216.675 - * Forward this method to the
216.676 - * wrapped object.
216.677 - */
216.678 - public AttributeList setAttributes(ObjectName name,
216.679 - AttributeList attributes)
216.680 - throws InstanceNotFoundException, ReflectionException {
216.681 - try {
216.682 - return connection().setAttributes(name, attributes);
216.683 - } catch (IOException x) {
216.684 - throw wrapIOException(x,"setAttributes");
216.685 - }
216.686 - }
216.687 -
216.688 - /**
216.689 - * Forward this method to the
216.690 - * wrapped object.
216.691 - */
216.692 - public void unregisterMBean(ObjectName name)
216.693 - throws InstanceNotFoundException, MBeanRegistrationException {
216.694 - try {
216.695 - connection().unregisterMBean(name);
216.696 - } catch (IOException x) {
216.697 - throw wrapIOException(x,"unregisterMBean");
216.698 - }
216.699 - }
216.700 -
216.701 - //----------------
216.702 - // PRIVATE METHODS
216.703 - //----------------
216.704 -
216.705 -}
217.1 --- a/src/share/classes/javax/management/namespace/MBeanServerSupport.java Mon Nov 23 10:04:47 2009 +0000
217.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
217.3 @@ -1,1321 +0,0 @@
217.4 -/*
217.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
217.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
217.7 - *
217.8 - * This code is free software; you can redistribute it and/or modify it
217.9 - * under the terms of the GNU General Public License version 2 only, as
217.10 - * published by the Free Software Foundation. Sun designates this
217.11 - * particular file as subject to the "Classpath" exception as provided
217.12 - * by Sun in the LICENSE file that accompanied this code.
217.13 - *
217.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
217.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
217.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
217.17 - * version 2 for more details (a copy is included in the LICENSE file that
217.18 - * accompanied this code).
217.19 - *
217.20 - * You should have received a copy of the GNU General Public License version
217.21 - * 2 along with this work; if not, write to the Free Software Foundation,
217.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
217.23 - *
217.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
217.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
217.26 - * have any questions.
217.27 - */
217.28 -package javax.management.namespace;
217.29 -
217.30 -import com.sun.jmx.defaults.JmxProperties;
217.31 -import com.sun.jmx.mbeanserver.Util;
217.32 -import java.io.ObjectInputStream;
217.33 -import java.util.Collections;
217.34 -import java.util.HashSet;
217.35 -import java.util.Set;
217.36 -import java.util.TreeSet;
217.37 -import java.util.logging.Level;
217.38 -import java.util.logging.Logger;
217.39 -import javax.management.Attribute;
217.40 -import javax.management.AttributeList;
217.41 -import javax.management.AttributeNotFoundException;
217.42 -import javax.management.DynamicMBean;
217.43 -import javax.management.DynamicWrapperMBean;
217.44 -import javax.management.InstanceAlreadyExistsException;
217.45 -import javax.management.InstanceNotFoundException;
217.46 -import javax.management.IntrospectionException;
217.47 -import javax.management.InvalidAttributeValueException;
217.48 -import javax.management.JMRuntimeException;
217.49 -import javax.management.ListenerNotFoundException;
217.50 -import javax.management.MBeanException;
217.51 -import javax.management.MBeanInfo;
217.52 -import javax.management.MBeanRegistrationException;
217.53 -import javax.management.MBeanServer;
217.54 -import javax.management.NotCompliantMBeanException;
217.55 -import javax.management.NotificationBroadcaster;
217.56 -import javax.management.NotificationEmitter;
217.57 -import javax.management.NotificationFilter;
217.58 -import javax.management.NotificationListener;
217.59 -import javax.management.ObjectInstance;
217.60 -import javax.management.ObjectName;
217.61 -import javax.management.OperationsException;
217.62 -import javax.management.QueryEval;
217.63 -import javax.management.QueryExp;
217.64 -import javax.management.ReflectionException;
217.65 -import javax.management.RuntimeOperationsException;
217.66 -import javax.management.loading.ClassLoaderRepository;
217.67 -
217.68 -/**
217.69 - * <p>Base class for custom implementations of the {@link MBeanServer}
217.70 - * interface. The commonest use of this class is as the {@linkplain
217.71 - * JMXNamespace#getSourceServer() source server} for a {@link
217.72 - * JMXNamespace}, although this class can be used anywhere an {@code
217.73 - * MBeanServer} instance is required. Note that the usual ways to
217.74 - * obtain an {@code MBeanServer} instance are either to use {@link
217.75 - * java.lang.management.ManagementFactory#getPlatformMBeanServer()
217.76 - * ManagementFactory.getPlatformMBeanServer()} or to use the {@code
217.77 - * newMBeanServer} or {@code createMBeanServer} methods from {@link
217.78 - * javax.management.MBeanServerFactory MBeanServerFactory}. {@code
217.79 - * MBeanServerSupport} is for certain cases where those are not
217.80 - * appropriate.</p>
217.81 - *
217.82 - * <p>There are two main use cases for this class: <a
217.83 - * href="#special-purpose">special-purpose MBeanServer implementations</a>,
217.84 - * and <a href="#virtual">namespaces containing Virtual MBeans</a>. The next
217.85 - * sections explain these use cases.</p>
217.86 - *
217.87 - * <p>In the simplest case, a subclass needs to implement only two methods:</p>
217.88 - *
217.89 - * <ul>
217.90 - * <li>
217.91 - * {@link #getNames getNames} which returns the name of
217.92 - * all MBeans handled by this {@code MBeanServer}.
217.93 - * </li>
217.94 - * <li>
217.95 - * {@link #getDynamicMBeanFor getDynamicMBeanFor} which returns a
217.96 - * {@link DynamicMBean} that can be used to invoke operations and
217.97 - * obtain meta data (MBeanInfo) on a given MBean.
217.98 - * </li>
217.99 - * </ul>
217.100 - *
217.101 - * <p>Subclasses can create such {@link DynamicMBean} MBeans on the fly - for
217.102 - * instance, using the class {@link javax.management.StandardMBean}, just for
217.103 - * the duration of an MBeanServer method call.</p>
217.104 - *
217.105 - * <h4 id="special-purpose">Special-purpose MBeanServer implementations</h4>
217.106 - *
217.107 - * <p>In some cases
217.108 - * the general-purpose {@code MBeanServer} that you get from
217.109 - * {@link javax.management.MBeanServerFactory MBeanServerFactory} is not
217.110 - * appropriate. You might need different security checks, or you might
217.111 - * want a mock {@code MBeanServer} suitable for use in tests, or you might
217.112 - * want a simplified and optimized {@code MBeanServer} for a special purpose.</p>
217.113 - *
217.114 - * <p>As an example of a special-purpose {@code MBeanServer}, the class {@link
217.115 - * javax.management.QueryNotificationFilter QueryNotificationFilter} constructs
217.116 - * an {@code MBeanServer} instance every time it filters a notification,
217.117 - * with just one MBean that represents the notification. Although it could
217.118 - * use {@code MBeanServerFactory.newMBeanServer}, a special-purpose {@code
217.119 - * MBeanServer} will be quicker to create, use less memory, and have simpler
217.120 - * methods that execute faster.</p>
217.121 - *
217.122 - * <p>Here is an example of a special-purpose {@code MBeanServer}
217.123 - * implementation that contains exactly one MBean, which is specified at the
217.124 - * time of creation.</p>
217.125 - *
217.126 - * <pre>
217.127 - * public class SingletonMBeanServer extends MBeanServerSupport {
217.128 - * private final ObjectName objectName;
217.129 - * private final DynamicMBean mbean;
217.130 - *
217.131 - * public SingletonMBeanServer(ObjectName objectName, DynamicMBean mbean) {
217.132 - * this.objectName = objectName;
217.133 - * this.mbean = mbean;
217.134 - * }
217.135 - *
217.136 - * @Override
217.137 - * protected {@code Set<ObjectName>} {@link #getNames getNames}() {
217.138 - * return Collections.singleton(objectName);
217.139 - * }
217.140 - *
217.141 - * @Override
217.142 - * public DynamicMBean {@link #getDynamicMBeanFor
217.143 - * getDynamicMBeanFor}(ObjectName name)
217.144 - * throws InstanceNotFoundException {
217.145 - * if (objectName.equals(name))
217.146 - * return mbean;
217.147 - * else
217.148 - * throw new InstanceNotFoundException(name);
217.149 - * }
217.150 - * }
217.151 - * </pre>
217.152 - *
217.153 - * <p>Using this class, you could make an {@code MBeanServer} that contains
217.154 - * a {@link javax.management.timer.Timer Timer} MBean like this:</p>
217.155 - *
217.156 - * <pre>
217.157 - * Timer timer = new Timer();
217.158 - * DynamicMBean mbean = new {@link javax.management.StandardMBean
217.159 - * StandardMBean}(timer, TimerMBean.class);
217.160 - * ObjectName name = new ObjectName("com.example:type=Timer");
217.161 - * MBeanServer timerMBS = new SingletonMBeanServer(name, mbean);
217.162 - * </pre>
217.163 - *
217.164 - * <p>When {@code getDynamicMBeanFor} always returns the same object for the
217.165 - * same name, as here, notifications work in the expected way: if the object
217.166 - * is a {@link NotificationEmitter} then listeners can be added using
217.167 - * {@link MBeanServer#addNotificationListener(ObjectName, NotificationListener,
217.168 - * NotificationFilter, Object) MBeanServer.addNotificationListener}. If
217.169 - * {@code getDynamicMBeanFor} does not always return the same object for the
217.170 - * same name, more work is needed to make notifications work, as described
217.171 - * <a href="#notifs">below</a>.</p>
217.172 - *
217.173 - * <h4 id="virtual">Namespaces containing Virtual MBeans</h4>
217.174 - *
217.175 - * <p>Virtual MBeans are MBeans that do not exist as Java objects,
217.176 - * except transiently while they are being accessed. This is useful when
217.177 - * there might be very many of them, or when keeping track of their creation
217.178 - * and deletion might be expensive or hard. For example, you might have one
217.179 - * MBean per system process. With an ordinary {@code MBeanServer}, you would
217.180 - * have to list the system processes in order to create an MBean object for
217.181 - * each one, and you would have to track the arrival and departure of system
217.182 - * processes in order to create or delete the corresponding MBeans. With
217.183 - * Virtual MBeans, you only need the MBean for a given process at the exact
217.184 - * point where it is referenced with a call such as
217.185 - * {@link MBeanServer#getAttribute MBeanServer.getAttribute}.</p>
217.186 - *
217.187 - * <p>Here is an example of an {@code MBeanServer} implementation that has
217.188 - * one MBean for every system property. The system property {@code "java.home"}
217.189 - * is represented by the MBean called {@code
217.190 - * com.example:type=Property,name="java.home"}, with an attribute called
217.191 - * {@code Value} that is the value of the property.</p>
217.192 - *
217.193 - * <pre>
217.194 - * public interface PropertyMBean {
217.195 - * public String getValue();
217.196 - * }
217.197 - *
217.198 - * <a name="PropsMBS"></a>public class PropsMBS extends MBeanServerSupport {
217.199 - * public static class PropertyImpl implements PropertyMBean {
217.200 - * private final String name;
217.201 - *
217.202 - * public PropertyImpl(String name) {
217.203 - * this.name = name;
217.204 - * }
217.205 - *
217.206 - * public String getValue() {
217.207 - * return System.getProperty(name);
217.208 - * }
217.209 - * }
217.210 - *
217.211 - * @Override
217.212 - * public DynamicMBean {@link #getDynamicMBeanFor
217.213 - * getDynamicMBeanFor}(ObjectName name)
217.214 - * throws InstanceNotFoundException {
217.215 - *
217.216 - * // Check that the name is a legal one for a Property MBean
217.217 - * ObjectName namePattern = ObjectName.valueOf(
217.218 - * "com.example:type=Property,name=\"*\"");
217.219 - * if (!namePattern.apply(name))
217.220 - * throw new InstanceNotFoundException(name);
217.221 - *
217.222 - * // Extract the name of the property that the MBean corresponds to
217.223 - * String propName = ObjectName.unquote(name.getKeyProperty("name"));
217.224 - * if (System.getProperty(propName) == null)
217.225 - * throw new InstanceNotFoundException(name);
217.226 - *
217.227 - * // Construct and return a transient MBean object
217.228 - * PropertyMBean propMBean = new PropertyImpl(propName);
217.229 - * return new StandardMBean(propMBean, PropertyMBean.class, false);
217.230 - * }
217.231 - *
217.232 - * @Override
217.233 - * protected {@code Set<ObjectName>} {@link #getNames getNames}() {
217.234 - * {@code Set<ObjectName> names = new TreeSet<ObjectName>();}
217.235 - * Properties props = System.getProperties();
217.236 - * for (String propName : props.stringPropertyNames()) {
217.237 - * ObjectName objectName = ObjectName.valueOf(
217.238 - * "com.example:type=Property,name=" +
217.239 - * ObjectName.quote(propName));
217.240 - * names.add(objectName);
217.241 - * }
217.242 - * return names;
217.243 - * }
217.244 - * }
217.245 - * </pre>
217.246 - *
217.247 - * <p id="virtual-notif-example">Because the {@code getDynamicMBeanFor} method
217.248 - * returns a different object every time it is called, the default handling
217.249 - * of notifications will not work, as explained <a href="#notifs">below</a>.
217.250 - * In this case it does not matter, because the object returned by {@code
217.251 - * getDynamicMBeanFor} is not a {@code NotificationEmitter}, so {@link
217.252 - * MBeanServer#addNotificationListener(ObjectName, NotificationListener,
217.253 - * NotificationFilter, Object) MBeanServer.addNotificationListener} will
217.254 - * always fail. But if we wanted to extend {@code PropsMBS} so that the MBean
217.255 - * for property {@code "foo"} emitted a notification every time that property
217.256 - * changed, we would need to do it as shown below. (Because there is no API to
217.257 - * be informed when a property changes, this code assumes that some other code
217.258 - * calls the {@code propertyChanged} method every time a property changes.)</p>
217.259 - *
217.260 - * <pre>
217.261 - * public class PropsMBS {
217.262 - * ...as <a href="#PropsMBS">above</a>...
217.263 - *
217.264 - * private final {@link VirtualEventManager} vem = new VirtualEventManager();
217.265 - *
217.266 - * @Override
217.267 - * public NotificationEmitter {@link #getNotificationEmitterFor
217.268 - * getNotificationEmitterFor}(
217.269 - * ObjectName name) throws InstanceNotFoundException {
217.270 - * getDynamicMBeanFor(name); // check that the name is valid
217.271 - * return vem.{@link VirtualEventManager#getNotificationEmitterFor
217.272 - * getNotificationEmitterFor}(name);
217.273 - * }
217.274 - *
217.275 - * public void propertyChanged(String name, String newValue) {
217.276 - * ObjectName objectName = ObjectName.valueOf(
217.277 - * "com.example:type=Property,name=" + ObjectName.quote(name));
217.278 - * Notification n = new Notification(
217.279 - * "com.example.property.changed", objectName, 0L,
217.280 - * "Property " + name + " changed");
217.281 - * n.setUserData(newValue);
217.282 - * vem.{@link VirtualEventManager#publish publish}(objectName, n);
217.283 - * }
217.284 - * }
217.285 - * </pre>
217.286 - *
217.287 - * <h4 id="creation">MBean creation and deletion</h4>
217.288 - *
217.289 - * <p>MBean creation through {@code MBeanServer.createMBean} is disabled
217.290 - * by default. Subclasses which need to support MBean creation
217.291 - * through {@code createMBean} need to implement a single method {@link
217.292 - * #createMBean(String, ObjectName, ObjectName, Object[], String[],
217.293 - * boolean)}.</p>
217.294 - *
217.295 - * <p>Similarly MBean registration and unregistration through {@code
217.296 - * registerMBean} and {@code unregisterMBean} are disabled by default.
217.297 - * Subclasses which need to support MBean registration and
217.298 - * unregistration will need to implement {@link #registerMBean registerMBean}
217.299 - * and {@link #unregisterMBean unregisterMBean}.</p>
217.300 - *
217.301 - * <h4 id="notifs">Notifications</h4>
217.302 - *
217.303 - * <p>By default {@link MBeanServer#addNotificationListener(ObjectName,
217.304 - * NotificationListener, NotificationFilter, Object) addNotificationListener}
217.305 - * is accepted for an MBean <em>{@code name}</em> if {@link #getDynamicMBeanFor
217.306 - * getDynamicMBeanFor}<code>(<em>name</em>)</code> returns an object that is a
217.307 - * {@link NotificationEmitter}. That is appropriate if
217.308 - * {@code getDynamicMBeanFor}<code>(<em>name</em>)</code> always returns the
217.309 - * same object for the same <em>{@code name}</em>. But with
217.310 - * Virtual MBeans, every call to {@code getDynamicMBeanFor} returns a new object,
217.311 - * which is discarded as soon as the MBean request has finished.
217.312 - * So a listener added to that object would be immediately forgotten.</p>
217.313 - *
217.314 - * <p>The simplest way for a subclass that defines Virtual MBeans
217.315 - * to support notifications is to create a private {@link VirtualEventManager}
217.316 - * and override the method {@link
217.317 - * #getNotificationEmitterFor getNotificationEmitterFor} as follows:</p>
217.318 - *
217.319 - * <pre>
217.320 - * private final VirtualEventManager vem = new VirtualEventManager();
217.321 - *
217.322 - * @Override
217.323 - * public NotificationEmitter getNotificationEmitterFor(
217.324 - * ObjectName name) throws InstanceNotFoundException {
217.325 - * // Check that the name is a valid Virtual MBean.
217.326 - * // This is the easiest way to do that, but not always the
217.327 - * // most efficient:
217.328 - * getDynamicMBeanFor(name);
217.329 - *
217.330 - * // Return an object that supports add/removeNotificationListener
217.331 - * // through the VirtualEventManager.
217.332 - * return vem.getNotificationEmitterFor(name);
217.333 - * }
217.334 - * </pre>
217.335 - *
217.336 - * <p>A notification <em>{@code n}</em> can then be sent from the Virtual MBean
217.337 - * called <em>{@code name}</em> by calling {@link VirtualEventManager#publish
217.338 - * vem.publish}<code>(<em>name</em>, <em>n</em>)</code>. See the example
217.339 - * <a href="#virtual-notif-example">above</a>.</p>
217.340 - *
217.341 - * @since 1.7
217.342 - */
217.343 -public abstract class MBeanServerSupport implements MBeanServer {
217.344 -
217.345 - /**
217.346 - * A logger for this class.
217.347 - */
217.348 - private static final Logger LOG =
217.349 - JmxProperties.NAMESPACE_LOGGER;
217.350 -
217.351 - /**
217.352 - * <p>Make a new {@code MBeanServerSupport} instance.</p>
217.353 - */
217.354 - protected MBeanServerSupport() {
217.355 - }
217.356 -
217.357 - /**
217.358 - * <p>Returns a dynamically created handle that makes it possible to
217.359 - * access the named MBean for the duration of a method call.</p>
217.360 - *
217.361 - * <p>An easy way to create such a {@link DynamicMBean} handle is, for
217.362 - * instance, to create a temporary MXBean instance and to wrap it in
217.363 - * an instance of
217.364 - * {@link javax.management.StandardMBean}.
217.365 - * This handle should remain valid for the duration of the call
217.366 - * but can then be discarded.</p>
217.367 - * @param name the name of the MBean for which a request was received.
217.368 - * @return a {@link DynamicMBean} handle that can be used to invoke
217.369 - * operations on the named MBean.
217.370 - * @throws InstanceNotFoundException if no such MBean is supposed
217.371 - * to exist.
217.372 - */
217.373 - public abstract DynamicMBean getDynamicMBeanFor(ObjectName name)
217.374 - throws InstanceNotFoundException;
217.375 -
217.376 - /**
217.377 - * <p>Subclasses should implement this method to return
217.378 - * the names of all MBeans handled by this object instance.</p>
217.379 - *
217.380 - * <p>The object returned by getNames() should be safely {@linkplain
217.381 - * Set#iterator iterable} even in the presence of other threads that may
217.382 - * cause the set of names to change. Typically this means one of the
217.383 - * following:</p>
217.384 - *
217.385 - * <ul>
217.386 - * <li>the returned set of names is always the same; or
217.387 - * <li>the returned set of names is an object such as a {@link
217.388 - * java.util.concurrent.CopyOnWriteArraySet CopyOnWriteArraySet} that is
217.389 - * safely iterable even if the set is changed by other threads; or
217.390 - * <li>a new Set is constructed every time this method is called.
217.391 - * </ul>
217.392 - *
217.393 - * @return the names of all MBeans handled by this object.
217.394 - */
217.395 - protected abstract Set<ObjectName> getNames();
217.396 -
217.397 - /**
217.398 - * <p>List names matching the given pattern.
217.399 - * The default implementation of this method calls {@link #getNames()}
217.400 - * and returns the subset of those names matching {@code pattern}.</p>
217.401 - *
217.402 - * @param pattern an ObjectName pattern
217.403 - * @return the list of MBean names that match the given pattern.
217.404 - */
217.405 - protected Set<ObjectName> getMatchingNames(ObjectName pattern) {
217.406 - return Util.filterMatchingNames(pattern, getNames());
217.407 - }
217.408 -
217.409 - /**
217.410 - * <p>Returns a {@link NotificationEmitter} which can be used to
217.411 - * subscribe or unsubscribe for notifications with the named
217.412 - * mbean.</p>
217.413 - *
217.414 - * <p>The default implementation of this method calls {@link
217.415 - * #getDynamicMBeanFor getDynamicMBeanFor(name)} and returns that object
217.416 - * if it is a {@code NotificationEmitter}, otherwise null. See <a
217.417 - * href="#notifs">above</a> for further discussion of notification
217.418 - * handling.</p>
217.419 - *
217.420 - * @param name The name of the MBean whose notifications are being
217.421 - * subscribed, or unsuscribed.
217.422 - *
217.423 - * @return A {@link NotificationEmitter} that can be used to subscribe or
217.424 - * unsubscribe for notifications emitted by the named MBean, or {@code
217.425 - * null} if the MBean does not emit notifications and should not be
217.426 - * considered as a {@code NotificationEmitter}.
217.427 - *
217.428 - * @throws InstanceNotFoundException if {@code name} is not the name of
217.429 - * an MBean in this {@code MBeanServer}.
217.430 - */
217.431 - public NotificationEmitter getNotificationEmitterFor(ObjectName name)
217.432 - throws InstanceNotFoundException {
217.433 - DynamicMBean mbean = getDynamicMBeanFor(name);
217.434 - if (mbean instanceof NotificationEmitter)
217.435 - return (NotificationEmitter) mbean;
217.436 - else
217.437 - return null;
217.438 - }
217.439 -
217.440 - private NotificationEmitter getNonNullNotificationEmitterFor(
217.441 - ObjectName name)
217.442 - throws InstanceNotFoundException {
217.443 - NotificationEmitter emitter = getNotificationEmitterFor(name);
217.444 - if (emitter == null) {
217.445 - IllegalArgumentException iae = new IllegalArgumentException(
217.446 - "Not a NotificationEmitter: " + name);
217.447 - throw new RuntimeOperationsException(iae);
217.448 - }
217.449 - return emitter;
217.450 - }
217.451 -
217.452 - /**
217.453 - * <p>Creates a new MBean in the MBean name space.
217.454 - * This operation is not supported in this base class implementation.</p>
217.455 - * The default implementation of this method always throws an {@link
217.456 - * UnsupportedOperationException}
217.457 - * wrapped in a {@link RuntimeOperationsException}.</p>
217.458 - *
217.459 - * <p>Subclasses may redefine this method to provide an implementation.
217.460 - * All the various flavors of {@code MBeanServer.createMBean} methods
217.461 - * will eventually call this method. A subclass that wishes to
217.462 - * support MBean creation through {@code createMBean} thus only
217.463 - * needs to provide an implementation for this one method.</p>
217.464 - *
217.465 - * <p>A subclass implementation of this method should respect the contract
217.466 - * of the various {@code createMBean} methods in the {@link MBeanServer}
217.467 - * interface, in particular as regards exception wrapping.</p>
217.468 - *
217.469 - * @param className The class name of the MBean to be instantiated.
217.470 - * @param name The object name of the MBean. May be null.
217.471 - * @param params An array containing the parameters of the
217.472 - * constructor to be invoked.
217.473 - * @param signature An array containing the signature of the
217.474 - * constructor to be invoked.
217.475 - * @param loaderName The object name of the class loader to be used.
217.476 - * @param useCLR This parameter is {@code true} when this method
217.477 - * is called from one of the {@code MBeanServer.createMBean} methods
217.478 - * whose signature does not include the {@code ObjectName} of an
217.479 - * MBean class loader to use for loading the MBean class.
217.480 - *
217.481 - * @return An <CODE>ObjectInstance</CODE>, containing the
217.482 - * <CODE>ObjectName</CODE> and the Java class name of the newly
217.483 - * instantiated MBean. If the contained <code>ObjectName</code>
217.484 - * is <code>n</code>, the contained Java class name is
217.485 - * <code>{@link javax.management.MBeanServer#getMBeanInfo
217.486 - * getMBeanInfo(n)}.getClassName()</code>.
217.487 - *
217.488 - * @exception ReflectionException Wraps a
217.489 - * <CODE>java.lang.ClassNotFoundException</CODE> or a
217.490 - * <CODE>java.lang.Exception</CODE> that occurred when trying to
217.491 - * invoke the MBean's constructor.
217.492 - * @exception InstanceAlreadyExistsException The MBean is already
217.493 - * under the control of the MBean server.
217.494 - * @exception MBeanRegistrationException The
217.495 - * <CODE>preRegister</CODE> (<CODE>MBeanRegistration</CODE>
217.496 - * interface) method of the MBean has thrown an exception. The
217.497 - * MBean will not be registered.
217.498 - * @exception RuntimeMBeanException If the MBean's constructor or its
217.499 - * {@code preRegister} or {@code postRegister} method threw
217.500 - * a {@code RuntimeException}. If the <CODE>postRegister</CODE>
217.501 - * (<CODE>MBeanRegistration</CODE> interface) method of the MBean throws a
217.502 - * <CODE>RuntimeException</CODE>, the <CODE>createMBean</CODE> method will
217.503 - * throw a <CODE>RuntimeMBeanException</CODE>, although the MBean creation
217.504 - * and registration succeeded. In such a case, the MBean will be actually
217.505 - * registered even though the <CODE>createMBean</CODE> method
217.506 - * threw an exception. Note that <CODE>RuntimeMBeanException</CODE> can
217.507 - * also be thrown by <CODE>preRegister</CODE>, in which case the MBean
217.508 - * will not be registered.
217.509 - * @exception MBeanException The constructor of the MBean has
217.510 - * thrown an exception
217.511 - * @exception NotCompliantMBeanException This class is not a JMX
217.512 - * compliant MBean
217.513 - * @exception InstanceNotFoundException The specified class loader
217.514 - * is not registered in the MBean server.
217.515 - * @exception RuntimeOperationsException Wraps either:
217.516 - * <ul>
217.517 - * <li>a <CODE>java.lang.IllegalArgumentException</CODE>: The className
217.518 - * passed in parameter is null, the <CODE>ObjectName</CODE> passed in
217.519 - * parameter contains a pattern or no <CODE>ObjectName</CODE> is specified
217.520 - * for the MBean; or</li>
217.521 - * <li>an {@code UnsupportedOperationException} if creating MBeans is not
217.522 - * supported by this {@code MBeanServer} implementation.
217.523 - * </ul>
217.524 - */
217.525 - public ObjectInstance createMBean(String className,
217.526 - ObjectName name, ObjectName loaderName, Object[] params,
217.527 - String[] signature, boolean useCLR)
217.528 - throws ReflectionException, InstanceAlreadyExistsException,
217.529 - MBeanRegistrationException, MBeanException,
217.530 - NotCompliantMBeanException, InstanceNotFoundException {
217.531 - throw newUnsupportedException("createMBean");
217.532 - }
217.533 -
217.534 -
217.535 - /**
217.536 - * <p>Attempts to determine whether the named MBean should be
217.537 - * considered as an instance of a given class. The default implementation
217.538 - * of this method calls {@link #getDynamicMBeanFor getDynamicMBeanFor(name)}
217.539 - * to get an MBean object. Then its behaviour is the same as the standard
217.540 - * {@link MBeanServer#isInstanceOf MBeanServer.isInstanceOf} method.</p>
217.541 - *
217.542 - * {@inheritDoc}
217.543 - */
217.544 - public boolean isInstanceOf(ObjectName name, String className)
217.545 - throws InstanceNotFoundException {
217.546 -
217.547 - final DynamicMBean instance = nonNullMBeanFor(name);
217.548 -
217.549 - try {
217.550 - final String mbeanClassName = instance.getMBeanInfo().getClassName();
217.551 -
217.552 - if (mbeanClassName.equals(className))
217.553 - return true;
217.554 -
217.555 - final Object resource;
217.556 - final ClassLoader cl;
217.557 - if (instance instanceof DynamicWrapperMBean) {
217.558 - DynamicWrapperMBean d = (DynamicWrapperMBean) instance;
217.559 - resource = d.getWrappedObject();
217.560 - cl = d.getWrappedClassLoader();
217.561 - } else {
217.562 - resource = instance;
217.563 - cl = instance.getClass().getClassLoader();
217.564 - }
217.565 -
217.566 - final Class<?> classNameClass = Class.forName(className, false, cl);
217.567 -
217.568 - if (classNameClass.isInstance(resource))
217.569 - return true;
217.570 -
217.571 - if (classNameClass == NotificationBroadcaster.class ||
217.572 - classNameClass == NotificationEmitter.class) {
217.573 - try {
217.574 - getNotificationEmitterFor(name);
217.575 - return true;
217.576 - } catch (Exception x) {
217.577 - LOG.finest("MBean " + name +
217.578 - " is not a notification emitter. Ignoring: "+x);
217.579 - return false;
217.580 - }
217.581 - }
217.582 -
217.583 - final Class<?> resourceClass = Class.forName(mbeanClassName, false, cl);
217.584 - return classNameClass.isAssignableFrom(resourceClass);
217.585 - } catch (Exception x) {
217.586 - /* Could be SecurityException or ClassNotFoundException */
217.587 - LOG.logp(Level.FINEST,
217.588 - MBeanServerSupport.class.getName(),
217.589 - "isInstanceOf", "Exception calling isInstanceOf", x);
217.590 - return false;
217.591 - }
217.592 - }
217.593 -
217.594 - /**
217.595 - * {@inheritDoc}
217.596 - *
217.597 - * <p>The default implementation of this method returns the string
217.598 - * "DefaultDomain".</p>
217.599 - */
217.600 - public String getDefaultDomain() {
217.601 - return "DefaultDomain";
217.602 - }
217.603 -
217.604 - /**
217.605 - * {@inheritDoc}
217.606 - *
217.607 - * <p>The default implementation of this method returns
217.608 - * {@link #getNames()}.size().</p>
217.609 - */
217.610 - public Integer getMBeanCount() {
217.611 - return getNames().size();
217.612 - }
217.613 -
217.614 - /**
217.615 - * {@inheritDoc}
217.616 - *
217.617 - * <p>The default implementation of this method first calls {@link #getNames
217.618 - * getNames()} to get a list of all MBean names,
217.619 - * and from this set of names, derives the set of domains which contain
217.620 - * MBeans.</p>
217.621 - */
217.622 - public String[] getDomains() {
217.623 - final Set<ObjectName> names = getNames();
217.624 - final Set<String> res = new TreeSet<String>();
217.625 - for (ObjectName n : names) {
217.626 - if (n == null) continue; // not allowed but you never know.
217.627 - res.add(n.getDomain());
217.628 - }
217.629 - return res.toArray(new String[res.size()]);
217.630 - }
217.631 -
217.632 -
217.633 - /**
217.634 - * {@inheritDoc}
217.635 - *
217.636 - * <p>The default implementation of this method will first
217.637 - * call {@link
217.638 - * #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a handle
217.639 - * to the named MBean,
217.640 - * and then call {@link DynamicMBean#getAttribute getAttribute}
217.641 - * on that {@link DynamicMBean} handle.</p>
217.642 - *
217.643 - * @throws RuntimeOperationsException {@inheritDoc}
217.644 - */
217.645 - public Object getAttribute(ObjectName name, String attribute)
217.646 - throws MBeanException, AttributeNotFoundException,
217.647 - InstanceNotFoundException, ReflectionException {
217.648 - final DynamicMBean mbean = nonNullMBeanFor(name);
217.649 - return mbean.getAttribute(attribute);
217.650 - }
217.651 -
217.652 - /**
217.653 - * {@inheritDoc}
217.654 - *
217.655 - * <p>The default implementation of this method will first
217.656 - * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)}
217.657 - * to obtain a handle to the named MBean,
217.658 - * and then call {@link DynamicMBean#setAttribute setAttribute}
217.659 - * on that {@link DynamicMBean} handle.</p>
217.660 - *
217.661 - * @throws RuntimeOperationsException {@inheritDoc}
217.662 - */
217.663 - public void setAttribute(ObjectName name, Attribute attribute)
217.664 - throws InstanceNotFoundException, AttributeNotFoundException,
217.665 - InvalidAttributeValueException, MBeanException,
217.666 - ReflectionException {
217.667 - final DynamicMBean mbean = nonNullMBeanFor(name);
217.668 - mbean.setAttribute(attribute);
217.669 - }
217.670 -
217.671 - /**
217.672 - * {@inheritDoc}
217.673 - *
217.674 - * <p>The default implementation of this method will first
217.675 - * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a
217.676 - * handle to the named MBean,
217.677 - * and then call {@link DynamicMBean#getAttributes getAttributes}
217.678 - * on that {@link DynamicMBean} handle.</p>
217.679 - *
217.680 - * @throws RuntimeOperationsException {@inheritDoc}
217.681 - */
217.682 - public AttributeList getAttributes(ObjectName name,
217.683 - String[] attributes) throws InstanceNotFoundException,
217.684 - ReflectionException {
217.685 - final DynamicMBean mbean = nonNullMBeanFor(name);
217.686 - return mbean.getAttributes(attributes);
217.687 - }
217.688 -
217.689 - /**
217.690 - * {@inheritDoc}
217.691 - *
217.692 - * <p>The default implementation of this method will first
217.693 - * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a
217.694 - * handle to the named MBean,
217.695 - * and then call {@link DynamicMBean#setAttributes setAttributes}
217.696 - * on that {@link DynamicMBean} handle.</p>
217.697 - *
217.698 - * @throws RuntimeOperationsException {@inheritDoc}
217.699 - */
217.700 - public AttributeList setAttributes(ObjectName name, AttributeList attributes)
217.701 - throws InstanceNotFoundException, ReflectionException {
217.702 - final DynamicMBean mbean = nonNullMBeanFor(name);
217.703 - return mbean.setAttributes(attributes);
217.704 - }
217.705 -
217.706 - /**
217.707 - * {@inheritDoc}
217.708 - *
217.709 - * <p>The default implementation of this method will first
217.710 - * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a
217.711 - * handle to the named MBean,
217.712 - * and then call {@link DynamicMBean#invoke invoke}
217.713 - * on that {@link DynamicMBean} handle.</p>
217.714 - */
217.715 - public Object invoke(ObjectName name, String operationName,
217.716 - Object[] params, String[] signature)
217.717 - throws InstanceNotFoundException, MBeanException,
217.718 - ReflectionException {
217.719 - final DynamicMBean mbean = nonNullMBeanFor(name);
217.720 - return mbean.invoke(operationName, params, signature);
217.721 - }
217.722 -
217.723 - /**
217.724 - * {@inheritDoc}
217.725 - *
217.726 - * <p>The default implementation of this method will first
217.727 - * call {@link #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a
217.728 - * handle to the named MBean,
217.729 - * and then call {@link DynamicMBean#getMBeanInfo getMBeanInfo}
217.730 - * on that {@link DynamicMBean} handle.</p>
217.731 - */
217.732 - public MBeanInfo getMBeanInfo(ObjectName name)
217.733 - throws InstanceNotFoundException, IntrospectionException,
217.734 - ReflectionException {
217.735 - final DynamicMBean mbean = nonNullMBeanFor(name);
217.736 - return mbean.getMBeanInfo();
217.737 - }
217.738 -
217.739 - /**
217.740 - * {@inheritDoc}
217.741 - *
217.742 - * <p>The default implementation of this method will call
217.743 - * {@link #getDynamicMBeanFor getDynamicMBeanFor(name)}.<!--
217.744 - * -->{@link DynamicMBean#getMBeanInfo getMBeanInfo()}.<!--
217.745 - * -->{@link MBeanInfo#getClassName getClassName()} to get the
217.746 - * class name to combine with {@code name} to produce a new
217.747 - * {@code ObjectInstance}.</p>
217.748 - */
217.749 - public ObjectInstance getObjectInstance(ObjectName name)
217.750 - throws InstanceNotFoundException {
217.751 - final DynamicMBean mbean = nonNullMBeanFor(name);
217.752 - final String className = mbean.getMBeanInfo().getClassName();
217.753 - return new ObjectInstance(name, className);
217.754 - }
217.755 -
217.756 - /**
217.757 - * {@inheritDoc}
217.758 - *
217.759 - * <p>The default implementation of this method will first call {@link
217.760 - * #getDynamicMBeanFor getDynamicMBeanFor(name)} to obtain a handle to the
217.761 - * named MBean. If {@code getDynamicMBeanFor} returns an object, {@code
217.762 - * isRegistered} will return true. If {@code getDynamicMBeanFor} returns
217.763 - * null or throws {@link InstanceNotFoundException}, {@code isRegistered}
217.764 - * will return false.</p>
217.765 - *
217.766 - * @throws RuntimeOperationsException {@inheritDoc}
217.767 - */
217.768 - public boolean isRegistered(ObjectName name) {
217.769 - try {
217.770 - final DynamicMBean mbean = getDynamicMBeanFor(name);
217.771 - return mbean!=null;
217.772 - } catch (InstanceNotFoundException x) {
217.773 - if (LOG.isLoggable(Level.FINEST))
217.774 - LOG.finest("MBean "+name+" is not registered: "+x);
217.775 - return false;
217.776 - }
217.777 - }
217.778 -
217.779 -
217.780 - /**
217.781 - * {@inheritDoc}
217.782 - *
217.783 - * <p>The default implementation of this method will first
217.784 - * call {@link #queryNames queryNames}
217.785 - * to get a list of all matching MBeans, and then, for each returned name,
217.786 - * call {@link #getObjectInstance getObjectInstance(name)}.</p>
217.787 - */
217.788 - public Set<ObjectInstance> queryMBeans(ObjectName pattern, QueryExp query) {
217.789 - final Set<ObjectName> names = queryNames(pattern, query);
217.790 - if (names.isEmpty()) return Collections.emptySet();
217.791 - final Set<ObjectInstance> mbeans = new HashSet<ObjectInstance>();
217.792 - for (ObjectName name : names) {
217.793 - try {
217.794 - mbeans.add(getObjectInstance(name));
217.795 - } catch (SecurityException x) { // DLS: OK
217.796 - continue;
217.797 - } catch (InstanceNotFoundException x) { // DLS: OK
217.798 - continue;
217.799 - }
217.800 - }
217.801 - return mbeans;
217.802 - }
217.803 -
217.804 - /**
217.805 - * {@inheritDoc}
217.806 - *
217.807 - * <p>The default implementation of this method calls {@link #getMatchingNames
217.808 - * getMatchingNames(pattern)} to obtain a list of MBeans matching
217.809 - * the given name pattern. If the {@code query} parameter is null,
217.810 - * this will be the result. Otherwise, it will evaluate the
217.811 - * {@code query} parameter for each of the returned names, exactly
217.812 - * as an {@code MBeanServer} would. This might result in
217.813 - * {@link #getDynamicMBeanFor getDynamicMBeanFor} being called
217.814 - * several times for each returned name.</p>
217.815 - */
217.816 - public Set<ObjectName> queryNames(ObjectName pattern, QueryExp query) {
217.817 - try {
217.818 - final Set<ObjectName> res = getMatchingNames(pattern);
217.819 - return filterListOfObjectNames(res, query);
217.820 - } catch (Exception x) {
217.821 - LOG.fine("Unexpected exception raised in queryNames: "+x);
217.822 - LOG.log(Level.FINEST, "Unexpected exception raised in queryNames", x);
217.823 - }
217.824 - // We reach here only when an exception was raised.
217.825 - //
217.826 - return Collections.emptySet();
217.827 - }
217.828 -
217.829 - private final static boolean apply(final QueryExp query,
217.830 - final ObjectName on,
217.831 - final MBeanServer srv) {
217.832 - boolean res = false;
217.833 - MBeanServer oldServer = QueryEval.getMBeanServer();
217.834 - query.setMBeanServer(srv);
217.835 - try {
217.836 - res = query.apply(on);
217.837 - } catch (Exception e) {
217.838 - LOG.finest("QueryExp.apply threw exception, returning false." +
217.839 - " Cause: "+e);
217.840 - res = false;
217.841 - } finally {
217.842 - /*
217.843 - * query.setMBeanServer is probably
217.844 - * QueryEval.setMBeanServer so put back the old
217.845 - * value. Since that method uses a ThreadLocal
217.846 - * variable, this code is only needed for the
217.847 - * unusual case where the user creates a custom
217.848 - * QueryExp that calls a nested query on another
217.849 - * MBeanServer.
217.850 - */
217.851 - query.setMBeanServer(oldServer);
217.852 - }
217.853 - return res;
217.854 - }
217.855 -
217.856 - /**
217.857 - * Filters a {@code Set<ObjectName>} according to a pattern and a query.
217.858 - * This might be quite inefficient for virtual name spaces.
217.859 - */
217.860 - Set<ObjectName>
217.861 - filterListOfObjectNames(Set<ObjectName> list,
217.862 - QueryExp query) {
217.863 - if (list.isEmpty() || query == null)
217.864 - return list;
217.865 -
217.866 - // create a new result set
217.867 - final Set<ObjectName> result = new HashSet<ObjectName>();
217.868 -
217.869 - for (ObjectName on : list) {
217.870 - // if on doesn't match query exclude it.
217.871 - if (apply(query, on, this))
217.872 - result.add(on);
217.873 - }
217.874 - return result;
217.875 - }
217.876 -
217.877 -
217.878 - // Don't use {@inheritDoc}, because we don't want to say that the
217.879 - // MBeanServer replaces a reference to the MBean by its ObjectName.
217.880 - /**
217.881 - * <p>Adds a listener to a registered MBean. A notification emitted by
217.882 - * the MBean will be forwarded to the listener.</p>
217.883 - *
217.884 - * <p>This implementation calls
217.885 - * {@link #getNotificationEmitterFor getNotificationEmitterFor}
217.886 - * and invokes {@code addNotificationListener} on the
217.887 - * {@link NotificationEmitter} it returns.
217.888 - *
217.889 - * @see #getDynamicMBeanFor getDynamicMBeanFor
217.890 - * @see #getNotificationEmitterFor getNotificationEmitterFor
217.891 - */
217.892 - public void addNotificationListener(ObjectName name,
217.893 - NotificationListener listener, NotificationFilter filter,
217.894 - Object handback) throws InstanceNotFoundException {
217.895 - final NotificationEmitter emitter =
217.896 - getNonNullNotificationEmitterFor(name);
217.897 - emitter.addNotificationListener(listener, filter, handback);
217.898 - }
217.899 -
217.900 - /**
217.901 - * {@inheritDoc}
217.902 - *
217.903 - * <p>This implementation calls
217.904 - * {@link #getNotificationEmitterFor getNotificationEmitterFor}
217.905 - * and invokes {@code removeNotificationListener} on the
217.906 - * {@link NotificationEmitter} it returns.
217.907 - * @see #getDynamicMBeanFor getDynamicMBeanFor
217.908 - * @see #getNotificationEmitterFor getNotificationEmitterFor
217.909 - */
217.910 - public void removeNotificationListener(ObjectName name,
217.911 - NotificationListener listener)
217.912 - throws InstanceNotFoundException, ListenerNotFoundException {
217.913 - final NotificationEmitter emitter =
217.914 - getNonNullNotificationEmitterFor(name);
217.915 - emitter.removeNotificationListener(listener);
217.916 - }
217.917 -
217.918 - /**
217.919 - * {@inheritDoc}
217.920 - *
217.921 - * <p>This implementation calls
217.922 - * {@link #getNotificationEmitterFor getNotificationEmitterFor}
217.923 - * and invokes {@code removeNotificationListener} on the
217.924 - * {@link NotificationEmitter} it returns.
217.925 - * @see #getDynamicMBeanFor getDynamicMBeanFor
217.926 - * @see #getNotificationEmitterFor getNotificationEmitterFor
217.927 - */
217.928 - public void removeNotificationListener(ObjectName name,
217.929 - NotificationListener listener, NotificationFilter filter,
217.930 - Object handback)
217.931 - throws InstanceNotFoundException, ListenerNotFoundException {
217.932 - NotificationEmitter emitter =
217.933 - getNonNullNotificationEmitterFor(name);
217.934 - emitter.removeNotificationListener(listener);
217.935 - }
217.936 -
217.937 -
217.938 - /**
217.939 - * <p>Adds a listener to a registered MBean.</p>
217.940 - *
217.941 - * <p>The default implementation of this method first calls
217.942 - * {@link #getDynamicMBeanFor getDynamicMBeanFor(listenerName)}.
217.943 - * If that successfully returns an object, call it {@code
217.944 - * mbean}, then (a) if {@code mbean} is an instance of {@link
217.945 - * NotificationListener} then this method calls {@link
217.946 - * #addNotificationListener(ObjectName, NotificationListener,
217.947 - * NotificationFilter, Object) addNotificationListener(name, mbean, filter,
217.948 - * handback)}, otherwise (b) this method throws an exception as specified
217.949 - * for this case.</p>
217.950 - *
217.951 - * <p>This default implementation is not appropriate for Virtual MBeans,
217.952 - * although that only matters if the object returned by {@code
217.953 - * getDynamicMBeanFor} can be an instance of
217.954 - * {@code NotificationListener}.</p>
217.955 - *
217.956 - * @throws RuntimeOperationsException {@inheritDoc}
217.957 - */
217.958 - public void addNotificationListener(ObjectName name, ObjectName listenerName,
217.959 - NotificationFilter filter, Object handback)
217.960 - throws InstanceNotFoundException {
217.961 - NotificationListener listener = getListenerMBean(listenerName);
217.962 - addNotificationListener(name, listener, filter, handback);
217.963 - }
217.964 -
217.965 - /**
217.966 - * {@inheritDoc}
217.967 - *
217.968 - * <p>This operation is not supported in this base class implementation.
217.969 - * The default implementation of this method always throws
217.970 - * {@link RuntimeOperationsException} wrapping
217.971 - * {@link UnsupportedOperationException}.</p>
217.972 - *
217.973 - * @throws javax.management.RuntimeOperationsException wrapping
217.974 - * {@link UnsupportedOperationException}
217.975 - */
217.976 - public void removeNotificationListener(ObjectName name,
217.977 - ObjectName listenerName)
217.978 - throws InstanceNotFoundException, ListenerNotFoundException {
217.979 - NotificationListener listener = getListenerMBean(listenerName);
217.980 - removeNotificationListener(name, listener);
217.981 - }
217.982 -
217.983 - /**
217.984 - * {@inheritDoc}
217.985 - *
217.986 - * <p>This operation is not supported in this base class implementation.
217.987 - * The default implementation of this method always throws
217.988 - * {@link RuntimeOperationsException} wrapping
217.989 - * {@link UnsupportedOperationException}.</p>
217.990 - *
217.991 - * @throws javax.management.RuntimeOperationsException wrapping
217.992 - * {@link UnsupportedOperationException}
217.993 - */
217.994 - public void removeNotificationListener(ObjectName name,
217.995 - ObjectName listenerName, NotificationFilter filter,
217.996 - Object handback)
217.997 - throws InstanceNotFoundException, ListenerNotFoundException {
217.998 - NotificationListener listener = getListenerMBean(listenerName);
217.999 - removeNotificationListener(name, listener, filter, handback);
217.1000 - }
217.1001 -
217.1002 - private NotificationListener getListenerMBean(ObjectName listenerName)
217.1003 - throws InstanceNotFoundException {
217.1004 - Object mbean = getDynamicMBeanFor(listenerName);
217.1005 - if (mbean instanceof NotificationListener)
217.1006 - return (NotificationListener) mbean;
217.1007 - else {
217.1008 - throw newIllegalArgumentException(
217.1009 - "MBean is not a NotificationListener: " + listenerName);
217.1010 - }
217.1011 - }
217.1012 -
217.1013 -
217.1014 - /**
217.1015 - * {@inheritDoc}
217.1016 - *
217.1017 - * <p>This operation is not supported in this base class implementation.
217.1018 - * The default implementation of this method always throws
217.1019 - * {@link InstanceNotFoundException} wrapping
217.1020 - * {@link UnsupportedOperationException}.</p>
217.1021 - *
217.1022 - * @return the default implementation of this method never returns.
217.1023 - * @throws javax.management.RuntimeOperationsException wrapping
217.1024 - * {@link UnsupportedOperationException}
217.1025 - */
217.1026 - public ClassLoader getClassLoader(ObjectName loaderName)
217.1027 - throws InstanceNotFoundException {
217.1028 - final UnsupportedOperationException failed =
217.1029 - new UnsupportedOperationException("getClassLoader");
217.1030 - final InstanceNotFoundException x =
217.1031 - new InstanceNotFoundException(String.valueOf(loaderName));
217.1032 - x.initCause(failed);
217.1033 - throw x;
217.1034 - }
217.1035 -
217.1036 - /**
217.1037 - * {@inheritDoc}
217.1038 - *
217.1039 - * <p>The default implementation of this method calls
217.1040 - * {@link #getDynamicMBeanFor getDynamicMBeanFor(mbeanName)} and applies
217.1041 - * the logic just described to the result.</p>
217.1042 - */
217.1043 - public ClassLoader getClassLoaderFor(ObjectName mbeanName)
217.1044 - throws InstanceNotFoundException {
217.1045 - final DynamicMBean mbean = nonNullMBeanFor(mbeanName);
217.1046 - if (mbean instanceof DynamicWrapperMBean)
217.1047 - return ((DynamicWrapperMBean) mbean).getWrappedClassLoader();
217.1048 - else
217.1049 - return mbean.getClass().getClassLoader();
217.1050 - }
217.1051 -
217.1052 - /**
217.1053 - * {@inheritDoc}
217.1054 - *
217.1055 - * <p>The default implementation of this method returns a
217.1056 - * {@link ClassLoaderRepository} containing exactly one loader,
217.1057 - * the {@linkplain Thread#getContextClassLoader() context class loader}
217.1058 - * for the current thread.
217.1059 - * Subclasses can override this method to return a different
217.1060 - * {@code ClassLoaderRepository}.</p>
217.1061 - */
217.1062 - public ClassLoaderRepository getClassLoaderRepository() {
217.1063 - // We return a new ClassLoaderRepository each time this
217.1064 - // method is called. This is by design, because the
217.1065 - // SingletonClassLoaderRepository is a very small object and
217.1066 - // getClassLoaderRepository() will not be called very often
217.1067 - // (the connector server calls it once) - in the context of
217.1068 - // MBeanServerSupport there's a very good chance that this method will
217.1069 - // *never* be called.
217.1070 - ClassLoader ccl = Thread.currentThread().getContextClassLoader();
217.1071 - return Util.getSingleClassLoaderRepository(ccl);
217.1072 - }
217.1073 -
217.1074 -
217.1075 - /**
217.1076 - * {@inheritDoc}
217.1077 - *
217.1078 - * <p>This operation is not supported in this base class implementation.
217.1079 - * The default implementation of this method always throws
217.1080 - * {@link RuntimeOperationsException} wrapping
217.1081 - * {@link UnsupportedOperationException}.</p>
217.1082 - * @throws javax.management.RuntimeOperationsException wrapping
217.1083 - * {@link UnsupportedOperationException}
217.1084 - */
217.1085 - public ObjectInstance registerMBean(Object object, ObjectName name)
217.1086 - throws InstanceAlreadyExistsException, MBeanRegistrationException,
217.1087 - NotCompliantMBeanException {
217.1088 - throw newUnsupportedException("registerMBean");
217.1089 - }
217.1090 -
217.1091 - /**
217.1092 - * {@inheritDoc}
217.1093 - *
217.1094 - * <p>This operation is not supported in this base class implementation.
217.1095 - * The default implementation of this method always throws
217.1096 - * {@link RuntimeOperationsException} wrapping
217.1097 - * {@link UnsupportedOperationException}.
217.1098 - * @throws javax.management.RuntimeOperationsException wrapping
217.1099 - * {@link UnsupportedOperationException}
217.1100 - */
217.1101 - public void unregisterMBean(ObjectName name)
217.1102 - throws InstanceNotFoundException, MBeanRegistrationException {
217.1103 - throw newUnsupportedException("unregisterMBean");
217.1104 - }
217.1105 -
217.1106 - /**
217.1107 - * Calls {@link #createMBean(String, ObjectName,
217.1108 - * ObjectName, Object[], String[], boolean)
217.1109 - * createMBean(className, name, null, params, signature, true)};
217.1110 - */
217.1111 - public final ObjectInstance createMBean(String className, ObjectName name,
217.1112 - Object[] params, String[] signature)
217.1113 - throws ReflectionException, InstanceAlreadyExistsException,
217.1114 - MBeanRegistrationException, MBeanException,
217.1115 - NotCompliantMBeanException {
217.1116 - try {
217.1117 - return createMBean(className, name, null, params, signature, true);
217.1118 - } catch (InstanceNotFoundException ex) {
217.1119 - // should not happen!
217.1120 - throw new MBeanException(ex, "Unexpected exception: " + ex);
217.1121 - }
217.1122 - }
217.1123 -
217.1124 - /**
217.1125 - * Calls {@link #createMBean(String, ObjectName,
217.1126 - * ObjectName, Object[], String[], boolean)
217.1127 - * createMBean(className,name, loaderName, params, signature, false)};
217.1128 - */
217.1129 - public final ObjectInstance createMBean(String className, ObjectName name,
217.1130 - ObjectName loaderName, Object[] params, String[] signature)
217.1131 - throws ReflectionException, InstanceAlreadyExistsException,
217.1132 - MBeanRegistrationException, MBeanException,
217.1133 - NotCompliantMBeanException, InstanceNotFoundException {
217.1134 - return createMBean(className, name, loaderName, params, signature, false);
217.1135 - }
217.1136 -
217.1137 - /**
217.1138 - * Calls {@link #createMBean(String, ObjectName,
217.1139 - * ObjectName, Object[], String[], boolean)
217.1140 - * createMBean(className, name, null, null, null, true)};
217.1141 - */
217.1142 - public final ObjectInstance createMBean(String className, ObjectName name)
217.1143 - throws ReflectionException, InstanceAlreadyExistsException,
217.1144 - MBeanRegistrationException, MBeanException,
217.1145 - NotCompliantMBeanException {
217.1146 - try {
217.1147 - return createMBean(className, name, null, null, null, true);
217.1148 - } catch (InstanceNotFoundException ex) {
217.1149 - // should not happen!
217.1150 - throw new MBeanException(ex, "Unexpected exception: " + ex);
217.1151 - }
217.1152 - }
217.1153 -
217.1154 - /**
217.1155 - * Calls {@link #createMBean(String, ObjectName,
217.1156 - * ObjectName, Object[], String[], boolean)
217.1157 - * createMBean(className, name, loaderName, null, null, false)};
217.1158 - */
217.1159 - public final ObjectInstance createMBean(String className, ObjectName name,
217.1160 - ObjectName loaderName)
217.1161 - throws ReflectionException, InstanceAlreadyExistsException,
217.1162 - MBeanRegistrationException, MBeanException,
217.1163 - NotCompliantMBeanException, InstanceNotFoundException {
217.1164 - return createMBean(className, name, loaderName, null, null, false);
217.1165 - }
217.1166 -
217.1167 -
217.1168 - /**
217.1169 - * {@inheritDoc}
217.1170 - *
217.1171 - * <p>This operation is not supported in this base class implementation.
217.1172 - * The default implementation of this method always throws
217.1173 - * {@link RuntimeOperationsException} wrapping
217.1174 - * {@link UnsupportedOperationException}.</p>
217.1175 - *
217.1176 - * @throws javax.management.RuntimeOperationsException wrapping
217.1177 - * {@link UnsupportedOperationException}
217.1178 - */
217.1179 - public Object instantiate(String className)
217.1180 - throws ReflectionException, MBeanException {
217.1181 - throw new UnsupportedOperationException("Not applicable.");
217.1182 - }
217.1183 -
217.1184 - /**
217.1185 - * {@inheritDoc}
217.1186 - *
217.1187 - * <p>This operation is not supported in this base class implementation.
217.1188 - * The default implementation of this method always throws
217.1189 - * {@link RuntimeOperationsException} wrapping
217.1190 - * {@link UnsupportedOperationException}.</p>
217.1191 - *
217.1192 - * @throws javax.management.RuntimeOperationsException wrapping
217.1193 - * {@link UnsupportedOperationException}
217.1194 - */
217.1195 - public Object instantiate(String className, ObjectName loaderName)
217.1196 - throws ReflectionException, MBeanException,
217.1197 - InstanceNotFoundException {
217.1198 - throw new UnsupportedOperationException("Not applicable.");
217.1199 - }
217.1200 -
217.1201 - /**
217.1202 - * {@inheritDoc}
217.1203 - *
217.1204 - * <p>This operation is not supported in this base class implementation.
217.1205 - * The default implementation of this method always throws
217.1206 - * {@link RuntimeOperationsException} wrapping
217.1207 - * {@link UnsupportedOperationException}.</p>
217.1208 - *
217.1209 - * @throws javax.management.RuntimeOperationsException wrapping
217.1210 - * {@link UnsupportedOperationException}
217.1211 - */
217.1212 - public Object instantiate(String className, Object[] params,
217.1213 - String[] signature) throws ReflectionException, MBeanException {
217.1214 - throw new UnsupportedOperationException("Not applicable.");
217.1215 - }
217.1216 -
217.1217 - /**
217.1218 - * {@inheritDoc}
217.1219 - *
217.1220 - * <p>This operation is not supported in this base class implementation.
217.1221 - * The default implementation of this method always throws
217.1222 - * {@link RuntimeOperationsException} wrapping
217.1223 - * {@link UnsupportedOperationException}.</p>
217.1224 - *
217.1225 - * @throws javax.management.RuntimeOperationsException wrapping
217.1226 - * {@link UnsupportedOperationException}
217.1227 - */
217.1228 - public Object instantiate(String className, ObjectName loaderName,
217.1229 - Object[] params, String[] signature)
217.1230 - throws ReflectionException, MBeanException,
217.1231 - InstanceNotFoundException {
217.1232 - throw new UnsupportedOperationException("Not applicable.");
217.1233 - }
217.1234 -
217.1235 -
217.1236 - /**
217.1237 - * {@inheritDoc}
217.1238 - *
217.1239 - * <p>This operation is not supported in this base class implementation.
217.1240 - * The default implementation of this method always throws
217.1241 - * {@link RuntimeOperationsException} wrapping
217.1242 - * {@link UnsupportedOperationException}.</p>
217.1243 - *
217.1244 - * @throws javax.management.RuntimeOperationsException wrapping
217.1245 - * {@link UnsupportedOperationException}
217.1246 - */
217.1247 - @Deprecated
217.1248 - public ObjectInputStream deserialize(ObjectName name, byte[] data)
217.1249 - throws InstanceNotFoundException, OperationsException {
217.1250 - throw new UnsupportedOperationException("Not applicable.");
217.1251 - }
217.1252 -
217.1253 - /**
217.1254 - * {@inheritDoc}
217.1255 - *
217.1256 - * <p>This operation is not supported in this base class implementation.
217.1257 - * The default implementation of this method always throws
217.1258 - * {@link RuntimeOperationsException} wrapping
217.1259 - * {@link UnsupportedOperationException}.</p>
217.1260 - *
217.1261 - * @throws javax.management.RuntimeOperationsException wrapping
217.1262 - * {@link UnsupportedOperationException}
217.1263 - */
217.1264 - @Deprecated
217.1265 - public ObjectInputStream deserialize(String className, byte[] data)
217.1266 - throws OperationsException, ReflectionException {
217.1267 - throw new UnsupportedOperationException("Not applicable.");
217.1268 - }
217.1269 -
217.1270 - /**
217.1271 - * {@inheritDoc}
217.1272 - *
217.1273 - * <p>This operation is not supported in this base class implementation.
217.1274 - * The default implementation of this method always throws
217.1275 - * {@link RuntimeOperationsException} wrapping
217.1276 - * {@link UnsupportedOperationException}.</p>
217.1277 - *
217.1278 - * @throws javax.management.RuntimeOperationsException wrapping
217.1279 - * {@link UnsupportedOperationException}
217.1280 - */
217.1281 - @Deprecated
217.1282 - public ObjectInputStream deserialize(String className,
217.1283 - ObjectName loaderName, byte[] data)
217.1284 - throws InstanceNotFoundException, OperationsException,
217.1285 - ReflectionException {
217.1286 - throw new UnsupportedOperationException("Not applicable.");
217.1287 - }
217.1288 -
217.1289 -
217.1290 - // Calls getDynamicMBeanFor, and throws an InstanceNotFoundException
217.1291 - // if the returned mbean is null.
217.1292 - // The DynamicMBean returned by this method is thus guaranteed to be
217.1293 - // non null.
217.1294 - //
217.1295 - private DynamicMBean nonNullMBeanFor(ObjectName name)
217.1296 - throws InstanceNotFoundException {
217.1297 - if (name == null)
217.1298 - throw newIllegalArgumentException("Null ObjectName");
217.1299 - if (name.getDomain().equals("")) {
217.1300 - String defaultDomain = getDefaultDomain();
217.1301 - try {
217.1302 - name = name.withDomain(getDefaultDomain());
217.1303 - } catch (Exception e) {
217.1304 - throw newIllegalArgumentException(
217.1305 - "Illegal default domain: " + defaultDomain);
217.1306 - }
217.1307 - }
217.1308 - final DynamicMBean mbean = getDynamicMBeanFor(name);
217.1309 - if (mbean!=null) return mbean;
217.1310 - throw new InstanceNotFoundException(String.valueOf(name));
217.1311 - }
217.1312 -
217.1313 - static RuntimeException newUnsupportedException(String operation) {
217.1314 - return new RuntimeOperationsException(
217.1315 - new UnsupportedOperationException(
217.1316 - operation+": Not supported in this namespace"));
217.1317 - }
217.1318 -
217.1319 - static RuntimeException newIllegalArgumentException(String msg) {
217.1320 - return new RuntimeOperationsException(
217.1321 - new IllegalArgumentException(msg));
217.1322 - }
217.1323 -
217.1324 -}
218.1 --- a/src/share/classes/javax/management/namespace/VirtualEventManager.java Mon Nov 23 10:04:47 2009 +0000
218.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
218.3 @@ -1,378 +0,0 @@
218.4 -/*
218.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
218.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
218.7 - *
218.8 - * This code is free software; you can redistribute it and/or modify it
218.9 - * under the terms of the GNU General Public License version 2 only, as
218.10 - * published by the Free Software Foundation. Sun designates this
218.11 - * particular file as subject to the "Classpath" exception as provided
218.12 - * by Sun in the LICENSE file that accompanied this code.
218.13 - *
218.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
218.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
218.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
218.17 - * version 2 for more details (a copy is included in the LICENSE file that
218.18 - * accompanied this code).
218.19 - *
218.20 - * You should have received a copy of the GNU General Public License version
218.21 - * 2 along with this work; if not, write to the Free Software Foundation,
218.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
218.23 - *
218.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
218.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
218.26 - * have any questions.
218.27 - */
218.28 -
218.29 -package javax.management.namespace;
218.30 -
218.31 -import com.sun.jmx.remote.util.ClassLogger;
218.32 -import java.util.ArrayList;
218.33 -import java.util.HashMap;
218.34 -import java.util.Iterator;
218.35 -import java.util.List;
218.36 -import java.util.Map;
218.37 -import javax.management.InstanceNotFoundException;
218.38 -import javax.management.ListenerNotFoundException;
218.39 -import javax.management.MBeanNotificationInfo;
218.40 -import javax.management.Notification;
218.41 -import javax.management.NotificationEmitter;
218.42 -import javax.management.NotificationFilter;
218.43 -import javax.management.NotificationListener;
218.44 -import javax.management.ObjectName;
218.45 -import javax.management.event.EventConsumer;
218.46 -
218.47 -/**
218.48 - * <p>This class maintains a list of subscribers for ObjectName patterns and
218.49 - * allows a notification to be sent to all subscribers for a given ObjectName.
218.50 - * It is typically used in conjunction with {@link MBeanServerSupport}
218.51 - * to implement a namespace with Virtual MBeans that can emit notifications.
218.52 - * The {@code VirtualEventManager} keeps track of the listeners that have been
218.53 - * added to each Virtual MBean. When an event occurs that should trigger a
218.54 - * notification from a Virtual MBean, the {@link #publish publish} method can
218.55 - * be used to send it to the appropriate listeners.</p>
218.56 - * @since 1.7
218.57 - */
218.58 -public class VirtualEventManager implements EventConsumer {
218.59 - /**
218.60 - * <p>Create a new {@code VirtualEventManager}.</p>
218.61 - */
218.62 - public VirtualEventManager() {
218.63 - }
218.64 -
218.65 - public void subscribe(
218.66 - ObjectName name,
218.67 - NotificationListener listener,
218.68 - NotificationFilter filter,
218.69 - Object handback) {
218.70 -
218.71 - if (logger.traceOn())
218.72 - logger.trace("subscribe", "" + name);
218.73 -
218.74 - if (name == null)
218.75 - throw new IllegalArgumentException("Null MBean name");
218.76 -
218.77 - if (listener == null)
218.78 - throw new IllegalArgumentException("Null listener");
218.79 -
218.80 - Map<ObjectName, List<ListenerInfo>> map =
218.81 - name.isPattern() ? patternSubscriptionMap : exactSubscriptionMap;
218.82 -
218.83 - final ListenerInfo li = new ListenerInfo(listener, filter, handback);
218.84 - List<ListenerInfo> list;
218.85 -
218.86 - synchronized (map) {
218.87 - list = map.get(name);
218.88 - if (list == null) {
218.89 - list = new ArrayList<ListenerInfo>();
218.90 - map.put(name, list);
218.91 - }
218.92 - list.add(li);
218.93 - }
218.94 - }
218.95 -
218.96 - public void unsubscribe(
218.97 - ObjectName name, NotificationListener listener)
218.98 - throws ListenerNotFoundException {
218.99 -
218.100 - if (logger.traceOn())
218.101 - logger.trace("unsubscribe2", "" + name);
218.102 -
218.103 - if (name == null)
218.104 - throw new IllegalArgumentException("Null MBean name");
218.105 -
218.106 - if (listener == null)
218.107 - throw new ListenerNotFoundException();
218.108 -
218.109 - Map<ObjectName, List<ListenerInfo>> map =
218.110 - name.isPattern() ? patternSubscriptionMap : exactSubscriptionMap;
218.111 -
218.112 - final ListenerInfo li = new ListenerInfo(listener, null, null);
218.113 - List<ListenerInfo> list;
218.114 - synchronized (map) {
218.115 - list = map.get(name);
218.116 - if (list == null || !list.remove(li))
218.117 - throw new ListenerNotFoundException();
218.118 -
218.119 - if (list.isEmpty())
218.120 - map.remove(name);
218.121 - }
218.122 - }
218.123 -
218.124 - /**
218.125 - * <p>Unsubscribes a listener which is listening to an MBean or a set of
218.126 - * MBeans represented by an {@code ObjectName} pattern.</p>
218.127 - *
218.128 - * <p>The listener to be removed must have been added by the {@link
218.129 - * #subscribe subscribe} method with the given {@code name}, {@code filter},
218.130 - * and {@code handback}. If the {@code
218.131 - * name} is a pattern, then the {@code subscribe} must have used the same
218.132 - * pattern. If the same listener has been subscribed more than once to the
218.133 - * {@code name} with the same filter and handback, only one listener is
218.134 - * removed.</p>
218.135 - *
218.136 - * @param name The name of the MBean or an {@code ObjectName} pattern
218.137 - * representing a set of MBeans to which the listener was subscribed.
218.138 - * @param listener A listener that was previously subscribed to the
218.139 - * MBean(s).
218.140 - *
218.141 - * @throws ListenerNotFoundException The given {@code listener} was not
218.142 - * subscribed to the given {@code name}.
218.143 - *
218.144 - * @see #subscribe
218.145 - */
218.146 - public void unsubscribe(
218.147 - ObjectName name, NotificationListener listener,
218.148 - NotificationFilter filter, Object handback)
218.149 - throws ListenerNotFoundException {
218.150 -
218.151 - if (logger.traceOn())
218.152 - logger.trace("unsubscribe4", "" + name);
218.153 -
218.154 - if (name == null)
218.155 - throw new IllegalArgumentException("Null MBean name");
218.156 -
218.157 - if (listener == null)
218.158 - throw new ListenerNotFoundException();
218.159 -
218.160 - Map<ObjectName, List<ListenerInfo>> map =
218.161 - name.isPattern() ? patternSubscriptionMap : exactSubscriptionMap;
218.162 -
218.163 - List<ListenerInfo> list;
218.164 - synchronized (map) {
218.165 - list = map.get(name);
218.166 - boolean removed = false;
218.167 - for (Iterator<ListenerInfo> it = list.iterator(); it.hasNext(); ) {
218.168 - ListenerInfo li = it.next();
218.169 - if (li.equals(listener, filter, handback)) {
218.170 - it.remove();
218.171 - removed = true;
218.172 - break;
218.173 - }
218.174 - }
218.175 - if (!removed)
218.176 - throw new ListenerNotFoundException();
218.177 -
218.178 - if (list.isEmpty())
218.179 - map.remove(name);
218.180 - }
218.181 - }
218.182 -
218.183 - /**
218.184 - * <p>Sends a notification to the subscribers for a given MBean.</p>
218.185 - *
218.186 - * <p>For each listener subscribed with an {@code ObjectName} that either
218.187 - * is equal to {@code emitterName} or is a pattern that matches {@code
218.188 - * emitterName}, if the associated filter accepts the notification then it
218.189 - * is forwarded to the listener.</p>
218.190 - *
218.191 - * @param emitterName The name of the MBean emitting the notification.
218.192 - * @param n The notification being sent by the MBean called
218.193 - * {@code emitterName}.
218.194 - *
218.195 - * @throws IllegalArgumentException If the emitterName of the
218.196 - * notification is null or is an {@code ObjectName} pattern.
218.197 - */
218.198 - public void publish(ObjectName emitterName, Notification n) {
218.199 - if (logger.traceOn())
218.200 - logger.trace("publish", "" + emitterName);
218.201 -
218.202 - if (n == null)
218.203 - throw new IllegalArgumentException("Null notification");
218.204 -
218.205 - if (emitterName == null) {
218.206 - throw new IllegalArgumentException(
218.207 - "Null emitter name");
218.208 - } else if (emitterName.isPattern()) {
218.209 - throw new IllegalArgumentException(
218.210 - "The emitter must not be an ObjectName pattern");
218.211 - }
218.212 -
218.213 - final List<ListenerInfo> listeners = new ArrayList<ListenerInfo>();
218.214 -
218.215 - // If there are listeners for this exact name, add them.
218.216 - synchronized (exactSubscriptionMap) {
218.217 - List<ListenerInfo> exactListeners =
218.218 - exactSubscriptionMap.get(emitterName);
218.219 - if (exactListeners != null)
218.220 - listeners.addAll(exactListeners);
218.221 - }
218.222 -
218.223 - // Loop over subscription patterns, and add all listeners for each
218.224 - // one that matches the emitterName name.
218.225 - synchronized (patternSubscriptionMap) {
218.226 - for (ObjectName on : patternSubscriptionMap.keySet()) {
218.227 - if (on.apply(emitterName))
218.228 - listeners.addAll(patternSubscriptionMap.get(on));
218.229 - }
218.230 - }
218.231 -
218.232 - // Send the notification to all the listeners we found.
218.233 - sendNotif(listeners, n);
218.234 - }
218.235 -
218.236 - /**
218.237 - * <p>Returns a {@link NotificationEmitter} object which can be used to
218.238 - * subscribe or unsubscribe for notifications with the named
218.239 - * mbean. The returned object implements {@link
218.240 - * NotificationEmitter#addNotificationListener
218.241 - * addNotificationListener(listener, filter, handback)} as
218.242 - * {@link #subscribe this.subscribe(name, listener, filter, handback)}
218.243 - * and the two {@code removeNotificationListener} methods from {@link
218.244 - * NotificationEmitter} as the corresponding {@code unsubscribe} methods
218.245 - * from this class.</p>
218.246 - *
218.247 - * @param name The name of the MBean whose notifications are being
218.248 - * subscribed, or unsuscribed.
218.249 - *
218.250 - * @return A {@link NotificationEmitter}
218.251 - * that can be used to subscribe or unsubscribe for
218.252 - * notifications emitted by the named MBean, or {@code null} if
218.253 - * the MBean does not emit notifications and should not
218.254 - * be considered as a {@code NotificationBroadcaster}. This class
218.255 - * never returns null but a subclass is allowed to.
218.256 - *
218.257 - * @throws InstanceNotFoundException if {@code name} does not exist.
218.258 - * This implementation never throws {@code InstanceNotFoundException} but
218.259 - * a subclass is allowed to override this method to do so.
218.260 - */
218.261 - public NotificationEmitter
218.262 - getNotificationEmitterFor(final ObjectName name)
218.263 - throws InstanceNotFoundException {
218.264 - final NotificationEmitter emitter = new NotificationEmitter() {
218.265 - public void addNotificationListener(NotificationListener listener,
218.266 - NotificationFilter filter, Object handback)
218.267 - throws IllegalArgumentException {
218.268 - subscribe(name, listener, filter, handback);
218.269 - }
218.270 -
218.271 - public void removeNotificationListener(
218.272 - NotificationListener listener)
218.273 - throws ListenerNotFoundException {
218.274 - unsubscribe(name, listener);
218.275 - }
218.276 -
218.277 - public void removeNotificationListener(NotificationListener listener,
218.278 - NotificationFilter filter,
218.279 - Object handback)
218.280 - throws ListenerNotFoundException {
218.281 - unsubscribe(name, listener, filter, handback);
218.282 - }
218.283 -
218.284 - public MBeanNotificationInfo[] getNotificationInfo() {
218.285 - // Never called.
218.286 - return null;
218.287 - }
218.288 - };
218.289 - return emitter;
218.290 - }
218.291 -
218.292 - // ---------------------------------
218.293 - // private stuff
218.294 - // ---------------------------------
218.295 -
218.296 - private static class ListenerInfo {
218.297 - public final NotificationListener listener;
218.298 - public final NotificationFilter filter;
218.299 - public final Object handback;
218.300 -
218.301 - public ListenerInfo(NotificationListener listener,
218.302 - NotificationFilter filter,
218.303 - Object handback) {
218.304 -
218.305 - if (listener == null) {
218.306 - throw new IllegalArgumentException("Null listener.");
218.307 - }
218.308 -
218.309 - this.listener = listener;
218.310 - this.filter = filter;
218.311 - this.handback = handback;
218.312 - }
218.313 -
218.314 - /* Two ListenerInfo instances are equal if they have the same
218.315 - * NotificationListener. This means that we can use List.remove
218.316 - * to implement the two-argument removeNotificationListener.
218.317 - */
218.318 - @Override
218.319 - public boolean equals(Object o) {
218.320 - if (o == this) {
218.321 - return true;
218.322 - }
218.323 -
218.324 - if (!(o instanceof ListenerInfo)) {
218.325 - return false;
218.326 - }
218.327 -
218.328 - return listener.equals(((ListenerInfo)o).listener);
218.329 - }
218.330 -
218.331 - /* Method that compares all four fields, appropriate for the
218.332 - * four-argument removeNotificationListener.
218.333 - */
218.334 - boolean equals(
218.335 - NotificationListener listener,
218.336 - NotificationFilter filter,
218.337 - Object handback) {
218.338 - return (this.listener == listener && same(this.filter, filter)
218.339 - && same(this.handback, handback));
218.340 - }
218.341 -
218.342 - private static boolean same(Object x, Object y) {
218.343 - if (x == y)
218.344 - return true;
218.345 - if (x == null)
218.346 - return false;
218.347 - return x.equals(y);
218.348 - }
218.349 -
218.350 - @Override
218.351 - public int hashCode() {
218.352 - return listener.hashCode();
218.353 - }
218.354 - }
218.355 -
218.356 - private static void sendNotif(List<ListenerInfo> listeners, Notification n) {
218.357 - for (ListenerInfo li : listeners) {
218.358 - if (li.filter == null ||
218.359 - li.filter.isNotificationEnabled(n)) {
218.360 - try {
218.361 - li.listener.handleNotification(n, li.handback);
218.362 - } catch (Exception e) {
218.363 - logger.trace("sendNotif", "handleNotification", e);
218.364 - }
218.365 - }
218.366 - }
218.367 - }
218.368 -
218.369 - // ---------------------------------
218.370 - // private variables
218.371 - // ---------------------------------
218.372 -
218.373 - private final Map<ObjectName, List<ListenerInfo>> exactSubscriptionMap =
218.374 - new HashMap<ObjectName, List<ListenerInfo>>();
218.375 - private final Map<ObjectName, List<ListenerInfo>> patternSubscriptionMap =
218.376 - new HashMap<ObjectName, List<ListenerInfo>>();
218.377 -
218.378 - // trace issue
218.379 - private static final ClassLogger logger =
218.380 - new ClassLogger("javax.management.event", "EventManager");
218.381 -}
219.1 --- a/src/share/classes/javax/management/namespace/package-info.java Mon Nov 23 10:04:47 2009 +0000
219.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
219.3 @@ -1,629 +0,0 @@
219.4 -/*
219.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
219.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
219.7 - *
219.8 - * This code is free software; you can redistribute it and/or modify it
219.9 - * under the terms of the GNU General Public License version 2 only, as
219.10 - * published by the Free Software Foundation. Sun designates this
219.11 - * particular file as subject to the "Classpath" exception as provided
219.12 - * by Sun in the LICENSE file that accompanied this code.
219.13 - *
219.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
219.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
219.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
219.17 - * version 2 for more details (a copy is included in the LICENSE file that
219.18 - * accompanied this code).
219.19 - *
219.20 - * You should have received a copy of the GNU General Public License version
219.21 - * 2 along with this work; if not, write to the Free Software Foundation,
219.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
219.23 - *
219.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
219.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
219.26 - * have any questions.
219.27 - */
219.28 -
219.29 -/**
219.30 - * <p>The <code>javax.management.namespace</code> package makes it possible
219.31 - * to federate MBeanServers into a hierarchical name space.</p>
219.32 - *
219.33 - * <h3 id="WhatIs">What Is a Name Space?</h3>
219.34 - * <p>
219.35 - * A name space is like an {@link javax.management.MBeanServer} within
219.36 - * an {@code MBeanServer}. Just as a file system folder can contain
219.37 - * another file system folder, an {@code MBeanServer} can contain another
219.38 - * {@code MBeanServer}. Similarly, just as a remote folder on a remote
219.39 - * disk can be mounted on a parent folder on a local disk, a remote name
219.40 - * space in a remote {@code MBeanServer} can be mounted on a name
219.41 - * space in a local parent {@code MBeanServer}.
219.42 - * </p>
219.43 - * <p>
219.44 - * The <code>javax.management.namespace</code> API thus makes it possible to
219.45 - * create a hierarchy of MBean servers federated in a hierarchical name
219.46 - * space inside a single {@code MBeanServer}.
219.47 - * </p>
219.48 - * <h3 id="HowToCreate">How To Create a Name Space?</h3>
219.49 - * <p>
219.50 - * To create a name space, you only need to register a
219.51 - * {@link javax.management.namespace.JMXNamespace} MBean in
219.52 - * an MBean server. We have seen that a namespace is like
219.53 - * an {@code MBeanServer} within an {@code MBeanServer}, and
219.54 - * therefore, it is possible to create a namespace that shows the
219.55 - * content of another {@code MBeanServer}. The simplest case is
219.56 - * when that {@code MBeanServer} is another {@code MBeanServer}
219.57 - * created by the {@link javax.management.MBeanServerFactory} as
219.58 - * shown in the extract below:
219.59 - * </p>
219.60 - * <pre>
219.61 - * final MBeanServer server = ....;
219.62 - * final String namespace = "foo";
219.63 - * final ObjectName namespaceName = {@link javax.management.namespace.JMXNamespaces#getNamespaceObjectName
219.64 - * JMXNamespaces.getNamespaceObjectName(namespace)};
219.65 - * server.registerMBean(new JMXNamespace(MBeanServerFactory.newMBeanServer()),
219.66 - * namespaceName);
219.67 - * </pre>
219.68 - * <p id="NamespaceView">
219.69 - * To navigate in namespaces and view their content, the easiest way is
219.70 - * to use an instance of {@link javax.management.namespace.JMXNamespaceView}. For instance, given
219.71 - * the {@code server} above, in which we created a namespace {@code "foo"},
219.72 - * it is possible to create a {@code JMXNamespaceView} that will make it
219.73 - * possible to navigate easily in the namespaces and sub-namespaces of that
219.74 - * server:
219.75 - * </p>
219.76 - * <pre>
219.77 - * // create a namespace view for 'server'
219.78 - * final JMXNamespaceView view = new JMXNamespaceView(server);
219.79 - *
219.80 - * // list all top level namespaces in 'server'
219.81 - * System.out.println("List of namespaces: " + Arrays.toString({@link javax.management.namespace.JMXNamespaceView#list() view.list()}));
219.82 - *
219.83 - * // go down into namespace 'foo': provides a namespace view of 'foo' and its
219.84 - * // sub namespaces...
219.85 - * final JMXNamespaceView foo = {@link javax.management.namespace.JMXNamespaceView#down view.down("foo")};
219.86 - *
219.87 - * // list all MBeans contained in namespace 'foo'
219.88 - * System.out.println({@link javax.management.namespace.JMXNamespaceView#where() foo.where()} + " contains: " +
219.89 - * {@link javax.management.namespace.JMXNamespaceView#getMBeanServerConnection foo.getMBeanServerConnection()}.queryNames(null,null));
219.90 - * </pre>
219.91 - * <p>
219.92 - * It is also possible to create more complex namespaces, such as namespaces
219.93 - * that point to MBean servers located in remote JVMs.
219.94 - * </p>
219.95 - * <p>
219.96 - * For instance, to mount the MBeanServer accessible
219.97 - * at <code>service:jmx:rmi:///jndi/rmi://localhost:9000/jmxrmi</code>
219.98 - * in a name space {@code "foo"} inside the {@linkplain
219.99 - * java.lang.management.ManagementFactory#getPlatformMBeanServer platform
219.100 - * MBeanServer} you would write the following piece of code:
219.101 - * </p>
219.102 - * <pre>
219.103 - * final JMXServiceURL sourceURL =
219.104 - * new JMXServiceURL("service:jmx:rmi:///jndi/rmi://localhost:9000/jmxrmi");
219.105 - * final MBeanServer platform = ManagementFactory.getPlatformMBeanServer();
219.106 - * final Map<String,Object> options = Collections.emptyMap();
219.107 - * final JMXRemoteNamespace mbean = {@link
219.108 - * javax.management.namespace.JMXRemoteNamespace JMXRemoteNamespace}.
219.109 - * {@link javax.management.namespace.JMXRemoteNamespace#newJMXRemoteNamespace newJMXRemoteNamespace(sourceURL, options)};
219.110 - * final ObjectName name = {@link javax.management.namespace.JMXNamespaces JMXNamespaces}.{@link javax.management.namespace.JMXNamespaces#getNamespaceObjectName(String) getNamespaceObjectName("foo")};
219.111 - * final ObjectInstance ref = platform.registerMBean(mbean,name);
219.112 - * platform.invoke(ref.getObjectName(),"connect",null,null);
219.113 - * </pre>
219.114 - *
219.115 - * <h3 id="WhatLike">What Does a Name Space Look Like?</h3>
219.116 - *
219.117 - * <p>
219.118 - * We have seen that {@link javax.management.namespace.JMXNamespaceView} class
219.119 - * provides an easy way to navigate within namespaces. It is however also
219.120 - * possible to interact with namespaces directly from the top level
219.121 - * {@code MBeanServer} in which they have been created.
219.122 - * From the outside, a name space only appears as a special MBean in
219.123 - * the MBean server. There's nothing much you can do with this MBean
219.124 - * directly.
219.125 - * </p>
219.126 - * <p>
219.127 - * For instance, let's assume you have registered a {@link
219.128 - * javax.management.namespace.JMXRemoteNamespaceMBean
219.129 - * JMXRemoteNamespaceMBean} to manage the name space {@code "foo"}.
219.130 - * <br>If you query for
219.131 - * <code>platform.queryNames("*//:*",null)</code>, then you will see
219.132 - * one MBean named {@code "foo//:type=JMXNamespace"}.
219.133 - * <br>This is the {@link javax.management.namespace.JMXNamespace}
219.134 - * MBean which is in charge of handling the namespace {@code "foo"}.
219.135 - * </p>
219.136 - * <p>
219.137 - * In fact, name space handler MBeans are instances of
219.138 - * the class {@link javax.management.namespace.JMXNamespace} - or
219.139 - * instances of a subclass of that class.
219.140 - * They have a special {@link javax.management.ObjectName} defined by
219.141 - * {@link javax.management.namespace.JMXNamespaces#getNamespaceObjectName
219.142 - * JMXNamespaces.getNamespaceObjectName}.<br>
219.143 - * {@link javax.management.namespace.JMXNamespace} instances are able
219.144 - * to return an {@link
219.145 - * javax.management.namespace.JMXNamespace#getSourceServer MBeanServer}
219.146 - * which corresponds to the MBeanServer within (= the name space itself).
219.147 - * </p>
219.148 - * <p>
219.149 - * So how does it work? How can you see the MBeans contained in the new
219.150 - * name space?
219.151 - * </p>
219.152 - * <p>In order to address scalability issues, MBeans registered in
219.153 - * namespaces (such as our namespace {@code "foo"} above) can not be
219.154 - * seen with {@code mbeanServer.queryNames("*:*",null)}. To see the MBeans
219.155 - * contained in a namespace, you can use one of these methods:
219.156 - * </p>
219.157 - * <ol>
219.158 - * <li>
219.159 - * You can use the {@link javax.management.namespace.JMXNamespaceView}
219.160 - * class <a href="#NamespaceView">shown above</a>,
219.161 - * </li>
219.162 - * <li>
219.163 - * or you can <a href="#NamespacePrefix">directly look</a> for MBeans
219.164 - * whose names match
219.165 - * {@code "foo//*:*"},
219.166 - * </li>
219.167 - * <li>
219.168 - * or you can <a href="#ChangeTo">narrow down</a> to the namespace
219.169 - * and obtain an MBeanServer
219.170 - * proxy that corresponds to an MBeanServer view of that namespace.
219.171 - * The JMXNamespaces class provides a static method that
219.172 - * allows you to narrow down to a name space, by calling
219.173 - * {@link javax.management.namespace.JMXNamespaces#narrowToNamespace(MBeanServer,String)
219.174 - * JMXNamespaces.narrowToNamespace}.
219.175 - * </li>
219.176 - * </ol>
219.177 - *
219.178 - * <h3 id="NamespacePrefix">Using Name Space Prefixes</h3>
219.179 - * <p>
219.180 - * As we have explained above, MBeans contained in name
219.181 - * spaces are not returned by {@code server.queryNames(null,null)} - or
219.182 - * <code>server.queryNames({@link javax.management.ObjectName#WILDCARD ObjectName.WILDCARD},null)</code>.
219.183 - * <br>
219.184 - * However, these MBeans can still be accessed from the top level
219.185 - * {@code MBeanServer} interface, without using any API specific to the
219.186 - * version 2.0 of the JMX API, simply by using object names with
219.187 - * name space prefixes:
219.188 - * <br>To list MBeans contained in a namespace {@code "foo"} you can
219.189 - * query for MBeans whose names match {@code "foo//*:*"}, as shown
219.190 - * earlier in this document:
219.191 - * <pre>
219.192 - * server.queryNames(new ObjectName("foo//*:*", null);
219.193 - * // or equivalently:
219.194 - * server.queryNames(JMXNamespaces.getWildcardFor("foo"), null);
219.195 - * </pre>
219.196 - * This will return a list of MBean names whose domain name starts
219.197 - * with {@code foo//}.
219.198 - * </p><p>
219.199 - * Using these names, you can invoke any operation on the corresponding
219.200 - * MBeans. For instance, to get the {@link javax.management.MBeanInfo
219.201 - * MBeanInfo} of an MBean
219.202 - * contained in name space {@code "foo"} (assuming
219.203 - * the name of the MBean within its name space is <i>domain:type=Thing</i>,
219.204 - * then simply call:
219.205 - * <pre>
219.206 - * server.getMBeanInfo(new ObjectName("foo//domain:type=Thing"));
219.207 - * </pre>
219.208 - * An easier way to access MBeans contained in a name space is to
219.209 - * <i>cd</i> inside the name space, as shown in the following paragraph.
219.210 - * </p><p id="RejectedNamespacePatterns">
219.211 - * Although ObjectName patterns where the characters
219.212 - * <code>*</code> and <code>?</code> appear in the namespace path are
219.213 - * legal, they are not valid in the {@code name} parameter of the
219.214 - * MBean Server {@link
219.215 - * javax.management.MBeanServer#queryNames queryNames} and {@link
219.216 - * javax.management.MBeanServer#queryMBeans queryMBeans} methods.<br>
219.217 - * When invoking <code>queryNames</code> or <code>queryMBeans</code>,
219.218 - * only ObjectNames of the form:<br>
219.219 - * [<em>namespace-without-pattern</em>//]*[<em>pattern-without-namespace</em>]:<em>key-properties-with-or-without-pattern</em>
219.220 - * are valid.<br>
219.221 - * In other words: in the case of {@link
219.222 - * javax.management.MBeanServer#queryNames queryNames} and {@link
219.223 - * javax.management.MBeanServer#queryMBeans queryMBeans}, if a
219.224 - * namespace path is present, it must not contain any pattern.
219.225 - * </p><p id="NamespaceAndQueries">
219.226 - * There is no such restriction for the {@code query} parameter of these
219.227 - * methods. However, it must be noted that the {@code query} parameter
219.228 - * will be evaluated in the context of the namespace where the MBeans
219.229 - * selected by the pattern specified in {@code name} are located.
219.230 - * This means that if {@code query} parameter is an ObjectName pattern that
219.231 - * contains a namespace path, no MBean name will match and the result of
219.232 - * the query will be empty.<br>
219.233 - * In other words:</p>
219.234 - * <ul><li>{@code queryNames("foo//bar//?a?:*","b?z:type=Monitor,*")} will select
219.235 - * all MBeans in namespace <em>foo//bar</em> whose names match both
219.236 - * <em>?a?:*</em> and <em>b?z:type=Monitor,*</em>, but</li>
219.237 - * <li>{@code queryNames("foo//bar//?a?:*","foo//bar//b?z:type=Monitor,*")}
219.238 - * will select nothing because no name matching <em>?a?:*</em> will
219.239 - * also match <em>foo//bar//b?z:type=Monitor,*</em>.
219.240 - * </li>
219.241 - * </ul>
219.242 - *
219.243 - * <h3 id="ChangeTo">Narrowing Down Into a Name Spaces</h3>
219.244 - * <p>
219.245 - * As we have seen, name spaces are like MBean servers within MBean servers.
219.246 - * Therefore, it is possible to view a name space just as if it were
219.247 - * an other MBean server. This is similar to opening a sub
219.248 - * folder from a parent folder.<br>
219.249 - * This operation is illustrated in the code extract below:
219.250 - * <pre>
219.251 - * final MBeanServer foo =
219.252 - * JMXNamespaces.narrowToNamespace(platform, "foo");
219.253 - * final MBeanInfo info =
219.254 - * foo.getMBeanInfo(new ObjectName("domain:type=Thing"));
219.255 - * </pre>
219.256 - * The {@code MBeanServer} returned by {@link
219.257 - * javax.management.namespace.JMXNamespaces#narrowToNamespace(MBeanServer,String)
219.258 - * JMXNamespaces.narrowToNamespace} is an {@code MBeanServer} view that
219.259 - * narrows down into a given namespace. The MBeans contained inside that
219.260 - * namespace can now be accessed by their regular local name. <br>
219.261 - * The MBean server obtained by narrowing down
219.262 - * to name space {@code "foo"} behaves just like a regular MBean server.
219.263 - * However, it may sometimes throw an {@link
219.264 - * java.lang.UnsupportedOperationException UnsupportedOperationException}
219.265 - * wrapped in a {@link javax.management.RuntimeOperationsException
219.266 - * RuntimeOperationsException} if you try to call an operation which is not
219.267 - * supported by the underlying name space handler.
219.268 - * <br>For instance, {@link javax.management.MBeanServer#registerMBean
219.269 - * registerMBean} is not supported for name spaces mounted from remote
219.270 - * MBean servers.
219.271 - * </p>
219.272 - * <p>
219.273 - * <u>Note:</u> If you have a deep hierarchy of namespaces, and if you
219.274 - * are switching from one namespace to another in the course of your
219.275 - * application, it might be more convenient to use a
219.276 - * {@link javax.management.namespace.JMXNamespaceView}
219.277 - * in order to navigate in your namespaces.
219.278 - * </p>
219.279 - *
219.280 - * <h3 id="NamespaceTypes">Different Types of Name Spaces</h3>
219.281 - * <p>
219.282 - * This API lets you create several types of name spaces:
219.283 - * <ul>
219.284 - * <li id="RemoteNS">
219.285 - * You can use the {@link
219.286 - * javax.management.namespace.JMXRemoteNamespace
219.287 - * JMXRemoteNamespace} to create
219.288 - * <b>remote</b> name spaces, mounted from
219.289 - * a remote sub {@code MBeanServer} source, as shown
219.290 - * <a href="#HowToCreate">earlier</a> in this document.
219.291 - * </li>
219.292 - * <li id="LocalNS">
219.293 - * You can also use {@link
219.294 - * javax.management.namespace.JMXNamespace
219.295 - * JMXNamespace} to create
219.296 - * <b>local</b> name spaces,
219.297 - * by providing a direct reference to another {@code MBeanServer}
219.298 - * instance living in the same JVM.
219.299 - * </li>
219.300 - * <li id="VirtualNS">
219.301 - * Finally, you can create
219.302 - * name spaces containing <b>virtual</b> MBeans,
219.303 - * by subclassing the {@link
219.304 - * javax.management.namespace.MBeanServerSupport
219.305 - * MBeanServerSupport}, and passing an instance of
219.306 - * your own subclass to a {@link
219.307 - * javax.management.namespace.JMXNamespace JMXNamespace}.
219.308 - * </li>
219.309 - * <li id="CustomNS">
219.310 - * If none of these classes suit your needs, you can also provide
219.311 - * <b>your own</b> subclass of {@link
219.312 - * javax.management.namespace.JMXNamespace
219.313 - * JMXNamespace}. This is however discouraged.
219.314 - * </li>
219.315 - * </ul>
219.316 - * </p>
219.317 - *
219.318 - * <h3 id="SpecialOp">Name Spaces And Special Operations</h3>
219.319 - * <p>
219.320 - * MBean Naming considerations aside, Name Spaces are transparent for
219.321 - * most {@code MBeanServer} operations. There are however a few
219.322 - * exceptions:
219.323 - * </p>
219.324 - * <ul>
219.325 - * <li>
219.326 - * <p>MBeanServer only operations - these are the operations which are
219.327 - * supported by {@link javax.management.MBeanServer MBeanServer} but
219.328 - * are not present in {@link
219.329 - * javax.management.MBeanServerConnection
219.330 - * MBeanServerConnection}. Since a name space can be a local view of
219.331 - * a remote {@code MBeanServer}, accessible only through an
219.332 - * {@code MBeanServerConnection}, these
219.333 - * kinds of operations are not always supported.</p>
219.334 - * <ul>
219.335 - * <li id="registerMBean">
219.336 - * <p>registerMBean:</p>
219.337 - * <p> The {@link javax.management.MBeanServer#registerMBean
219.338 - * registerMBean}
219.339 - * operation is not supported by most name spaces. A call
219.340 - * to
219.341 - * <pre>
219.342 - * MBeanServer server = ....;
219.343 - * ThingMBean mbean = new Thing(...);
219.344 - * ObjectName name = new ObjectName("foo//domain:type=Thing");
219.345 - * server.registerMBean(mbean, name);
219.346 - * </pre>
219.347 - * will usually fail, unless the name space
219.348 - * {@code "foo"} is a <a href="#LocalNS">local</a> name
219.349 - * space. In the case where you attempt to cross
219.350 - * multiple name spaces, then all name spaces in the
219.351 - * path must support the {@code registerMBean} operation
219.352 - * in order for it to succeed.<br>
219.353 - * To create an MBean inside a name space, it is
219.354 - * usually safer to use {@code createMBean} -
219.355 - * although some <a href="#MBeanCreation">special
219.356 - * considerations</a> can also apply.
219.357 - * </p>
219.358 - * <p></p>
219.359 - * </li>
219.360 - * <li id="getClassLoader">
219.361 - * <p>getClassLoader:</p>
219.362 - * <p> Similarly to <a href="#registerMBean">registerMBean</a>,
219.363 - * and for the same reasons, {@link
219.364 - * javax.management.MBeanServer#getClassLoader
219.365 - * getClassLoader} will usually fail, unless the
219.366 - * class loader is an MBean registered in a
219.367 - * <a href="#LocalNS">local</a> name space.<br>
219.368 - * </p>
219.369 - * </li>
219.370 - * <li id="getClassLoaderFor">
219.371 - * <p>getClassLoaderFor:</p>
219.372 - * <p> The implementation of {@link
219.373 - * javax.management.MBeanServer#getClassLoaderFor
219.374 - * getClassLoaderFor} also depends on which
219.375 - * <a href="#NamespaceTypes">type of name space</a>
219.376 - * handler is used across the namespace path.
219.377 - * </p>
219.378 - * <p>
219.379 - * A <a href="#LocalNS">local</a> name space will usually
219.380 - * be able to implement this method just as a real
219.381 - * {@code MBeanServer} would. A
219.382 - * <a href="#RemoteNS">remote</a> name space will usually
219.383 - * return the default class loader configured on the
219.384 - * internal {@link javax.management.remote.JMXConnector
219.385 - * JMXConnector} used to connect to the remote server.
219.386 - * When a {@link
219.387 - * javax.management.namespace.JMXRemoteNamespace
219.388 - * JMXRemoteNamespace} is used to connect to a
219.389 - * remote server that contains MBeans which export
219.390 - * custom types, the {@link
219.391 - * javax.management.namespace.JMXRemoteNamespace
219.392 - * JMXRemoteNamespace} must thus be configured with
219.393 - * an options map such that the underlying connector
219.394 - * can obtain a default class loader able
219.395 - * to handle those types.
219.396 - * </p>
219.397 - * <p>
219.398 - * Other <a href="#NamespaceTypes">types of name spaces</a>
219.399 - * may implement this method
219.400 - * as best as they can.
219.401 - * </p>
219.402 - * </li>
219.403 - * </ul>
219.404 - * </li>
219.405 - * <li id="MBeanCreation">
219.406 - * <p>MBean creation</p>
219.407 - * <p> MBean creation through {@link
219.408 - * javax.management.MBeanServerConnection#createMBean
219.409 - * createMBean} might not be supported by all
219.410 - * name spaces: <a href="#LocalNS">local</a> name spaces and
219.411 - * <a href="#LocalNS">remote</a> name spaces will usually
219.412 - * support it, but <a href="#VirtualNS">virtual</a> name
219.413 - * spaces and <a href="#CustomNS">custom</a> name
219.414 - * spaces might not.
219.415 - * </p>
219.416 - * <p>
219.417 - * In that case, they will throw an {@link
219.418 - * java.lang.UnsupportedOperationException
219.419 - * UnsupportedOperationException} usually wrapped into an {@link
219.420 - * javax.management.MBeanRegistrationException}.
219.421 - * </p>
219.422 - * </li>
219.423 - * <li id="Notifications">
219.424 - * <p>Notifications</p>
219.425 - * <p> Some namespaces might not support JMX Notifications. In that
219.426 - * case, a call to add or remove notification listener for an
219.427 - * MBean contained in that name space will raise a
219.428 - * {@link javax.management.RuntimeOperationsException
219.429 - * RuntimeOperationsException} wrapping an {@link
219.430 - * java.lang.UnsupportedOperationException
219.431 - * UnsupportedOperationException} exception.
219.432 - * </p>
219.433 - * </li>
219.434 - * </ul>
219.435 - *
219.436 - * <h3 id="CrossingNamespace">Crossing Several Name Spaces</h3>
219.437 - * <p>
219.438 - * Just as folders can contain other folders, name spaces can contain
219.439 - * other name spaces. For instance, if an {@code MBeanServer} <i>S1</i>
219.440 - * containing a name space {@code "bar"} is mounted in another
219.441 - * {@code MBeanServer} <i>S2</i> with name space {@code "foo"}, then
219.442 - * an MBean <i>M1</i> named {@code "domain:type=Thing"} in namespace
219.443 - * {@code "bar"} will appear as {@code "foo//bar//domain:type=Thing"} in
219.444 - * {@code MBeanServer} <i>S2</i>.
219.445 - * </p>
219.446 - * <p>
219.447 - * When accessing the MBean <i>M1</i> from server <i>S2</i>, the
219.448 - * method call will traverse in a cascade {@code MBeanServer} <i>S2</i>,
219.449 - * then the name space handler for name space {@code "foo"}, then
219.450 - * {@code MBeanServer} <i>S1</i>, before coming to the name space
219.451 - * handler for name space {@code "bar"}. Any operation invoked
219.452 - * on the MBean from a "top-level" name space will therefore need to
219.453 - * traverse all the name spaces along the name space path until
219.454 - * it eventually reaches the named MBean. This means that an operation
219.455 - * like <a href="#registerMBean">registerMBean</a> for instance,
219.456 - * can only succeed if all the name spaces along the path support it.
219.457 - * </p>
219.458 - * <p>
219.459 - * Narrowing to a nested name space works just the same as narrowing
219.460 - * to a top level name space:
219.461 - * <pre>
219.462 - * final MBeanServer S2 = .... ;
219.463 - * final MBeanServer bar =
219.464 - * JMXNamespaces.narrowToNamespace(S2, "foo//bar");
219.465 - * final MBeanInfo info =
219.466 - * foo.getMBeanInfo(new ObjectName("domain:type=Thing"));
219.467 - * </pre>
219.468 - * </p>
219.469 - *
219.470 - * <h3 id="OperationResult">Name Spaces And Operation Results</h3>
219.471 - * <p>
219.472 - * Operation results, as well as attribute values returned by an MBean
219.473 - * contained in a name space must be interpreted in the context of that
219.474 - * name space.<br>
219.475 - * In other words, if an MBean in name space "foo" has an attribute of
219.476 - * type {@code ObjectName}, then it must be assumed that the
219.477 - * {@code ObjectName} returned by that MBean is relative to
219.478 - * name space "foo".<br>
219.479 - * The same rule aplies for MBean names that can be returned by
219.480 - * operations invoked on such an MBean. If one of the MBean operations
219.481 - * return, say, a {@code Set<ObjectName>} then those MBean names must
219.482 - * also be assumed to be relative to name space "foo".<br>
219.483 - * </p>
219.484 - * <p>
219.485 - * In the usual case, a JMX client will first
219.486 - * <a href="#ChangeTo">narrow to a name space</a> before invoking
219.487 - * any operation on the MBeans it contains. In that case the names
219.488 - * returned by the MBean invoked can be directly fed back to the
219.489 - * narrowed connection.
219.490 - * <br>
219.491 - * If however, the JMX client directly invoked the MBean from a higher
219.492 - * name space, without having narrowed to that name space first, then
219.493 - * the names that might be returned by that MBean will not be directly
219.494 - * usable - the JMX client will need to either
219.495 - * <a href="#ChangeTo">narrow to the name space</a> before using the
219.496 - * returned names, or convert the names to the higher level name space
219.497 - * context.
219.498 - * <br>
219.499 - * The {@link javax.management.namespace.JMXNamespaces JMXNamespaces}
219.500 - * class provides methods that can be used to perform that conversion.
219.501 - * </p>
219.502 - *
219.503 - * <h3 id="NamespacesAndNotifications">Name Spaces And Notifications</h3>
219.504 - * <p>
219.505 - * As <a href="#WhatIs">already explained</a>, name spaces are very
219.506 - * similar to {@code MBeanServer}s. It is thus possible to get
219.507 - * {@link javax.management.MBeanServerNotification MBeanServerNotifications}
219.508 - * when MBeans are added or removed within a name space, by registering
219.509 - * with the {@link javax.management.MBeanServerDelegate
219.510 - * MBeanServerDelegate} MBean of the corresponding name space.<br>
219.511 - * However, it must be noted that the notifications emitted by a
219.512 - * name space must be interpreted in the context of that name space.
219.513 - * For instance, if an MBean {@code "domain:type=Thing"} contained in
219.514 - * namespace "foo//bar" emits a notification, the source of the
219.515 - * notification will be {@code "domain:type=Thing"}, not
219.516 - * {@code "foo//bar//domain:type=Thing"}. <br>
219.517 - * It is therefore recommended to keep track of the name space
219.518 - * information when registering a listener with an MBean contained in
219.519 - * a name space, especially if the same listener is used to receive
219.520 - * notifications from different name spaces. An easy solution is to
219.521 - * use the handback, as illustrated in the code below.
219.522 - * <pre>
219.523 - * final MBeanServer server = ...;
219.524 - * final NotificationListener listener = new NotificationListener() {
219.525 - * public void handleNotification(Notification n, Object handback) {
219.526 - * if (!(n instanceof MBeanServerNotification)) {
219.527 - * System.err.println("Error: expected MBeanServerNotification");
219.528 - * return;
219.529 - * }
219.530 - * final MBeanServerNotification mbsn =
219.531 - * (MBeanServerNotification) n;
219.532 - *
219.533 - * // We will pass the namespace path in the handback.
219.534 - * //
219.535 - * // The received notification must be interpreted in
219.536 - * // the context of its source - therefore
219.537 - * // mbsn.getMBeanName() does not include the name space
219.538 - * // path...
219.539 - * //
219.540 - * final String namespace = (String) handback;
219.541 - * System.out.println("Received " + mbsn.getType() +
219.542 - * " for MBean " + mbsn.getMBeanName() +
219.543 - * " from name space " + namespace);
219.544 - * }
219.545 - * };
219.546 - * server.addNotificationListener(JMXNamespaces.insertPath("foo//bar",
219.547 - * MBeanServerDelegate.DELEGATE_NAME),listener,null,"foo//bar");
219.548 - * server.addNotificationListener(JMXNamespaces.insertPath("foo//joe",
219.549 - * MBeanServerDelegate.DELEGATE_NAME),listener,null,"foo//joe");
219.550 - * </pre>
219.551 - * </p>
219.552 - * <p>
219.553 - * JMX Connectors may require some configuration in order to be able
219.554 - * to forward notifications from MBeans located in name spaces.
219.555 - * The RMI JMX Connector Server
219.556 - * in the Java SE 7 platform is configured by default to internally
219.557 - * use the new {@linkplain javax.management.event event service} on
219.558 - * the server side.
219.559 - * When the connector server is configured in this way, JMX clients
219.560 - * which use the old JMX Notifications mechanism (such as clients
219.561 - * running on prior versions of the JDK) will be able to
219.562 - * to receive notifications from MBeans located in sub name spaces.
219.563 - * This is because the connector server will transparently delegate
219.564 - * their subscriptions to the underlying {@linkplain
219.565 - * javax.management.event event service}. In summary:
219.566 - * <ul>
219.567 - * <li>
219.568 - * On the server side: When exporting an {@code MBeanServer}
219.569 - * through a JMX Connector, you will need to make sure that the
219.570 - * connector server uses the new {@linkplain javax.management.event
219.571 - * event service} in order to register for notifications. If the
219.572 - * connector server doesn't use the event service, only clients
219.573 - * which explicitly use the new {@linkplain javax.management.event
219.574 - * event service} will be able to register for notifications
219.575 - * with MBeans located in sub name spaces.
219.576 - * </li>
219.577 - * <li>
219.578 - * On the client side: if the JMX Connector server (on the remote
219.579 - * server side) was configured to internally use the new
219.580 - * {@linkplain javax.management.event
219.581 - * event service}, then clients can continue to use the old
219.582 - * {@code MBeanServerConnection} add / remove notification
219.583 - * listener methods transparently. Otherwise, only clients which
219.584 - * explicitly use the new {@linkplain javax.management.event
219.585 - * event service} will be able to receive notifications from
219.586 - * MBeans contained in sub name spaces.
219.587 - * </li>
219.588 - * </ul>
219.589 - * </p>
219.590 - * <p>
219.591 - * These configuration issues apply at each node in the name space path,
219.592 - * whenever the name space points to a remote server. The
219.593 - * {@link javax.management.namespace.JMXRemoteNamespace
219.594 - * JMXRemoteNamespace} can be configured in such a way that it will
219.595 - * explicitly use an {@link javax.management.event.EventClient EventClient}
219.596 - * when forwarding subscription to the remote side. Note that this can be
219.597 - * unnecessary (and a waste of resources) if the underlying JMXConnector
219.598 - * returned by the JMXConnectorFactory (client side) already uses the
219.599 - * {@linkplain javax.management.event event service} to register for
219.600 - * notifications with the server side.
219.601 - * </p>
219.602 - *
219.603 - * <h3 id="Security">Name Spaces And Access Control</h3>
219.604 - * <p>
219.605 - * Access to MBeans exposed through JMX namespaces is controlled by
219.606 - * {@linkplain javax.management.namespace.JMXNamespacePermission
219.607 - * jmx namespace permissions}. These permissions are checked by the
219.608 - * MBeanServer in which the {@link
219.609 - * javax.management.namespace.JMXNamespace JMXNamespace} MBean is registered.
219.610 - * This is <a href="JMXNamespace.html#PermissionChecks">described in
219.611 - * details</a> in the {@link
219.612 - * javax.management.namespace.JMXNamespace JMXNamespace} class.
219.613 - * </p>
219.614 - * <p>
219.615 - * To implement a "firewall-like" access control in a JMX agent you
219.616 - * can also place an {@link
219.617 - * javax.management.remote.MBeanServerForwarder} in the JMX Connector
219.618 - * Server which exposes the top-level MBeanServer of your application.
219.619 - * This {@code MBeanServerForwarder} will be able to perform
219.620 - * authorization checks for all MBeans, including those located in
219.621 - * sub name spaces.
219.622 - * </p>
219.623 - * <p>
219.624 - * For a tighter access control we recommend using a {@link
219.625 - * java.lang.SecurityManager security manager}.
219.626 - * </p>
219.627 - * @since 1.7
219.628 - * <p></p>
219.629 - **/
219.630 -
219.631 -package javax.management.namespace;
219.632 -
220.1 --- a/src/share/classes/javax/management/openmbean/CompositeDataInvocationHandler.java Mon Nov 23 10:04:47 2009 +0000
220.2 +++ b/src/share/classes/javax/management/openmbean/CompositeDataInvocationHandler.java Wed Nov 25 11:08:25 2009 -0800
220.3 @@ -26,6 +26,8 @@
220.4 package javax.management.openmbean;
220.5
220.6 import com.sun.jmx.mbeanserver.MXBeanLookup;
220.7 +import com.sun.jmx.mbeanserver.MXBeanMapping;
220.8 +import com.sun.jmx.mbeanserver.MXBeanMappingFactory;
220.9 import com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory;
220.10 import java.lang.reflect.InvocationHandler;
220.11 import java.lang.reflect.Method;
220.12 @@ -115,12 +117,7 @@
220.13 is null.
220.14 */
220.15 public CompositeDataInvocationHandler(CompositeData compositeData) {
220.16 - this(compositeData, MXBeanMappingFactory.DEFAULT);
220.17 - }
220.18 -
220.19 - public CompositeDataInvocationHandler(CompositeData compositeData,
220.20 - MXBeanMappingFactory mappingFactory) {
220.21 - this(compositeData, mappingFactory, null);
220.22 + this(compositeData, null);
220.23 }
220.24
220.25 /**
220.26 @@ -139,13 +136,11 @@
220.27 is null.
220.28 */
220.29 CompositeDataInvocationHandler(CompositeData compositeData,
220.30 - MXBeanMappingFactory mappingFactory,
220.31 MXBeanLookup lookup) {
220.32 if (compositeData == null)
220.33 throw new IllegalArgumentException("compositeData");
220.34 this.compositeData = compositeData;
220.35 this.lookup = lookup;
220.36 - this.mappingFactory = mappingFactory;
220.37 }
220.38
220.39 /**
220.40 @@ -204,7 +199,7 @@
220.41 }
220.42 }
220.43 MXBeanMapping mapping =
220.44 - mappingFactory.mappingForType(method.getGenericReturnType(),
220.45 + MXBeanMappingFactory.DEFAULT.mappingForType(method.getGenericReturnType(),
220.46 MXBeanMappingFactory.DEFAULT);
220.47 return mapping.fromOpenValue(openValue);
220.48 }
220.49 @@ -250,5 +245,4 @@
220.50
220.51 private final CompositeData compositeData;
220.52 private final MXBeanLookup lookup;
220.53 - private final MXBeanMappingFactory mappingFactory;
220.54 }
221.1 --- a/src/share/classes/javax/management/openmbean/CompositeDataSupport.java Mon Nov 23 10:04:47 2009 +0000
221.2 +++ b/src/share/classes/javax/management/openmbean/CompositeDataSupport.java Wed Nov 25 11:08:25 2009 -0800
221.3 @@ -92,16 +92,16 @@
221.4 * @param itemNames <tt>itemNames</tt> must list, in any order, all the
221.5 * item names defined in <tt>compositeType</tt>; the order in which the
221.6 * names are listed, is used to match values in <tt>itemValues[]</tt>; must
221.7 - * not be null.
221.8 + * not be null or empty.
221.9 *
221.10 * @param itemValues the values of the items, listed in the same order as
221.11 * their respective names in <tt>itemNames</tt>; each item value can be
221.12 * null, but if it is non-null it must be a valid value for the open type
221.13 * defined in <tt>compositeType</tt> for the corresponding item; must be of
221.14 - * the same size as <tt>itemNames</tt>; must not be null.
221.15 + * the same size as <tt>itemNames</tt>; must not be null or empty.
221.16 *
221.17 * @throws IllegalArgumentException <tt>compositeType</tt> is null, or
221.18 - * <tt>itemNames[]</tt> or <tt>itemValues[]</tt> is null, or one
221.19 + * <tt>itemNames[]</tt> or <tt>itemValues[]</tt> is null or empty, or one
221.20 * of the elements in <tt>itemNames[]</tt> is a null or empty string, or
221.21 * <tt>itemNames[]</tt> and <tt>itemValues[]</tt> are not of the same size.
221.22 *
221.23 @@ -124,6 +124,8 @@
221.24
221.25 if (itemNames == null || itemValues == null)
221.26 throw new IllegalArgumentException("Null itemNames or itemValues");
221.27 + if (itemNames.length == 0 || itemValues.length == 0)
221.28 + throw new IllegalArgumentException("Empty itemNames or itemValues");
221.29 if (itemNames.length != itemValues.length) {
221.30 throw new IllegalArgumentException(
221.31 "Different lengths: itemNames[" + itemNames.length +
221.32 @@ -154,10 +156,10 @@
221.33 * must not be null.
221.34 * @param items the mappings of all the item names to their values;
221.35 * <tt>items</tt> must contain all the item names defined in <tt>compositeType</tt>;
221.36 - * must not be null.
221.37 + * must not be null or empty.
221.38 *
221.39 * @throws IllegalArgumentException <tt>compositeType</tt> is null, or
221.40 - * <tt>items</tt> is null, or one of the keys in <tt>items</tt> is a null
221.41 + * <tt>items</tt> is null or empty, or one of the keys in <tt>items</tt> is a null
221.42 * or empty string.
221.43 * @throws OpenDataException <tt>items</tt>' size differs from the
221.44 * number of items defined in <tt>compositeType</tt>, or one of the
221.45 @@ -167,8 +169,6 @@
221.46 * <tt>compositeType</tt>.
221.47 * @throws ArrayStoreException one or more keys in <tt>items</tt> is not of
221.48 * the class <tt>java.lang.String</tt>.
221.49 - *
221.50 - * @see #toMap
221.51 */
221.52 public CompositeDataSupport(CompositeType compositeType,
221.53 Map<String,?> items)
221.54 @@ -177,13 +177,13 @@
221.55 }
221.56
221.57 private static SortedMap<String, Object> makeMap(Map<String, ?> items) {
221.58 - if (items == null)
221.59 - throw new IllegalArgumentException("Null items map");
221.60 - if (items.containsKey(null) || items.containsKey(""))
221.61 - throw new IllegalArgumentException("Null or empty item name");
221.62 + if (items == null || items.isEmpty())
221.63 + throw new IllegalArgumentException("Null or empty items map");
221.64
221.65 SortedMap<String, Object> map = new TreeMap<String, Object>();
221.66 for (Object key : items.keySet()) {
221.67 + if (key == null || key.equals(""))
221.68 + throw new IllegalArgumentException("Null or empty item name");
221.69 if (!(key instanceof String)) {
221.70 throw new ArrayStoreException("Item name is not string: " + key);
221.71 // This can happen because of erasure. The particular
221.72 @@ -329,54 +329,6 @@
221.73 }
221.74
221.75 /**
221.76 - * <p>Returns a Map representing the contents of the given CompositeData.
221.77 - * Each item in the CompositeData is represented by an entry in the map,
221.78 - * where the name and value of the item are the key and value of the entry.
221.79 - * The returned value is modifiable but modifications to it have no effect
221.80 - * on the original CompositeData.</p>
221.81 - *
221.82 - * <p>For example, if you have a CompositeData {@code cd1} and you want
221.83 - * to produce another CompositeData {@code cd2} which is the same except
221.84 - * that the value of its {@code id} item has been changed to 253, you
221.85 - * could write:</p>
221.86 - *
221.87 - * <pre>
221.88 - * CompositeData cd1 = ...;
221.89 - * {@code Map<String, Object>} map = CompositeDataSupport.toMap(cd1);
221.90 - * assert(map.get("id") instanceof Integer);
221.91 - * map.put("id", 253);
221.92 - * CompositeData cd2 = {@link #CompositeDataSupport(CompositeType, Map)
221.93 - * new CompositeDataSupport}(cd1.getCompositeType(), map);
221.94 - * </pre>
221.95 - *
221.96 - * <p>Logically, this method would be a method in the {@link CompositeData}
221.97 - * interface, but cannot be for compatibility reasons.</p>
221.98 - *
221.99 - * @param cd the CompositeData to convert to a Map.
221.100 - *
221.101 - * @return a Map that is a copy of the contents of {@code cd}.
221.102 - *
221.103 - * @throws IllegalArgumentException if {@code cd} is null.
221.104 - *
221.105 - * @see #CompositeDataSupport(CompositeType, Map)
221.106 - */
221.107 - public static Map<String, Object> toMap(CompositeData cd) {
221.108 - if (cd == null)
221.109 - throw new IllegalArgumentException("Null argument");
221.110 -
221.111 - // If we really wanted, we could check whether cd is a
221.112 - // CompositeDataSupport and return a copy of cd.contents if so,
221.113 - // but I don't think that would be substantially faster.
221.114 - Map<String, Object> map = new LinkedHashMap<String, Object>();
221.115 - CompositeType ct = cd.getCompositeType();
221.116 - for (String key : ct.keySet()) {
221.117 - Object value = cd.get(key);
221.118 - map.put(key, value);
221.119 - }
221.120 - return map;
221.121 - }
221.122 -
221.123 - /**
221.124 * Compares the specified <var>obj</var> parameter with this
221.125 * <code>CompositeDataSupport</code> instance for equality.
221.126 * <p>
222.1 --- a/src/share/classes/javax/management/openmbean/CompositeType.java Mon Nov 23 10:04:47 2009 +0000
222.2 +++ b/src/share/classes/javax/management/openmbean/CompositeType.java Wed Nov 25 11:08:25 2009 -0800
222.3 @@ -89,7 +89,7 @@
222.4 * <br>
222.5 * @param itemNames The names of the items contained in the
222.6 * composite data values described by this <code>CompositeType</code> instance;
222.7 - * cannot be null; no element can be null or an empty string.
222.8 + * cannot be null and should contain at least one element; no element can be a null or empty string.
222.9 * Note that the order in which the item names are given is not important to differentiate a
222.10 * <code>CompositeType</code> instance from another;
222.11 * the item names are internally stored sorted in ascending alphanumeric order.
222.12 @@ -125,7 +125,7 @@
222.13 //
222.14 super(CompositeData.class.getName(), typeName, description, false);
222.15
222.16 - // Check the 3 arrays are not null and that there is no null element or empty string in them
222.17 + // Check the 3 arrays are not null or empty (ie length==0) and that there is no null element or empty string in them
222.18 //
222.19 checkForNullElement(itemNames, "itemNames");
222.20 checkForNullElement(itemDescriptions, "itemDescriptions");
222.21 @@ -159,8 +159,8 @@
222.22 }
222.23
222.24 private static void checkForNullElement(Object[] arg, String argName) {
222.25 - if (arg == null) {
222.26 - throw new IllegalArgumentException("Argument "+ argName +"[] cannot be null.");
222.27 + if ( (arg == null) || (arg.length == 0) ) {
222.28 + throw new IllegalArgumentException("Argument "+ argName +"[] cannot be null or empty.");
222.29 }
222.30 for (int i=0; i<arg.length; i++) {
222.31 if (arg[i] == null) {
223.1 --- a/src/share/classes/javax/management/openmbean/MXBeanMapping.java Mon Nov 23 10:04:47 2009 +0000
223.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
223.3 @@ -1,210 +0,0 @@
223.4 -/*
223.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
223.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
223.7 - *
223.8 - * This code is free software; you can redistribute it and/or modify it
223.9 - * under the terms of the GNU General Public License version 2 only, as
223.10 - * published by the Free Software Foundation. Sun designates this
223.11 - * particular file as subject to the "Classpath" exception as provided
223.12 - * by Sun in the LICENSE file that accompanied this code.
223.13 - *
223.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
223.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
223.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
223.17 - * version 2 for more details (a copy is included in the LICENSE file that
223.18 - * accompanied this code).
223.19 - *
223.20 - * You should have received a copy of the GNU General Public License version
223.21 - * 2 along with this work; if not, write to the Free Software Foundation,
223.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
223.23 - *
223.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
223.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
223.26 - * have any questions.
223.27 - */
223.28 -
223.29 -package javax.management.openmbean;
223.30 -
223.31 -import java.io.InvalidObjectException;
223.32 -import java.lang.reflect.Type;
223.33 -
223.34 -/**
223.35 - * <p>A custom mapping between Java types and Open types for use in MXBeans.
223.36 - * To define such a mapping, subclass this class and define at least the
223.37 - * {@link #fromOpenValue fromOpenValue} and {@link #toOpenValue toOpenValue}
223.38 - * methods, and optionally the {@link #checkReconstructible} method.
223.39 - * Then either use an {@link MXBeanMappingClass} annotation on your custom
223.40 - * Java types, or include this MXBeanMapping in an
223.41 - * {@link MXBeanMappingFactory}.</p>
223.42 - *
223.43 - * <p>For example, suppose we have a class {@code MyLinkedList}, which looks
223.44 - * like this:</p>
223.45 - *
223.46 - * <pre>
223.47 - * public class MyLinkedList {
223.48 - * public MyLinkedList(String name, MyLinkedList next) {...}
223.49 - * public String getName() {...}
223.50 - * public MyLinkedList getNext() {...}
223.51 - * }
223.52 - * </pre>
223.53 - *
223.54 - * <p>This is not a valid type for MXBeans, because it contains a
223.55 - * self-referential property "next" defined by the {@code getNext()}
223.56 - * method. MXBeans do not support recursive types. So we would like
223.57 - * to specify a mapping for {@code MyLinkedList} explicitly. When an
223.58 - * MXBean interface contains {@code MyLinkedList}, that will be mapped
223.59 - * into a {@code String[]}, which is a valid Open Type.</p>
223.60 - *
223.61 - * <p>To define this mapping, we first subclass {@code MXBeanMapping}:</p>
223.62 - *
223.63 - * <pre>
223.64 - * public class MyLinkedListMapping extends MXBeanMapping {
223.65 - * public MyLinkedListMapping(Type type) throws OpenDataException {
223.66 - * super(MyLinkedList.class, ArrayType.getArrayType(SimpleType.STRING));
223.67 - * if (type != MyLinkedList.class)
223.68 - * throw new OpenDataException("Mapping only valid for MyLinkedList");
223.69 - * }
223.70 - *
223.71 - * {@literal @Override}
223.72 - * public Object fromOpenValue(Object openValue) throws InvalidObjectException {
223.73 - * String[] array = (String[]) openValue;
223.74 - * MyLinkedList list = null;
223.75 - * for (int i = array.length - 1; i >= 0; i--)
223.76 - * list = new MyLinkedList(array[i], list);
223.77 - * return list;
223.78 - * }
223.79 - *
223.80 - * {@literal @Override}
223.81 - * public Object toOpenValue(Object javaValue) throws OpenDataException {
223.82 - * ArrayList<String> array = new ArrayList<String>();
223.83 - * for (MyLinkedList list = (MyLinkedList) javaValue; list != null;
223.84 - * list = list.getNext())
223.85 - * array.add(list.getName());
223.86 - * return array.toArray(new String[0]);
223.87 - * }
223.88 - * }
223.89 - * </pre>
223.90 - *
223.91 - * <p>The call to the superclass constructor specifies what the
223.92 - * original Java type is ({@code MyLinkedList.class}) and what Open
223.93 - * Type it is mapped to ({@code
223.94 - * ArrayType.getArrayType(SimpleType.STRING)}). The {@code
223.95 - * fromOpenValue} method says how we go from the Open Type ({@code
223.96 - * String[]}) to the Java type ({@code MyLinkedList}), and the {@code
223.97 - * toOpenValue} method says how we go from the Java type to the Open
223.98 - * Type.</p>
223.99 - *
223.100 - * <p>With this mapping defined, we can annotate the {@code MyLinkedList}
223.101 - * class appropriately:</p>
223.102 - *
223.103 - * <pre>
223.104 - * {@literal @MXBeanMappingClass}(MyLinkedListMapping.class)
223.105 - * public class MyLinkedList {...}
223.106 - * </pre>
223.107 - *
223.108 - * <p>Now we can use {@code MyLinkedList} in an MXBean interface and it
223.109 - * will work.</p>
223.110 - *
223.111 - * <p>If we are unable to modify the {@code MyLinkedList} class,
223.112 - * we can define an {@link MXBeanMappingFactory}. See the documentation
223.113 - * of that class for further details.</p>
223.114 - *
223.115 - * @see <a href="../MXBean.html#custom">MXBean specification, section
223.116 - * "Custom MXBean type mappings"</a>
223.117 - */
223.118 -public abstract class MXBeanMapping {
223.119 - private final Type javaType;
223.120 - private final OpenType<?> openType;
223.121 - private final Class<?> openClass;
223.122 -
223.123 - /**
223.124 - * <p>Construct a mapping between the given Java type and the given
223.125 - * Open Type.</p>
223.126 - *
223.127 - * @param javaType the Java type (for example, {@code MyLinkedList}).
223.128 - * @param openType the Open Type (for example, {@code
223.129 - * ArrayType.getArrayType(SimpleType.STRING)})
223.130 - *
223.131 - * @throws NullPointerException if either argument is null.
223.132 - */
223.133 - protected MXBeanMapping(Type javaType, OpenType<?> openType) {
223.134 - if (javaType == null || openType == null)
223.135 - throw new NullPointerException("Null argument");
223.136 - this.javaType = javaType;
223.137 - this.openType = openType;
223.138 - this.openClass = makeOpenClass(javaType, openType);
223.139 - }
223.140 -
223.141 - /**
223.142 - * <p>The Java type that was supplied to the constructor.</p>
223.143 - * @return the Java type that was supplied to the constructor.
223.144 - */
223.145 - public final Type getJavaType() {
223.146 - return javaType;
223.147 - }
223.148 -
223.149 - /**
223.150 - * <p>The Open Type that was supplied to the constructor.</p>
223.151 - * @return the Open Type that was supplied to the constructor.
223.152 - */
223.153 - public final OpenType<?> getOpenType() {
223.154 - return openType;
223.155 - }
223.156 -
223.157 - /**
223.158 - * <p>The Java class that corresponds to instances of the
223.159 - * {@linkplain #getOpenType() Open Type} for this mapping.</p>
223.160 - * @return the Java class that corresponds to instances of the
223.161 - * Open Type for this mapping.
223.162 - * @see OpenType#getClassName
223.163 - */
223.164 - public final Class<?> getOpenClass() {
223.165 - return openClass;
223.166 - }
223.167 -
223.168 - private static Class<?> makeOpenClass(Type javaType, OpenType<?> openType) {
223.169 - if (javaType instanceof Class<?> && ((Class<?>) javaType).isPrimitive())
223.170 - return (Class<?>) javaType;
223.171 - try {
223.172 - String className = OpenType.validClassName(openType.getClassName());
223.173 - return Class.forName(className, false, null);
223.174 - } catch (ClassNotFoundException e) {
223.175 - throw new RuntimeException(e); // should not happen
223.176 - } catch (OpenDataException e) {
223.177 - throw new IllegalArgumentException("Bad OpenType: " + openType, e);
223.178 - }
223.179 - }
223.180 -
223.181 - /**
223.182 - * <p>Convert an instance of the Open Type into the Java type.
223.183 - * @param openValue the value to be converted.
223.184 - * @return the converted value.
223.185 - * @throws InvalidObjectException if the value cannot be converted.
223.186 - */
223.187 - public abstract Object fromOpenValue(Object openValue)
223.188 - throws InvalidObjectException;
223.189 -
223.190 - /**
223.191 - * <p>Convert an instance of the Java type into the Open Type.
223.192 - * @param javaValue the value to be converted.
223.193 - * @return the converted value.
223.194 - * @throws OpenDataException if the value cannot be converted.
223.195 - */
223.196 - public abstract Object toOpenValue(Object javaValue)
223.197 - throws OpenDataException;
223.198 -
223.199 -
223.200 - /**
223.201 - * <p>Throw an appropriate InvalidObjectException if we will not
223.202 - * be able to convert back from the open data to the original Java
223.203 - * object. The {@link #fromOpenValue fromOpenValue} throws an
223.204 - * exception if a given open data value cannot be converted. This
223.205 - * method throws an exception if <em>no</em> open data values can
223.206 - * be converted. The default implementation of this method never
223.207 - * throws an exception. Subclasses can override it as
223.208 - * appropriate.</p>
223.209 - * @throws InvalidObjectException if {@code fromOpenValue} will throw
223.210 - * an exception no matter what its argument is.
223.211 - */
223.212 - public void checkReconstructible() throws InvalidObjectException {}
223.213 -}
224.1 --- a/src/share/classes/javax/management/openmbean/MXBeanMappingClass.java Mon Nov 23 10:04:47 2009 +0000
224.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
224.3 @@ -1,61 +0,0 @@
224.4 -/*
224.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
224.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
224.7 - *
224.8 - * This code is free software; you can redistribute it and/or modify it
224.9 - * under the terms of the GNU General Public License version 2 only, as
224.10 - * published by the Free Software Foundation. Sun designates this
224.11 - * particular file as subject to the "Classpath" exception as provided
224.12 - * by Sun in the LICENSE file that accompanied this code.
224.13 - *
224.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
224.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
224.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
224.17 - * version 2 for more details (a copy is included in the LICENSE file that
224.18 - * accompanied this code).
224.19 - *
224.20 - * You should have received a copy of the GNU General Public License version
224.21 - * 2 along with this work; if not, write to the Free Software Foundation,
224.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
224.23 - *
224.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
224.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
224.26 - * have any questions.
224.27 - */
224.28 -
224.29 -package javax.management.openmbean;
224.30 -
224.31 -import java.lang.annotation.Documented;
224.32 -import java.lang.annotation.ElementType;
224.33 -import java.lang.annotation.Inherited;
224.34 -import java.lang.annotation.Retention;
224.35 -import java.lang.annotation.RetentionPolicy;
224.36 -import java.lang.annotation.Target;
224.37 -
224.38 -import javax.management.NotCompliantMBeanException;
224.39 -
224.40 -/**
224.41 - * Specifies the MXBean mapping to be used for this Java type.
224.42 - * @see MXBeanMapping
224.43 - */
224.44 -@Retention(RetentionPolicy.RUNTIME)
224.45 -@Target(ElementType.TYPE)
224.46 -@Documented @Inherited
224.47 -public @interface MXBeanMappingClass {
224.48 - /**
224.49 - * <p>The {@link MXBeanMapping} class to be used to map the
224.50 - * annotated type. This class must have a public constructor with
224.51 - * a single argument of type {@link java.lang.reflect.Type}. The
224.52 - * constructor will be called with the annotated type as an
224.53 - * argument. See the {@code MXBeanMapping} documentation
224.54 - * for an example.</p>
224.55 - *
224.56 - * <p>If the {@code MXBeanMapping} cannot in fact handle that
224.57 - * type, the constructor should throw an {@link
224.58 - * OpenDataException}. If the constructor throws this or any other
224.59 - * exception then an MXBean in which the annotated type appears is
224.60 - * invalid, and registering it in the MBean Server will produce a
224.61 - * {@link NotCompliantMBeanException}.
224.62 - */
224.63 - public Class<? extends MXBeanMapping> value();
224.64 -}
225.1 --- a/src/share/classes/javax/management/openmbean/MXBeanMappingFactory.java Mon Nov 23 10:04:47 2009 +0000
225.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
225.3 @@ -1,165 +0,0 @@
225.4 -/*
225.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
225.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
225.7 - *
225.8 - * This code is free software; you can redistribute it and/or modify it
225.9 - * under the terms of the GNU General Public License version 2 only, as
225.10 - * published by the Free Software Foundation. Sun designates this
225.11 - * particular file as subject to the "Classpath" exception as provided
225.12 - * by Sun in the LICENSE file that accompanied this code.
225.13 - *
225.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
225.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
225.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
225.17 - * version 2 for more details (a copy is included in the LICENSE file that
225.18 - * accompanied this code).
225.19 - *
225.20 - * You should have received a copy of the GNU General Public License version
225.21 - * 2 along with this work; if not, write to the Free Software Foundation,
225.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
225.23 - *
225.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
225.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
225.26 - * have any questions.
225.27 - */
225.28 -
225.29 -package javax.management.openmbean;
225.30 -
225.31 -import com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory;
225.32 -import java.lang.reflect.Type;
225.33 -
225.34 -/**
225.35 - * <p>Defines how types are mapped for a given MXBean or set of MXBeans.
225.36 - * An {@code MXBeanMappingFactory} can be specified either through the
225.37 - * {@link MXBeanMappingFactoryClass} annotation, or through the
225.38 - * {@link javax.management.JMX.MBeanOptions JMX.MBeanOptions} argument to a
225.39 - * {@link javax.management.StandardMBean StandardMBean} constructor or MXBean
225.40 - * proxy.</p>
225.41 - *
225.42 - * <p>An {@code MXBeanMappingFactory} must return an {@code MXBeanMapping}
225.43 - * for any Java type that appears in the MXBeans that the factory is being
225.44 - * used for. Usually it does that by handling any custom types, and
225.45 - * forwarding everything else to the {@linkplain #DEFAULT default mapping
225.46 - * factory}.</p>
225.47 - *
225.48 - * <p>Consider the {@code MyLinkedList} example from the {@link MXBeanMapping}
225.49 - * documentation. If we are unable to change the {@code MyLinkedList} class
225.50 - * to add an {@link MXBeanMappingClass} annotation, we could achieve the same
225.51 - * effect by defining {@code MyLinkedListMappingFactory} as follows:</p>
225.52 - *
225.53 - * <pre>
225.54 - * public class MyLinkedListMappingFactory extends MXBeanMappingFactory {
225.55 - * public MyLinkedListMappingFactory() {}
225.56 - *
225.57 - * public MXBeanMapping mappingForType(Type t, MXBeanMappingFactory f)
225.58 - * throws OpenDataException {
225.59 - * if (t == MyLinkedList.class)
225.60 - * return new MyLinkedListMapping(t);
225.61 - * else
225.62 - * return MXBeanMappingFactory.DEFAULT.mappingForType(t, f);
225.63 - * }
225.64 - * }
225.65 - * </pre>
225.66 - *
225.67 - * <p>The mapping factory handles only the {@code MyLinkedList} class.
225.68 - * Every other type is forwarded to the default mapping factory.
225.69 - * This includes types such as {@code MyLinkedList[]} and
225.70 - * {@code List<MyLinkedList>}; the default mapping factory will recursively
225.71 - * invoke {@code MyLinkedListMappingFactory} to map the contained
225.72 - * {@code MyLinkedList} type.</p>
225.73 - *
225.74 - * <p>Once we have defined {@code MyLinkedListMappingFactory}, we can use
225.75 - * it in an MXBean interface like this:</p>
225.76 - *
225.77 - * <pre>
225.78 - * {@literal @MXBeanMappingFactoryClass}(MyLinkedListMappingFactory.class)
225.79 - * public interface SomethingMXBean {
225.80 - * public MyLinkedList getSomething();
225.81 - * }
225.82 - * </pre>
225.83 - *
225.84 - * <p>Alternatively we can annotate the package that {@code SomethingMXBean}
225.85 - * appears in, or we can supply the factory to a {@link
225.86 - * javax.management.StandardMBean StandardMBean} constructor or MXBean
225.87 - * proxy.</p>
225.88 - *
225.89 - * @see <a href="../MXBean.html#custom">MXBean specification, section
225.90 - * "Custom MXBean type mappings"</a>
225.91 - */
225.92 -public abstract class MXBeanMappingFactory {
225.93 - /**
225.94 - * <p>Construct an instance of this class.</p>
225.95 - */
225.96 - protected MXBeanMappingFactory() {}
225.97 -
225.98 - /**
225.99 - * <p>Mapping factory that applies the default rules for MXBean
225.100 - * mappings, as described in the <a
225.101 - * href="../MXBean.html#MXBean-spec">MXBean specification</a>.</p>
225.102 - */
225.103 - public static final MXBeanMappingFactory DEFAULT =
225.104 - new DefaultMXBeanMappingFactory();
225.105 -
225.106 - /**
225.107 - * <p>Determine the appropriate MXBeanMappingFactory to use for the given
225.108 - * MXBean interface, based on its annotations. If the interface has an
225.109 - * {@link MXBeanMappingFactoryClass @MXBeanMappingFactoryClass} annotation,
225.110 - * that is used to determine the MXBeanMappingFactory. Otherwise, if the
225.111 - * package containing the interface has such an annotation, that is used.
225.112 - * Otherwise the MXBeanMappingFactory is the {@linkplain #DEFAULT default}
225.113 - * one.</p>
225.114 - *
225.115 - * @param intf the MXBean interface for which to determine the
225.116 - * MXBeanMappingFactory.
225.117 - *
225.118 - * @return the MXBeanMappingFactory for the given MXBean interface.
225.119 - *
225.120 - * @throws IllegalArgumentException if {@code intf} is null, or if an
225.121 - * exception occurs while trying constructing an MXBeanMappingFactory
225.122 - * based on an annotation. In the second case, the exception will appear
225.123 - * in the {@linkplain Throwable#getCause() cause chain} of the
225.124 - * {@code IllegalArgumentException}.
225.125 - */
225.126 - public static MXBeanMappingFactory forInterface(Class<?> intf) {
225.127 - if (intf == null)
225.128 - throw new IllegalArgumentException("Null interface");
225.129 - MXBeanMappingFactoryClass annot =
225.130 - intf.getAnnotation(MXBeanMappingFactoryClass.class);
225.131 - if (annot == null) {
225.132 - Package p = intf.getPackage();
225.133 - if (p != null)
225.134 - annot = p.getAnnotation(MXBeanMappingFactoryClass.class);
225.135 - }
225.136 - if (annot == null)
225.137 - return MXBeanMappingFactory.DEFAULT;
225.138 - Class<? extends MXBeanMappingFactory> factoryClass = annot.value();
225.139 - try {
225.140 - return annot.value().newInstance();
225.141 - } catch (Exception e) {
225.142 - throw new IllegalArgumentException(
225.143 - "Could not instantiate MXBeanMappingFactory " +
225.144 - factoryClass.getName() +
225.145 - " from @MXBeanMappingFactoryClass", e);
225.146 - }
225.147 - }
225.148 -
225.149 - /**
225.150 - * <p>Return the mapping for the given Java type. Typically, a
225.151 - * mapping factory will return mappings for types it handles, and
225.152 - * forward other types to another mapping factory, most often
225.153 - * the {@linkplain #DEFAULT default one}.</p>
225.154 - * @param t the Java type to be mapped.
225.155 - * @param f the original mapping factory that was consulted to do
225.156 - * the mapping. A mapping factory should pass this parameter intact
225.157 - * if it forwards a type to another mapping factory. In the example,
225.158 - * this is how {@code MyLinkedListMappingFactory} works for types
225.159 - * like {@code MyLinkedList[]} and {@code List<MyLinkedList>}.
225.160 - * @return the mapping for the given type.
225.161 - * @throws OpenDataException if this type cannot be mapped. This
225.162 - * exception is appropriate if the factory is supposed to handle
225.163 - * all types of this sort (for example, all linked lists), but
225.164 - * cannot handle this particular type.
225.165 - */
225.166 - public abstract MXBeanMapping mappingForType(Type t, MXBeanMappingFactory f)
225.167 - throws OpenDataException;
225.168 -}
226.1 --- a/src/share/classes/javax/management/openmbean/MXBeanMappingFactoryClass.java Mon Nov 23 10:04:47 2009 +0000
226.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
226.3 @@ -1,72 +0,0 @@
226.4 -/*
226.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
226.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
226.7 - *
226.8 - * This code is free software; you can redistribute it and/or modify it
226.9 - * under the terms of the GNU General Public License version 2 only, as
226.10 - * published by the Free Software Foundation. Sun designates this
226.11 - * particular file as subject to the "Classpath" exception as provided
226.12 - * by Sun in the LICENSE file that accompanied this code.
226.13 - *
226.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
226.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
226.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
226.17 - * version 2 for more details (a copy is included in the LICENSE file that
226.18 - * accompanied this code).
226.19 - *
226.20 - * You should have received a copy of the GNU General Public License version
226.21 - * 2 along with this work; if not, write to the Free Software Foundation,
226.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
226.23 - *
226.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
226.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
226.26 - * have any questions.
226.27 - */
226.28 -
226.29 -package javax.management.openmbean;
226.30 -
226.31 -import java.lang.annotation.Documented;
226.32 -import java.lang.annotation.ElementType;
226.33 -import java.lang.annotation.Inherited;
226.34 -import java.lang.annotation.Retention;
226.35 -import java.lang.annotation.RetentionPolicy;
226.36 -import java.lang.annotation.Target;
226.37 -
226.38 -/**
226.39 - * <p>Specifies the MXBean mapping factory to be used for Java types
226.40 - * in an MXBean interface, or in all MXBean interfaces in a package.</p>
226.41 - *
226.42 - * <p>Applying a mapping factory to all Java types in an MXBean interface
226.43 - * looks like this:</p>
226.44 - *
226.45 - * <pre>
226.46 - * {@literal @MXBeanMappingFactoryClass}(MyLinkedListMappingFactory.class)
226.47 - * public interface SomethingMXBean {
226.48 - * public MyLinkedList getSomething();
226.49 - * }
226.50 - * </pre>
226.51 - *
226.52 - * <p>Applying a mapping factory to all Java types in all MXBean interfaces
226.53 - * in a package, say {@code com.example.mxbeans}, looks like this. In the
226.54 - * package source directory, create a file called {@code package-info.java}
226.55 - * with these contents:</p>
226.56 - *
226.57 - * <pre>
226.58 - * {@literal @MXBeanMappingFactoryClass}(MyLinkedListMappingFactory.class)
226.59 - * package com.example.mxbeans;
226.60 - * </pre>
226.61 - *
226.62 - * @see MXBeanMappingFactory
226.63 - */
226.64 -@Retention(RetentionPolicy.RUNTIME)
226.65 -@Target({ElementType.TYPE, ElementType.PACKAGE})
226.66 -@Documented @Inherited
226.67 -public @interface MXBeanMappingFactoryClass {
226.68 - /**
226.69 - * <p>The {@link MXBeanMappingFactory} class to be used to map
226.70 - * types in the annotated interface or package. This class must
226.71 - * have a public constructor with no arguments. See the {@code
226.72 - * MXBeanMappingFactory} documentation for an example.</p>
226.73 - */
226.74 - public Class<? extends MXBeanMappingFactory> value();
226.75 -}
227.1 --- a/src/share/classes/javax/management/openmbean/OpenType.java Mon Nov 23 10:04:47 2009 +0000
227.2 +++ b/src/share/classes/javax/management/openmbean/OpenType.java Wed Nov 25 11:08:25 2009 -0800
227.3 @@ -219,7 +219,7 @@
227.4 });
227.5 }
227.6
227.7 - static String validClassName(String className) throws OpenDataException {
227.8 + private static String validClassName(String className) throws OpenDataException {
227.9 className = valid("className", className);
227.10
227.11 // Check if className describes an array class, and determines its elements' class name.
228.1 --- a/src/share/classes/javax/management/package.html Mon Nov 23 10:04:47 2009 +0000
228.2 +++ b/src/share/classes/javax/management/package.html Wed Nov 25 11:08:25 2009 -0800
228.3 @@ -128,42 +128,6 @@
228.4 class.</p>
228.5
228.6
228.7 - <h3 id="stdannot">Defining Standard MBeans with annotations</h3>
228.8 -
228.9 - <p>As an alternative to creating an interface such as
228.10 - <code>ConfigurationMBean</code> and a class that implements it,
228.11 - you can write just the class, and use annotations to pick out the
228.12 - public methods that will make up the management interface. For
228.13 - example, the following class has the same management interface
228.14 - as a <code>Configuration</code> class that implements the
228.15 - <code>ConfigurationMBean</code> interface above.</p>
228.16 -
228.17 - <pre>
228.18 - {@link javax.management.MBean @MBean}
228.19 - public class Configuration {
228.20 - {@link javax.management.ManagedAttribute @ManagedAttribute}
228.21 - public int getCacheSize() {...}
228.22 - @ManagedAttribute
228.23 - public void setCacheSize(int size) {...}
228.24 -
228.25 - @ManagedAttribute
228.26 - public long getLastChangedTime() {...}
228.27 -
228.28 - {@link javax.management.ManagedOperation @ManagedOperation}
228.29 - public void save() {...}
228.30 - ...
228.31 - }
228.32 - </pre>
228.33 -
228.34 - <p>This approach simplifies development, but it does have two
228.35 - potential drawbacks. First, if you run the Javadoc tool on
228.36 - this class, the documentation of the management interface may
228.37 - be mixed in with the documentation of non-management methods
228.38 - in the class. Second, you cannot make a proxy
228.39 - as described <a href="#proxy">below</a> if you do not have an
228.40 - interface like <code>ConfigurationMBean</code>.</p>
228.41 -
228.42 -
228.43 <h3>MXBeans</h3>
228.44
228.45 <p>An <em>MXBean</em> is a variant of Standard MBean where complex
228.46 @@ -173,11 +137,6 @@
228.47 classes in your MBean interface. They are described in detail
228.48 in the specification for {@link javax.management.MXBean MXBean}.</p>
228.49
228.50 - <p>You can define MXBeans using annotations as described
228.51 - in the <a href="#stdannot">previous section</a>, but
228.52 - using the <code>@MXBean</code> annotation instead of
228.53 - <code>@MBean</code>.</p>
228.54 -
228.55
228.56 <h3>Dynamic MBeans</h3>
228.57
228.58 @@ -305,7 +264,7 @@
228.59 perform the query.</p>
228.60
228.61
228.62 - <h3>MBean lifecycle and resource injection</h3>
228.63 + <h3>MBean lifecycle</h3>
228.64
228.65 <p>An MBean can implement the {@link javax.management.MBeanRegistration
228.66 MBeanRegistration} interface in order to be told when it is registered
228.67 @@ -315,11 +274,6 @@
228.68 object and to get its <code>ObjectName</code> within the MBean
228.69 Server.</p>
228.70
228.71 - <p>If the only reason to implement <code>MBeanRegistration</code> is to
228.72 - discover the <code>MBeanServer</code> and <code>ObjectName</code>, <a
228.73 - href="MBeanRegistration.html#injection">resource injection</a> may be
228.74 - more convenient.</p>
228.75 -
228.76
228.77 <h2>Notifications</h2>
228.78
228.79 @@ -329,26 +283,16 @@
228.80 <em>type</em> string that can distinguish it from other
228.81 notifications of the same class.</p>
228.82
228.83 - <p>If an MBean is to emit notifications, it must do one of two things.</p>
228.84 -
228.85 - <ul>
228.86 - <li>It can implement the interface {@link
228.87 - javax.management.NotificationEmitter NotificationEmitter} (or
228.88 - its parent {@link javax.management.NotificationBroadcaster
228.89 - NotificationBroadcaster}), usually by subclassing
228.90 - {@link javax.management.NotificationBroadcasterSupport
228.91 - NotificationBroadcasterSupport} or delegating to an instance of
228.92 - that class.</li>
228.93 - <li>It can use <a href="MBeanRegistration.html#injection">resource
228.94 - injection</a> to obtain a {@link javax.management.SendNotification
228.95 - SendNotification} object that it can use to send
228.96 - notifications.</li>
228.97 - </ul>
228.98 -
228.99 - <p>The two classes below illustrate these two techniques:</p>
228.100 + <p>An MBean that will emit notifications must implement the
228.101 + {@link javax.management.NotificationBroadcaster
228.102 + NotificationBroadcaster} or {@link
228.103 + javax.management.NotificationEmitter NotificationEmitter}
228.104 + interface. Usually, it does this by subclassing
228.105 + {@link javax.management.NotificationBroadcasterSupport
228.106 + NotificationBroadcasterSupport} or delegating to an instance of
228.107 + that class. Here is an example:</p>
228.108
228.109 <pre>
228.110 - // Implementing NotificationEmitter (via NotificationBroadcasterSupport)
228.111 public class Configuration <b>extends NotificationBroadcasterSupport</b>
228.112 implements ConfigurationMBean {
228.113 ...
228.114 @@ -358,17 +302,6 @@
228.115 sendNotification}(n)</b>;
228.116 }
228.117 }
228.118 -
228.119 - // Getting a SendNotification through resource injection
228.120 - public class Configuration implements ConfigurationMBean {
228.121 - <b>@Resource</b>
228.122 - private volatile SendNotification sender;
228.123 - ...
228.124 - private void updated() {
228.125 - Notification n = new Notification(...);
228.126 - <b>sender.sendNotification(n)</b>;
228.127 - }
228.128 - }
228.129 </pre>
228.130
228.131
228.132 @@ -410,88 +343,51 @@
228.133 <h3 id="interop">Interoperability between versions of the JMX
228.134 specification</h3>
228.135
228.136 - <p>When a client connects to a server using the JMX Remote
228.137 - API, it is possible that they do not have the same version
228.138 - of the JMX specification. The version of the JMX
228.139 - specification described here is version 2.0. Previous
228.140 - versions were 1.0, 1.1, 1.2, and 1.4. (There was no 1.3.)
228.141 - The standard JMX Remote API is defined to work with version
228.142 - 1.2 onwards, so in standards-based deployment the only
228.143 - interoperability questions that arise concern version 1.2
228.144 - onwards.</p>
228.145 + <p>When a client connects to a server using the JMX Remote
228.146 + API, it is possible that they do not have the same version
228.147 + of the JMX specification. The version of the JMX
228.148 + specification described here is version 1.4. Previous
228.149 + versions were 1.0, 1.1, and 1.2. (There was no 1.3.)
228.150 + The standard JMX Remote API is defined to work with version
228.151 + 1.2 onwards, so in standards-based deployment the only
228.152 + interoperability questions that arise concern version 1.2
228.153 + onwards.</p>
228.154
228.155 - <p>Every version of the JMX specification continues to
228.156 - implement the features of previous versions. So when the
228.157 - client is running an earlier version than the server, there
228.158 - should not be any interoperability concerns. The only
228.159 - exception is the unlikely one where a pre-2.0 client used
228.160 - the string {@code //} in the domain part of an {@link
228.161 - javax.management.ObjectName ObjectName}.</p>
228.162 + <p>Every version of the JMX specification continues to
228.163 + implement the features of previous versions. So when the
228.164 + client is running an earlier version than the server, there
228.165 + should not be any interoperability concerns.</p>
228.166
228.167 - <p>When the client is running a later version than the server,
228.168 - certain newer features may not be available, as detailed in
228.169 - the next sections. The method {@link
228.170 - javax.management.JMX#getSpecificationVersion
228.171 - JMX.getSpecificationVersion} can be used to determine the
228.172 - server version to check if required features are
228.173 - available.</p>
228.174 + <p>When the client is running a later version than the server,
228.175 + certain newer features may not be available, as detailed in
228.176 + the next sections. The client can determine the server's
228.177 + version by examining the {@link
228.178 + javax.management.MBeanServerDelegateMBean#getSpecificationVersion
228.179 + SpecificationVersion} attribute of the {@code
228.180 + MBeanServerDelegate}.</p>
228.181
228.182 - <h4 id="interop-1.4">If the remote MBean Server is 1.4</h4>
228.183 + <h4 id="interop-1.2">If the remote MBean Server is 1.2</h4>
228.184
228.185 <ul>
228.186
228.187 - <li><p>You cannot use {@link
228.188 - javax.management.QueryNotificationFilter
228.189 - QueryNotificationFilter} in {@link
228.190 - javax.management.MBeanServerConnection#addNotificationListener
228.191 - addNotificationListener} since this class did not exist
228.192 - in 1.4.</p>
228.193 + <li><p>You cannot use wildcards in a key property of an
228.194 + {@link javax.management.ObjectName ObjectName}, for
228.195 + example {@code domain:type=Foo,name=*}. Wildcards that
228.196 + match whole properties are still allowed, for example
228.197 + {@code *:*} or {@code *:type=Foo,*}.</p>
228.198
228.199 - <li><p>In an attribute in a query, you cannot access values
228.200 - inside complex types using dot syntax, for example
228.201 - {@link javax.management.Query#attr Query.attr}{@code
228.202 - ("HeapMemoryUsage.used")}.</p>
228.203 + <li><p>You cannot use {@link
228.204 + javax.management.Query#isInstanceOf Query.isInstanceOf}
228.205 + in a query.</p>
228.206
228.207 - <li><p>The packages {@link javax.management.event} and
228.208 - {@link javax.management.namespace} did not exist in 1.4,
228.209 - so you cannot remotely create instances of the MBeans
228.210 - they define.</p>
228.211 + <li><p>You cannot use dot syntax such as {@code
228.212 + HeapMemoryUsage.used} in the {@linkplain
228.213 + javax.management.monitor.Monitor#setObservedAttribute
228.214 + observed attribute} of a monitor, as described in the
228.215 + documentation for the {@link javax.management.monitor}
228.216 + package.</p>
228.217
228.218 - <li><p>Even if the remote MBean Server is 2.0, you cannot in
228.219 - general suppose that {@link
228.220 - javax.management.event.EventClient EventClient} or
228.221 - {@link javax.management.ClientContext ClientContext}
228.222 - will work there without first checking. If the remote
228.223 - MBean Server is 1.4 then those checks will return false.
228.224 - An attempt to use these features without checking will
228.225 - fail in the same way as for a remote 2.0 that is not
228.226 - configured to support them.</p>
228.227 - </ul>
228.228 -
228.229 - <h4 id="interop-1.2">If the remote MBean Server is 1.2</h4>
228.230 -
228.231 - <p><b>In addition to the above</b>,</p>
228.232 -
228.233 - <ul>
228.234 -
228.235 - <li><p>You cannot use wildcards in a key property of an
228.236 - {@link javax.management.ObjectName ObjectName}, for
228.237 - example {@code domain:type=Foo,name=*}. Wildcards that
228.238 - match whole properties are still allowed, for example
228.239 - {@code *:*} or {@code *:type=Foo,*}.</p>
228.240 -
228.241 - <li><p>You cannot use {@link
228.242 - javax.management.Query#isInstanceOf Query.isInstanceOf}
228.243 - in a query.</p>
228.244 -
228.245 - <li><p>You cannot use dot syntax such as {@code
228.246 - HeapMemoryUsage.used} in the {@linkplain
228.247 - javax.management.monitor.Monitor#setObservedAttribute
228.248 - observed attribute} of a monitor, as described in the
228.249 - documentation for the {@link javax.management.monitor}
228.250 - package.</p>
228.251 -
228.252 - </ul>
228.253 + </ul>
228.254
228.255 <p id="spec">
228.256 @see <a href="{@docRoot}/../technotes/guides/jmx/index.html">
229.1 --- a/src/share/classes/javax/management/remote/IdentityMBeanServerForwarder.java Mon Nov 23 10:04:47 2009 +0000
229.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
229.3 @@ -1,303 +0,0 @@
229.4 -/*
229.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
229.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
229.7 - *
229.8 - * This code is free software; you can redistribute it and/or modify it
229.9 - * under the terms of the GNU General Public License version 2 only, as
229.10 - * published by the Free Software Foundation. Sun designates this
229.11 - * particular file as subject to the "Classpath" exception as provided
229.12 - * by Sun in the LICENSE file that accompanied this code.
229.13 - *
229.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
229.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
229.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
229.17 - * version 2 for more details (a copy is included in the LICENSE file that
229.18 - * accompanied this code).
229.19 - *
229.20 - * You should have received a copy of the GNU General Public License version
229.21 - * 2 along with this work; if not, write to the Free Software Foundation,
229.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
229.23 - *
229.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
229.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
229.26 - * have any questions.
229.27 - */
229.28 -package javax.management.remote;
229.29 -
229.30 -import java.io.ObjectInputStream;
229.31 -import java.util.Set;
229.32 -import javax.management.Attribute;
229.33 -import javax.management.AttributeList;
229.34 -import javax.management.AttributeNotFoundException;
229.35 -import javax.management.InstanceAlreadyExistsException;
229.36 -import javax.management.InstanceNotFoundException;
229.37 -import javax.management.IntrospectionException;
229.38 -import javax.management.InvalidAttributeValueException;
229.39 -import javax.management.ListenerNotFoundException;
229.40 -import javax.management.MBeanException;
229.41 -import javax.management.MBeanInfo;
229.42 -import javax.management.MBeanRegistrationException;
229.43 -import javax.management.MBeanServer;
229.44 -import javax.management.NotCompliantMBeanException;
229.45 -import javax.management.NotificationFilter;
229.46 -import javax.management.NotificationListener;
229.47 -import javax.management.ObjectInstance;
229.48 -import javax.management.ObjectName;
229.49 -import javax.management.OperationsException;
229.50 -import javax.management.QueryExp;
229.51 -import javax.management.ReflectionException;
229.52 -import javax.management.loading.ClassLoaderRepository;
229.53 -
229.54 -/**
229.55 - * An {@link MBeanServerForwarder} that forwards all {@link MBeanServer}
229.56 - * operations unchanged to the next {@code MBeanServer} in the chain.
229.57 - * This class is typically subclassed to override some but not all methods.
229.58 - */
229.59 -public class IdentityMBeanServerForwarder implements MBeanServerForwarder {
229.60 -
229.61 - private MBeanServer next;
229.62 -
229.63 - /**
229.64 - * <p>Construct a forwarder that has no next {@code MBeanServer}.
229.65 - * The resulting object will be unusable until {@link #setMBeanServer
229.66 - * setMBeanServer} is called to establish the next item in the chain.</p>
229.67 - */
229.68 - public IdentityMBeanServerForwarder() {
229.69 - }
229.70 -
229.71 - /**
229.72 - * <p>Construct a forwarder that forwards to the given {@code MBeanServer}.
229.73 - * It is not an error for {@code next} to be null, but the resulting object
229.74 - * will be unusable until {@link #setMBeanServer setMBeanServer} is called
229.75 - * to establish the next item in the chain.</p>
229.76 - */
229.77 - public IdentityMBeanServerForwarder(MBeanServer next) {
229.78 - this.next = next;
229.79 - }
229.80 -
229.81 - public synchronized MBeanServer getMBeanServer() {
229.82 - return next;
229.83 - }
229.84 -
229.85 - public synchronized void setMBeanServer(MBeanServer mbs) {
229.86 - next = mbs;
229.87 - }
229.88 -
229.89 - private synchronized MBeanServer next() {
229.90 - return next;
229.91 - }
229.92 -
229.93 - public void unregisterMBean(ObjectName name)
229.94 - throws InstanceNotFoundException, MBeanRegistrationException {
229.95 - next().unregisterMBean(name);
229.96 - }
229.97 -
229.98 - public AttributeList setAttributes(ObjectName name,
229.99 - AttributeList attributes)
229.100 - throws InstanceNotFoundException, ReflectionException {
229.101 - return next().setAttributes(name, attributes);
229.102 - }
229.103 -
229.104 - public void setAttribute(ObjectName name, Attribute attribute)
229.105 - throws InstanceNotFoundException, AttributeNotFoundException,
229.106 - InvalidAttributeValueException, MBeanException,
229.107 - ReflectionException {
229.108 - next().setAttribute(name, attribute);
229.109 - }
229.110 -
229.111 - public void removeNotificationListener(ObjectName name,
229.112 - NotificationListener listener,
229.113 - NotificationFilter filter,
229.114 - Object handback)
229.115 - throws InstanceNotFoundException, ListenerNotFoundException {
229.116 - next().removeNotificationListener(name, listener, filter, handback);
229.117 - }
229.118 -
229.119 - public void removeNotificationListener(ObjectName name,
229.120 - NotificationListener listener)
229.121 - throws InstanceNotFoundException, ListenerNotFoundException {
229.122 - next().removeNotificationListener(name, listener);
229.123 - }
229.124 -
229.125 - public void removeNotificationListener(ObjectName name, ObjectName listener,
229.126 - NotificationFilter filter,
229.127 - Object handback)
229.128 - throws InstanceNotFoundException, ListenerNotFoundException {
229.129 - next().removeNotificationListener(name, listener, filter, handback);
229.130 - }
229.131 -
229.132 - public void removeNotificationListener(ObjectName name, ObjectName listener)
229.133 - throws InstanceNotFoundException, ListenerNotFoundException {
229.134 - next().removeNotificationListener(name, listener);
229.135 - }
229.136 -
229.137 - public ObjectInstance registerMBean(Object object, ObjectName name)
229.138 - throws InstanceAlreadyExistsException, MBeanRegistrationException,
229.139 - NotCompliantMBeanException {
229.140 - return next().registerMBean(object, name);
229.141 - }
229.142 -
229.143 - public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
229.144 - return next().queryNames(name, query);
229.145 - }
229.146 -
229.147 - public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
229.148 - return next().queryMBeans(name, query);
229.149 - }
229.150 -
229.151 - public boolean isRegistered(ObjectName name) {
229.152 - return next().isRegistered(name);
229.153 - }
229.154 -
229.155 - public boolean isInstanceOf(ObjectName name, String className)
229.156 - throws InstanceNotFoundException {
229.157 - return next().isInstanceOf(name, className);
229.158 - }
229.159 -
229.160 - public Object invoke(ObjectName name, String operationName, Object[] params,
229.161 - String[] signature)
229.162 - throws InstanceNotFoundException, MBeanException,
229.163 - ReflectionException {
229.164 - return next().invoke(name, operationName, params, signature);
229.165 - }
229.166 -
229.167 - public Object instantiate(String className, ObjectName loaderName,
229.168 - Object[] params, String[] signature)
229.169 - throws ReflectionException, MBeanException,
229.170 - InstanceNotFoundException {
229.171 - return next().instantiate(className, loaderName, params, signature);
229.172 - }
229.173 -
229.174 - public Object instantiate(String className, Object[] params,
229.175 - String[] signature)
229.176 - throws ReflectionException, MBeanException {
229.177 - return next().instantiate(className, params, signature);
229.178 - }
229.179 -
229.180 - public Object instantiate(String className, ObjectName loaderName)
229.181 - throws ReflectionException, MBeanException,
229.182 - InstanceNotFoundException {
229.183 - return next().instantiate(className, loaderName);
229.184 - }
229.185 -
229.186 - public Object instantiate(String className)
229.187 - throws ReflectionException, MBeanException {
229.188 - return next().instantiate(className);
229.189 - }
229.190 -
229.191 - public ObjectInstance getObjectInstance(ObjectName name)
229.192 - throws InstanceNotFoundException {
229.193 - return next().getObjectInstance(name);
229.194 - }
229.195 -
229.196 - public MBeanInfo getMBeanInfo(ObjectName name)
229.197 - throws InstanceNotFoundException, IntrospectionException,
229.198 - ReflectionException {
229.199 - return next().getMBeanInfo(name);
229.200 - }
229.201 -
229.202 - public Integer getMBeanCount() {
229.203 - return next().getMBeanCount();
229.204 - }
229.205 -
229.206 - public String[] getDomains() {
229.207 - return next().getDomains();
229.208 - }
229.209 -
229.210 - public String getDefaultDomain() {
229.211 - return next().getDefaultDomain();
229.212 - }
229.213 -
229.214 - public ClassLoaderRepository getClassLoaderRepository() {
229.215 - return next().getClassLoaderRepository();
229.216 - }
229.217 -
229.218 - public ClassLoader getClassLoaderFor(ObjectName mbeanName)
229.219 - throws InstanceNotFoundException {
229.220 - return next().getClassLoaderFor(mbeanName);
229.221 - }
229.222 -
229.223 - public ClassLoader getClassLoader(ObjectName loaderName)
229.224 - throws InstanceNotFoundException {
229.225 - return next().getClassLoader(loaderName);
229.226 - }
229.227 -
229.228 - public AttributeList getAttributes(ObjectName name, String[] attributes)
229.229 - throws InstanceNotFoundException, ReflectionException {
229.230 - return next().getAttributes(name, attributes);
229.231 - }
229.232 -
229.233 - public Object getAttribute(ObjectName name, String attribute)
229.234 - throws MBeanException, AttributeNotFoundException,
229.235 - InstanceNotFoundException, ReflectionException {
229.236 - return next().getAttribute(name, attribute);
229.237 - }
229.238 -
229.239 - @Deprecated
229.240 - public ObjectInputStream deserialize(String className,
229.241 - ObjectName loaderName,
229.242 - byte[] data)
229.243 - throws InstanceNotFoundException, OperationsException,
229.244 - ReflectionException {
229.245 - return next().deserialize(className, loaderName, data);
229.246 - }
229.247 -
229.248 - @Deprecated
229.249 - public ObjectInputStream deserialize(String className, byte[] data)
229.250 - throws OperationsException, ReflectionException {
229.251 - return next().deserialize(className, data);
229.252 - }
229.253 -
229.254 - @Deprecated
229.255 - public ObjectInputStream deserialize(ObjectName name, byte[] data)
229.256 - throws InstanceNotFoundException, OperationsException {
229.257 - return next().deserialize(name, data);
229.258 - }
229.259 -
229.260 - public ObjectInstance createMBean(String className, ObjectName name,
229.261 - ObjectName loaderName, Object[] params,
229.262 - String[] signature)
229.263 - throws ReflectionException, InstanceAlreadyExistsException,
229.264 - MBeanRegistrationException, MBeanException,
229.265 - NotCompliantMBeanException, InstanceNotFoundException {
229.266 - return next().createMBean(className, name, loaderName, params, signature);
229.267 - }
229.268 -
229.269 - public ObjectInstance createMBean(String className, ObjectName name,
229.270 - Object[] params, String[] signature)
229.271 - throws ReflectionException, InstanceAlreadyExistsException,
229.272 - MBeanRegistrationException, MBeanException,
229.273 - NotCompliantMBeanException {
229.274 - return next().createMBean(className, name, params, signature);
229.275 - }
229.276 -
229.277 - public ObjectInstance createMBean(String className, ObjectName name,
229.278 - ObjectName loaderName)
229.279 - throws ReflectionException, InstanceAlreadyExistsException,
229.280 - MBeanRegistrationException, MBeanException,
229.281 - NotCompliantMBeanException, InstanceNotFoundException {
229.282 - return next().createMBean(className, name, loaderName);
229.283 - }
229.284 -
229.285 - public ObjectInstance createMBean(String className, ObjectName name)
229.286 - throws ReflectionException, InstanceAlreadyExistsException,
229.287 - MBeanRegistrationException, MBeanException,
229.288 - NotCompliantMBeanException {
229.289 - return next().createMBean(className, name);
229.290 - }
229.291 -
229.292 - public void addNotificationListener(ObjectName name, ObjectName listener,
229.293 - NotificationFilter filter,
229.294 - Object handback)
229.295 - throws InstanceNotFoundException {
229.296 - next().addNotificationListener(name, listener, filter, handback);
229.297 - }
229.298 -
229.299 - public void addNotificationListener(ObjectName name,
229.300 - NotificationListener listener,
229.301 - NotificationFilter filter,
229.302 - Object handback)
229.303 - throws InstanceNotFoundException {
229.304 - next().addNotificationListener(name, listener, filter, handback);
229.305 - }
229.306 -}
230.1 --- a/src/share/classes/javax/management/remote/JMXConnector.java Mon Nov 23 10:04:47 2009 +0000
230.2 +++ b/src/share/classes/javax/management/remote/JMXConnector.java Wed Nov 25 11:08:25 2009 -0800
230.3 @@ -1,5 +1,5 @@
230.4 /*
230.5 - * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
230.6 + * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
230.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
230.8 *
230.9 * This code is free software; you can redistribute it and/or modify it
230.10 @@ -57,26 +57,6 @@
230.11 public static final String CREDENTIALS =
230.12 "jmx.remote.credentials";
230.13
230.14 - /**
230.15 - * <p>Name of the attribute that specifies whether to use the
230.16 - * {@linkplain javax.management.event Event Service} to handle
230.17 - * notifications for this connector. The value associated with
230.18 - * this attribute, if any, is a String, which must be equal,
230.19 - * ignoring case, to {@code "true"} or {@code "false"}.</p>
230.20 - *
230.21 - * <p>Not all connectors will understand this attribute, but the
230.22 - * standard {@linkplain javax.management.remote.rmi.RMIConnector
230.23 - * RMI Connector} does.</p>
230.24 - *
230.25 - * <p>If this attribute is not present, then the system property of the
230.26 - * same name (<code>{@value}</code>) is consulted. If that is not set
230.27 - * either, then the Event Service is not used.</p>
230.28 - *
230.29 - * @since 1.7
230.30 - */
230.31 - public static final String USE_EVENT_SERVICE =
230.32 - "jmx.remote.use.event.service";
230.33 -
230.34 /**
230.35 * <p>Establishes the connection to the connector server. This
230.36 * method is equivalent to {@link #connect(Map)
231.1 --- a/src/share/classes/javax/management/remote/JMXConnectorServer.java Mon Nov 23 10:04:47 2009 +0000
231.2 +++ b/src/share/classes/javax/management/remote/JMXConnectorServer.java Wed Nov 25 11:08:25 2009 -0800
231.3 @@ -26,22 +26,17 @@
231.4
231.5 package javax.management.remote;
231.6
231.7 -import com.sun.jmx.remote.util.EnvHelp;
231.8 import java.io.IOException;
231.9 import java.util.ArrayList;
231.10 import java.util.List;
231.11 import java.util.Map;
231.12
231.13 -import java.util.NoSuchElementException;
231.14 -import javax.management.ClientContext;
231.15 -import javax.management.MBeanInfo; // for javadoc
231.16 import javax.management.MBeanNotificationInfo;
231.17 import javax.management.MBeanRegistration;
231.18 import javax.management.MBeanServer;
231.19 import javax.management.Notification;
231.20 import javax.management.NotificationBroadcasterSupport;
231.21 import javax.management.ObjectName;
231.22 -import javax.management.event.EventClientDelegate;
231.23
231.24 /**
231.25 * <p>Superclass of every connector server. A connector server is
231.26 @@ -80,98 +75,6 @@
231.27 public static final String AUTHENTICATOR =
231.28 "jmx.remote.authenticator";
231.29
231.30 - /**
231.31 - * <p>Name of the attribute that specifies whether this connector
231.32 - * server can delegate notification handling to the
231.33 - * {@linkplain javax.management.event Event Service}.
231.34 - * The value associated with
231.35 - * this attribute, if any, is a String, which must be equal,
231.36 - * ignoring case, to {@code "true"} or {@code "false"}.</p>
231.37 - *
231.38 - * <p>Not all connector servers will understand this attribute, but the
231.39 - * standard {@linkplain javax.management.remote.rmi.RMIConnectorServer
231.40 - * RMI Connector Server} does.</p>
231.41 - *
231.42 - * <p>If this attribute is not present, then the system property of the
231.43 - * same name (<code>{@value}</code>) is consulted. If that is not set
231.44 - * either, then the Event Service is used if the connector server
231.45 - * supports it.</p>
231.46 - *
231.47 - * @since 1.7
231.48 - */
231.49 - public static final String DELEGATE_TO_EVENT_SERVICE =
231.50 - "jmx.remote.delegate.event.service";
231.51 -
231.52 - /**
231.53 - * <p>Name of the attribute that specifies whether this connector
231.54 - * server allows clients to communicate a context with each request.
231.55 - * The value associated with this attribute, if any, must be a string
231.56 - * that is equal to {@code "true"} or {@code "false"}, ignoring case.
231.57 - * If it is {@code "true"}, then the connector server will simulate
231.58 - * a namespace {@code jmx.context//}, as described in
231.59 - * {@link ClientContext#newContextForwarder}. This namespace is needed
231.60 - * for {@link ClientContext#withContext ClientContext.withContext} to
231.61 - * function correctly.</p>
231.62 - *
231.63 - * <p>Not all connector servers will understand this attribute, but the
231.64 - * standard {@linkplain javax.management.remote.rmi.RMIConnectorServer
231.65 - * RMI Connector Server} does. For a connector server that understands
231.66 - * this attribute, the default value is {@code "true"}.</p>
231.67 - *
231.68 - * @since 1.7
231.69 - */
231.70 - public static final String CONTEXT_FORWARDER =
231.71 - "jmx.remote.context.forwarder";
231.72 -
231.73 - /**
231.74 - * <p>Name of the attribute that specifies whether this connector server
231.75 - * localizes the descriptions in the {@link MBeanInfo} object returned by
231.76 - * {@link MBeanServer#getMBeanInfo MBeanServer.getMBeanInfo}, based on the
231.77 - * locale communicated by the client.</p>
231.78 - *
231.79 - * <p>The value associated with this attribute, if any, must be a string
231.80 - * that is equal to {@code "true"} or {@code "false"}, ignoring case.
231.81 - * If it is {@code "true"}, then the connector server will localize
231.82 - * {@code MBeanInfo} descriptions as specified in {@link
231.83 - * ClientContext#newLocalizeMBeanInfoForwarder}.</p>
231.84 - *
231.85 - * <p>Not all connector servers will understand this attribute, but the
231.86 - * standard {@linkplain javax.management.remote.rmi.RMIConnectorServer
231.87 - * RMI Connector Server} does. For a connector server that understands
231.88 - * this attribute, the default value is {@code "false"}.</p>
231.89 - *
231.90 - * <p>Because localization requires the client to be able to communicate
231.91 - * its locale, it does not make sense to specify this attribute as
231.92 - * {@code "true"} if {@link #CONTEXT_FORWARDER} is not also {@code "true"}.
231.93 - * For a connector server that understands these attributes, specifying
231.94 - * this inconsistent combination will result in an {@link
231.95 - * IllegalArgumentException}.</p>
231.96 - *
231.97 - * @since 1.7
231.98 - */
231.99 - public static final String LOCALIZE_MBEAN_INFO_FORWARDER =
231.100 - "jmx.remote.localize.mbean.info";
231.101 -
231.102 - /**
231.103 - * <p>Name of the attribute that specifies whether this connector
231.104 - * server simulates the existence of the {@link EventClientDelegate}
231.105 - * MBean. The value associated with this attribute, if any, must
231.106 - * be a string that is equal to {@code "true"} or {@code "false"},
231.107 - * ignoring case. If it is {@code "true"}, then the connector server
231.108 - * will simulate an EventClientDelegate MBean, as described in {@link
231.109 - * EventClientDelegate#newForwarder}. This MBean is needed for {@link
231.110 - * javax.management.event.EventClient EventClient} to function correctly.</p>
231.111 - *
231.112 - * <p>Not all connector servers will understand this attribute, but the
231.113 - * standard {@linkplain javax.management.remote.rmi.RMIConnectorServer
231.114 - * RMI Connector Server} does. For a connector server that understands
231.115 - * this attribute, the default value is {@code "true"}.</p>
231.116 - *
231.117 - * @since 1.7
231.118 - */
231.119 - public static final String EVENT_CLIENT_DELEGATE_FORWARDER =
231.120 - "jmx.remote.event.client.delegate.forwarder";
231.121 -
231.122 /**
231.123 * <p>Constructs a connector server that will be registered as an
231.124 * MBean in the MBean server it is attached to. This constructor
231.125 @@ -194,322 +97,27 @@
231.126 * to an MBean server by being registered in it.
231.127 */
231.128 public JMXConnectorServer(MBeanServer mbeanServer) {
231.129 - insertUserMBeanServer(mbeanServer);
231.130 + this.mbeanServer = mbeanServer;
231.131 }
231.132
231.133 /**
231.134 * <p>Returns the MBean server that this connector server is
231.135 - * attached to, or the first in a chain of user-added
231.136 - * {@link MBeanServerForwarder}s, if any.</p>
231.137 + * attached to.</p>
231.138 *
231.139 * @return the MBean server that this connector server is attached
231.140 * to, or null if it is not yet attached to an MBean server.
231.141 - *
231.142 - * @see #setMBeanServerForwarder
231.143 - * @see #getSystemMBeanServerForwarder
231.144 */
231.145 public synchronized MBeanServer getMBeanServer() {
231.146 - return userMBeanServer;
231.147 + return mbeanServer;
231.148 }
231.149
231.150 - public synchronized void setMBeanServerForwarder(MBeanServerForwarder mbsf) {
231.151 + public synchronized void setMBeanServerForwarder(MBeanServerForwarder mbsf)
231.152 + {
231.153 if (mbsf == null)
231.154 throw new IllegalArgumentException("Invalid null argument: mbsf");
231.155
231.156 - if (userMBeanServer != null)
231.157 - mbsf.setMBeanServer(userMBeanServer);
231.158 - insertUserMBeanServer(mbsf);
231.159 - }
231.160 -
231.161 - /**
231.162 - * <p>Remove a forwarder from the chain of forwarders. The forwarder can
231.163 - * be in the system chain or the user chain. On successful return from
231.164 - * this method, the first occurrence in the chain of an object that is
231.165 - * {@linkplain Object#equals equal} to {@code mbsf} will have been
231.166 - * removed.</p>
231.167 - *
231.168 - * @param mbsf the forwarder to remove
231.169 - *
231.170 - * @throws NoSuchElementException if there is no occurrence of {@code mbsf}
231.171 - * in the chain.
231.172 - * @throws IllegalArgumentException if {@code mbsf} is null or is the
231.173 - * {@linkplain #getSystemMBeanServerForwarder() system forwarder}.
231.174 - *
231.175 - * @since 1.7
231.176 - */
231.177 - public synchronized void removeMBeanServerForwarder(MBeanServerForwarder mbsf) {
231.178 - if (mbsf == null)
231.179 - throw new IllegalArgumentException("Invalid null argument: mbsf");
231.180 - if (systemMBeanServerForwarder.equals(mbsf))
231.181 - throw new IllegalArgumentException("Cannot remove system forwarder");
231.182 -
231.183 - MBeanServerForwarder prev = systemMBeanServerForwarder;
231.184 - MBeanServer curr;
231.185 - while (true) {
231.186 - curr = prev.getMBeanServer();
231.187 - if (mbsf.equals(curr))
231.188 - break;
231.189 - if (curr instanceof MBeanServerForwarder)
231.190 - prev = (MBeanServerForwarder) curr;
231.191 - else
231.192 - throw new NoSuchElementException("MBeanServerForwarder not in chain");
231.193 - }
231.194 - MBeanServer next = mbsf.getMBeanServer();
231.195 - prev.setMBeanServer(next);
231.196 - if (userMBeanServer == mbsf)
231.197 - userMBeanServer = next;
231.198 - }
231.199 -
231.200 - /*
231.201 - * Set userMBeanServer to mbs and arrange for the end of the chain of
231.202 - * system MBeanServerForwarders to point to it. See the comment before
231.203 - * the systemMBeanServer and userMBeanServer field declarations.
231.204 - */
231.205 - private void insertUserMBeanServer(MBeanServer mbs) {
231.206 - MBeanServerForwarder lastSystemMBSF = systemMBeanServerForwarder;
231.207 - while (true) {
231.208 - MBeanServer mbsi = lastSystemMBSF.getMBeanServer();
231.209 - if (mbsi == userMBeanServer)
231.210 - break;
231.211 - lastSystemMBSF = (MBeanServerForwarder) mbsi;
231.212 - }
231.213 - userMBeanServer = mbs;
231.214 - lastSystemMBSF.setMBeanServer(mbs);
231.215 - }
231.216 -
231.217 - /**
231.218 - * <p>Returns the first item in the chain of system and then user
231.219 - * forwarders. There is a chain of {@link MBeanServerForwarder}s between
231.220 - * a {@code JMXConnectorServer} and its {@code MBeanServer}. This chain
231.221 - * consists of two sub-chains: first the <em>system chain</em> and then
231.222 - * the <em>user chain</em>. Incoming requests are given to the first
231.223 - * forwarder in the system chain. Each forwarder can handle a request
231.224 - * itself, or more usually forward it to the next forwarder, perhaps with
231.225 - * some extra behavior such as logging or security checking before or after
231.226 - * the forwarding. The last forwarder in the system chain is followed by
231.227 - * the first forwarder in the user chain.</p>
231.228 - *
231.229 - * <p>The object returned by this method is the first forwarder in the
231.230 - * system chain. For a given {@code JMXConnectorServer}, this method
231.231 - * always returns the same object, which simply forwards every request
231.232 - * to the next object in the chain.</p>
231.233 - *
231.234 - * <p>Not all connector servers support a system chain of forwarders,
231.235 - * although the standard {@linkplain
231.236 - * javax.management.remote.rmi.RMIConnectorServer RMI connector
231.237 - * server} does. For those that do not, this method will throw {@code
231.238 - * UnsupportedOperationException}. All
231.239 - * connector servers do support a user chain of forwarders.</p>
231.240 - *
231.241 - * <p>The <em>system chain</em> is usually defined by a
231.242 - * connector server based on the environment Map; see {@link
231.243 - * JMXConnectorServerFactory#newJMXConnectorServer
231.244 - * JMXConnectorServerFactory.newJMXConnectorServer}. Allowing
231.245 - * the connector server to define its forwarders in this way
231.246 - * ensures that they are in the correct order - some forwarders
231.247 - * need to be inserted before others for correct behavior. It is
231.248 - * possible to modify the system chain, for example using {@code
231.249 - * connectorServer.getSystemMBeanServerForwarder().setMBeanServer(mbsf)} or
231.250 - * {@link #removeMBeanServerForwarder removeMBeanServerForwarder}, but in
231.251 - * that case the system chain is no longer guaranteed to be correct.</p>
231.252 - *
231.253 - * <p>The <em>user chain</em> is defined by calling {@link
231.254 - * #setMBeanServerForwarder setMBeanServerForwarder} to insert forwarders
231.255 - * at the head of the user chain.</p>
231.256 - *
231.257 - * <p>This code illustrates how the chains can be traversed:</p>
231.258 - *
231.259 - * <pre>
231.260 - * JMXConnectorServer cs;
231.261 - * System.out.println("system chain:");
231.262 - * MBeanServer mbs = cs.getSystemMBeanServerForwarder();
231.263 - * while (true) {
231.264 - * if (mbs == cs.getMBeanServer())
231.265 - * System.out.println("user chain:");
231.266 - * if (!(mbs instanceof MBeanServerForwarder))
231.267 - * break;
231.268 - * MBeanServerForwarder mbsf = (MBeanServerForwarder) mbs;
231.269 - * System.out.println("--forwarder: " + mbsf);
231.270 - * mbs = mbsf.getMBeanServer();
231.271 - * }
231.272 - * System.out.println("--MBean Server");
231.273 - * </pre>
231.274 - *
231.275 - * <h4>Note for connector server implementors</h4>
231.276 - *
231.277 - * <p>Existing connector server implementations can be updated to support
231.278 - * a system chain of forwarders as follows:</p>
231.279 - *
231.280 - * <ul>
231.281 - * <li><p>Override the {@link #supportsSystemMBeanServerForwarder()}
231.282 - * method so that it returns true.</p>
231.283 - *
231.284 - * <li><p>Call {@link #installStandardForwarders} from the constructor of
231.285 - * the connector server.</p>
231.286 - *
231.287 - * <li><p>Direct incoming requests to the result of {@link
231.288 - * #getSystemMBeanServerForwarder()} instead of the result of {@link
231.289 - * #getMBeanServer()}.</p>
231.290 - * </ul>
231.291 - *
231.292 - * @return the first item in the system chain of forwarders.
231.293 - *
231.294 - * @throws UnsupportedOperationException if {@link
231.295 - * #supportsSystemMBeanServerForwarder} returns false.
231.296 - *
231.297 - * @see #supportsSystemMBeanServerForwarder
231.298 - * @see #setMBeanServerForwarder
231.299 - *
231.300 - * @since 1.7
231.301 - */
231.302 - public MBeanServerForwarder getSystemMBeanServerForwarder() {
231.303 - if (!supportsSystemMBeanServerForwarder()) {
231.304 - throw new UnsupportedOperationException(
231.305 - "System MBeanServerForwarder not supported by this " +
231.306 - "connector server");
231.307 - }
231.308 - return systemMBeanServerForwarder;
231.309 - }
231.310 -
231.311 - /**
231.312 - * <p>Returns true if this connector server supports a system chain of
231.313 - * {@link MBeanServerForwarder}s. The default implementation of this
231.314 - * method returns false. Connector servers that do support the system
231.315 - * chain must override this method to return true.
231.316 - *
231.317 - * @return true if this connector server supports the system chain of
231.318 - * forwarders.
231.319 - *
231.320 - * @since 1.7
231.321 - */
231.322 - public boolean supportsSystemMBeanServerForwarder() {
231.323 - return false;
231.324 - }
231.325 -
231.326 - /**
231.327 - * Closes a client connection. If the connection is successfully closed,
231.328 - * the method {@link #connectionClosed} is called to notify interested parties.
231.329 - * <P>Not all connector servers support this method. For those that do, it
231.330 - * should be possible to cause a new client connection to fail before it
231.331 - * can be used, by calling this method from within a
231.332 - * {@link javax.management.NotificationListener}
231.333 - * when it receives a {@link JMXConnectionNotification#OPENED} notification.
231.334 - * This allows the owner of a connector server to deny certain connections,
231.335 - * typically based on the information in the connection id.
231.336 - * <P>The implementation of this method in {@code JMXConnectorServer} throws
231.337 - * {@code UnsupportedOperationException}. Subclasses can override this
231.338 - * method to support closing a specified client connection.
231.339 - *
231.340 - * @param connectionId the id of the client connection to be closed.
231.341 - * @throws IllegalStateException if the server is not started or is closed.
231.342 - * @throws IllegalArgumentException if {@code connectionId} is null or is
231.343 - * not the id of any open connection.
231.344 - * @throws java.io.IOException if an I/O error appears when closing the
231.345 - * connection.
231.346 - *
231.347 - * @since 1.7
231.348 - */
231.349 - public void closeConnection(String connectionId)
231.350 - throws IOException {
231.351 - throw new UnsupportedOperationException();
231.352 - }
231.353 -
231.354 - /**
231.355 - * <p>Install {@link MBeanServerForwarder}s in the system chain
231.356 - * based on the attributes in the given {@code Map}. A connector
231.357 - * server that {@linkplain #supportsSystemMBeanServerForwarder supports}
231.358 - * a system chain of {@code MBeanServerForwarder}s can call this method
231.359 - * to add forwarders to that chain based on the contents of {@code env}.
231.360 - * In order:</p>
231.361 - *
231.362 - * <ul>
231.363 - *
231.364 - * <li>If {@link #EVENT_CLIENT_DELEGATE_FORWARDER} is absent, or is
231.365 - * present with the value {@code "true"}, then a forwarder
231.366 - * equivalent to {@link EventClientDelegate#newForwarder
231.367 - * EventClientDelegate.newForwarder}{@code (sysMBSF.getMBeanServer(),
231.368 - * sysMBSF)} is inserted at the start of the system chain,
231.369 - * where {@code sysMBSF} is the object returned by {@link
231.370 - * #getSystemMBeanServerForwarder()}. </li>
231.371 - *
231.372 - * <li>If {@link #LOCALIZE_MBEAN_INFO_FORWARDER} is present with the
231.373 - * value {@code "true"}, then a forwarder equivalent to
231.374 - * {@link ClientContext#newLocalizeMBeanInfoForwarder
231.375 - * ClientContext.newLocalizeMBeanInfoForwarder}{@code
231.376 - * (sysMBSF.getMBeanServer())} is inserted at the start of the system
231.377 - * chain.</li>
231.378 - *
231.379 - * <li>If {@link #CONTEXT_FORWARDER} is absent, or is present with
231.380 - * the value {@code "true"}, then a forwarder equivalent to
231.381 - * {@link ClientContext#newContextForwarder
231.382 - * ClientContext.newContextForwarder}{@code (sysMSBF.getMBeanServer(),
231.383 - * sysMBSF)} is inserted at the tart of the system chain.</li>
231.384 - *
231.385 - * </ul>
231.386 - *
231.387 - * <p>For {@code EVENT_CLIENT_DELEGATE_FORWARDER} and {@code
231.388 - * CONTEXT_FORWARDER}, if the attribute is absent from the {@code
231.389 - * Map} and a system property of the same name is defined, then
231.390 - * the value of the system property is used as if it were in the
231.391 - * {@code Map}.
231.392 - *
231.393 - * <p>Since each forwarder is inserted at the start of the chain,
231.394 - * the final order of the forwarders is the <b>reverse</b> of the order
231.395 - * above. This is important, because the {@code
231.396 - * LOCALIZE_MBEAN_INFO_FORWARDER} can only work if the {@code
231.397 - * CONTEXT_FORWARDER} has already installed the remote client's locale
231.398 - * in the {@linkplain ClientContext#getContext context} of the current
231.399 - * thread.</p>
231.400 - *
231.401 - * <p>Attributes in {@code env} that are not listed above are ignored
231.402 - * by this method.</p>
231.403 - *
231.404 - * @throws UnsupportedOperationException if {@link
231.405 - * #supportsSystemMBeanServerForwarder} is false.
231.406 - *
231.407 - * @throws IllegalArgumentException if the relevant attributes in {@code env} are
231.408 - * inconsistent, for example if {@link #LOCALIZE_MBEAN_INFO_FORWARDER} is
231.409 - * {@code "true"} but {@link #CONTEXT_FORWARDER} is {@code "false"}; or
231.410 - * if one of the attributes has an illegal value.
231.411 - *
231.412 - * @since 1.7
231.413 - */
231.414 - protected void installStandardForwarders(Map<String, ?> env) {
231.415 - MBeanServerForwarder sysMBSF = getSystemMBeanServerForwarder();
231.416 -
231.417 - // Remember that forwarders must be added in reverse order!
231.418 -
231.419 - boolean ecd = EnvHelp.computeBooleanFromString(
231.420 - env, EVENT_CLIENT_DELEGATE_FORWARDER, false, true);
231.421 - boolean localize = EnvHelp.computeBooleanFromString(
231.422 - env, LOCALIZE_MBEAN_INFO_FORWARDER, false, false);
231.423 - boolean context = EnvHelp.computeBooleanFromString(
231.424 - env, CONTEXT_FORWARDER, false, true);
231.425 -
231.426 - if (localize && !context) {
231.427 - throw new IllegalArgumentException(
231.428 - "Inconsistent environment parameters: " +
231.429 - LOCALIZE_MBEAN_INFO_FORWARDER + "=\"true\" requires " +
231.430 - CONTEXT_FORWARDER + "=\"true\"");
231.431 - }
231.432 -
231.433 - if (ecd) {
231.434 - MBeanServerForwarder mbsf = EventClientDelegate.newForwarder(
231.435 - sysMBSF.getMBeanServer(), sysMBSF);
231.436 - sysMBSF.setMBeanServer(mbsf);
231.437 - }
231.438 -
231.439 - if (localize) {
231.440 - MBeanServerForwarder mbsf = ClientContext.newLocalizeMBeanInfoForwarder(
231.441 - sysMBSF.getMBeanServer());
231.442 - sysMBSF.setMBeanServer(mbsf);
231.443 - }
231.444 -
231.445 - if (context) {
231.446 - MBeanServerForwarder mbsf = ClientContext.newContextForwarder(
231.447 - sysMBSF.getMBeanServer(), sysMBSF);
231.448 - sysMBSF.setMBeanServer(mbsf);
231.449 - }
231.450 + if (mbeanServer != null) mbsf.setMBeanServer(mbeanServer);
231.451 + mbeanServer = mbsf;
231.452 }
231.453
231.454 public String[] getConnectionIds() {
231.455 @@ -753,8 +361,8 @@
231.456 ObjectName name) {
231.457 if (mbs == null || name == null)
231.458 throw new NullPointerException("Null MBeanServer or ObjectName");
231.459 - if (userMBeanServer == null) {
231.460 - insertUserMBeanServer(mbs);
231.461 + if (mbeanServer == null) {
231.462 + mbeanServer = mbs;
231.463 myName = name;
231.464 }
231.465 return name;
231.466 @@ -788,53 +396,10 @@
231.467 myName = null;
231.468 }
231.469
231.470 - /*
231.471 - * Fields describing the chains of forwarders (MBeanServerForwarders).
231.472 - * In the general case, the forwarders look something like this:
231.473 - *
231.474 - * userMBeanServer
231.475 - * |
231.476 - * v
231.477 - * systemMBeanServerForwarder -> mbsf2 -> mbsf3 -> mbsf4 -> mbsf5 -> mbs
231.478 - *
231.479 - * Here, each mbsfi is an MBeanServerForwarder, and the arrows
231.480 - * illustrate its getMBeanServer() method. The last MBeanServerForwarder
231.481 - * can point to an MBeanServer that is not instanceof MBeanServerForwarder,
231.482 - * here mbs.
231.483 - *
231.484 - * The system chain is never empty because it always has at least
231.485 - * systemMBeanServerForwarder. Initially, the user chain can be empty if
231.486 - * this JMXConnectorServer was constructed without an MBeanServer. In
231.487 - * this case, userMBS will be null. If there is initially an MBeanServer,
231.488 - * userMBS will point to it.
231.489 - *
231.490 - * Whenever userMBS is changed, the system chain must be updated. Before
231.491 - * the update, the last forwarder in the system chain points to the old
231.492 - * value of userMBS (possibly null). It must be updated to point to
231.493 - * the new value. The invariant is that starting from systemMBSF and
231.494 - * repeatedly calling MBSF.getMBeanServer() you will end up at userMBS.
231.495 - * The implication is that you will not see any MBeanServer object on the
231.496 - * way that is not also an MBeanServerForwarder.
231.497 - *
231.498 - * The method insertUserMBeanServer contains the logic to change userMBS
231.499 - * and adjust the system chain appropriately.
231.500 - *
231.501 - * If userMBS is null and this JMXConnectorServer is registered in an
231.502 - * MBeanServer, then userMBS becomes that MBeanServer, and the system
231.503 - * chain must be updated as just described.
231.504 - *
231.505 - * When systemMBSF is updated, there is no effect on userMBS. The system
231.506 - * chain may contain forwarders even though the user chain is empty
231.507 - * (there is no MBeanServer). In that case an attempt to forward an
231.508 - * incoming request through the chain will fall off the end and fail with a
231.509 - * NullPointerException. Usually a connector server will refuse to start()
231.510 - * if it is not attached to an MBS, so this situation should not arise.
231.511 + /**
231.512 + * The MBeanServer used by this server to execute a client request.
231.513 */
231.514 -
231.515 - private MBeanServer userMBeanServer;
231.516 -
231.517 - private final MBeanServerForwarder systemMBeanServerForwarder =
231.518 - new IdentityMBeanServerForwarder();
231.519 + private MBeanServer mbeanServer = null;
231.520
231.521 /**
231.522 * The name used to registered this server in an MBeanServer.
231.523 @@ -842,7 +407,7 @@
231.524 */
231.525 private ObjectName myName;
231.526
231.527 - private List<String> connectionIds = new ArrayList<String>();
231.528 + private final List<String> connectionIds = new ArrayList<String>();
231.529
231.530 private static final int[] sequenceNumberLock = new int[0];
231.531 private static long sequenceNumber;
232.1 --- a/src/share/classes/javax/management/remote/JMXConnectorServerMBean.java Mon Nov 23 10:04:47 2009 +0000
232.2 +++ b/src/share/classes/javax/management/remote/JMXConnectorServerMBean.java Wed Nov 25 11:08:25 2009 -0800
232.3 @@ -130,18 +130,12 @@
232.4 * <code>MBeanServer</code>.</p>
232.5 * </ul>
232.6 *
232.7 - * <p>A connector server may support two chains of forwarders,
232.8 - * a system chain and a user chain. See {@link
232.9 - * JMXConnectorServer#getSystemMBeanServerForwarder} for details.</p>
232.10 - *
232.11 * @param mbsf the new <code>MBeanServerForwarder</code>.
232.12 *
232.13 * @exception IllegalArgumentException if the call to {@link
232.14 * MBeanServerForwarder#setMBeanServer mbsf.setMBeanServer} fails
232.15 * with <code>IllegalArgumentException</code>. This includes the
232.16 * case where <code>mbsf</code> is null.
232.17 - *
232.18 - * @see JMXConnectorServer#getSystemMBeanServerForwarder
232.19 */
232.20 public void setMBeanServerForwarder(MBeanServerForwarder mbsf);
232.21
233.1 --- a/src/share/classes/javax/management/remote/JMXServiceURL.java Mon Nov 23 10:04:47 2009 +0000
233.2 +++ b/src/share/classes/javax/management/remote/JMXServiceURL.java Wed Nov 25 11:08:25 2009 -0800
233.3 @@ -36,8 +36,6 @@
233.4 import java.net.UnknownHostException;
233.5 import java.util.BitSet;
233.6 import java.util.StringTokenizer;
233.7 -import javax.management.openmbean.CompositeData;
233.8 -import javax.management.openmbean.InvalidKeyException;
233.9
233.10 /**
233.11 * <p>The address of a JMX API connector server. Instances of this class
233.12 @@ -338,50 +336,6 @@
233.13 validate();
233.14 }
233.15
233.16 - /**
233.17 - * <p>Construct a {@code JMXServiceURL} instance from the given
233.18 - * {@code CompositeData}. The presence of this method means that
233.19 - * {@code JMXServiceURL} is <a href="../MXBean.html#reconstructible-def">
233.20 - * reconstructible</a> in MXBeans.</p>
233.21 - *
233.22 - * <p>(The effect of this method could have been obtained more simply
233.23 - * with a @{@link java.beans.ConstructorProperties ConstructorProperties}
233.24 - * annotation on the four-parameter {@linkplain #JMXServiceURL(
233.25 - * String, String, int, String) constructor}, but that would have meant
233.26 - * that this API could not be implemented on versions of the Java platform
233.27 - * that predated the introduction of that annotation.)</p>
233.28 - *
233.29 - * @param cd a {@code CompositeData} object that must contain items called
233.30 - * {@code protocol}, {@code host}, and {@code URLPath} of type {@code String}
233.31 - * and {@code port} of type {@code Integer}. Such an object will be produced
233.32 - * by the MXBean framework when <a
233.33 - * href="../MXBean.html#composite-map">mapping</a> a {@code JMXServiceURL}
233.34 - * instance to an Open Data value.
233.35 - *
233.36 - * @return a {@code JMXServiceURL} constructed with the protocol, host,
233.37 - * port, and URL path extracted from the given {@code CompositeData}.
233.38 - *
233.39 - * @throws MalformedURLException if the given {@code CompositeData} does
233.40 - * not contain all the required items with the required types or if the
233.41 - * resultant URL is syntactically incorrect.
233.42 - */
233.43 - public static JMXServiceURL from(CompositeData cd)
233.44 - throws MalformedURLException {
233.45 - try {
233.46 - String proto = (String) cd.get("protocol");
233.47 - String host = (String) cd.get("host");
233.48 - int port = (Integer) cd.get("port");
233.49 - String urlPath = (String) cd.get("URLPath");
233.50 - return new JMXServiceURL(proto, host, port, urlPath);
233.51 - } catch (RuntimeException e) {
233.52 - // Could be InvalidKeyException if the item is missing,
233.53 - // or ClassCastException if it is present but with the wrong type.
233.54 - MalformedURLException x = new MalformedURLException(e.getMessage());
233.55 - x.initCause(e);
233.56 - throw x;
233.57 - }
233.58 - }
233.59 -
233.60 private void validate() throws MalformedURLException {
233.61
233.62 // Check protocol
234.1 --- a/src/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java Mon Nov 23 10:04:47 2009 +0000
234.2 +++ b/src/share/classes/javax/management/remote/rmi/NoCallStackClassLoader.java Wed Nov 25 11:08:25 2009 -0800
234.3 @@ -225,4 +225,72 @@
234.4 (insert "\"")
234.5 (switch-to-buffer buf)))
234.6
234.7 +Alternatively, the following class reads a class file and outputs a string
234.8 +that can be used by the stringToBytes method above.
234.9 +
234.10 +import java.io.File;
234.11 +import java.io.FileInputStream;
234.12 +import java.io.IOException;
234.13 +
234.14 +public class BytesToString {
234.15 +
234.16 + public static void main(String[] args) throws IOException {
234.17 + File f = new File(args[0]);
234.18 + int len = (int)f.length();
234.19 + byte[] classBytes = new byte[len];
234.20 +
234.21 + FileInputStream in = new FileInputStream(args[0]);
234.22 + try {
234.23 + int pos = 0;
234.24 + for (;;) {
234.25 + int n = in.read(classBytes, pos, (len-pos));
234.26 + if (n < 0)
234.27 + throw new RuntimeException("class file changed??");
234.28 + pos += n;
234.29 + if (pos >= n)
234.30 + break;
234.31 + }
234.32 + } finally {
234.33 + in.close();
234.34 + }
234.35 +
234.36 + int pos = 0;
234.37 + boolean lastWasOctal = false;
234.38 + for (int i=0; i<len; i++) {
234.39 + int value = classBytes[i];
234.40 + if (value < 0)
234.41 + value += 256;
234.42 + String s = null;
234.43 + if (value == '\\')
234.44 + s = "\\\\";
234.45 + else if (value == '\"')
234.46 + s = "\\\"";
234.47 + else {
234.48 + if ((value >= 32 && value < 127) && ((!lastWasOctal ||
234.49 + (value < '0' || value > '7')))) {
234.50 + s = Character.toString((char)value);
234.51 + }
234.52 + }
234.53 + if (s == null) {
234.54 + s = "\\" + Integer.toString(value, 8);
234.55 + lastWasOctal = true;
234.56 + } else {
234.57 + lastWasOctal = false;
234.58 + }
234.59 + if (pos > 61) {
234.60 + System.out.print("\"");
234.61 + if (i<len)
234.62 + System.out.print("+");
234.63 + System.out.println();
234.64 + pos = 0;
234.65 + }
234.66 + if (pos == 0)
234.67 + System.out.print(" \"");
234.68 + System.out.print(s);
234.69 + pos += s.length();
234.70 + }
234.71 + System.out.println("\"");
234.72 + }
234.73 +}
234.74 +
234.75 */
235.1 --- a/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java Mon Nov 23 10:04:47 2009 +0000
235.2 +++ b/src/share/classes/javax/management/remote/rmi/RMIConnectionImpl.java Wed Nov 25 11:08:25 2009 -0800
235.3 @@ -25,12 +25,10 @@
235.4
235.5 package javax.management.remote.rmi;
235.6
235.7 -import com.sun.jmx.mbeanserver.Util;
235.8 import static com.sun.jmx.mbeanserver.Util.cast;
235.9 import com.sun.jmx.remote.internal.ServerCommunicatorAdmin;
235.10 import com.sun.jmx.remote.internal.ServerNotifForwarder;
235.11 import com.sun.jmx.remote.security.JMXSubjectDomainCombiner;
235.12 -import com.sun.jmx.remote.security.NotificationAccessController;
235.13 import com.sun.jmx.remote.security.SubjectDelegator;
235.14 import com.sun.jmx.remote.util.ClassLoaderWithRepository;
235.15 import com.sun.jmx.remote.util.ClassLogger;
235.16 @@ -38,7 +36,6 @@
235.17 import com.sun.jmx.remote.util.OrderClassLoaders;
235.18
235.19 import java.io.IOException;
235.20 -import java.lang.reflect.UndeclaredThrowableException;
235.21 import java.rmi.MarshalledObject;
235.22 import java.rmi.UnmarshalException;
235.23 import java.rmi.server.Unreferenced;
235.24 @@ -59,25 +56,18 @@
235.25 import javax.management.InstanceNotFoundException;
235.26 import javax.management.IntrospectionException;
235.27 import javax.management.InvalidAttributeValueException;
235.28 -import javax.management.JMX;
235.29 import javax.management.ListenerNotFoundException;
235.30 import javax.management.MBeanException;
235.31 import javax.management.MBeanInfo;
235.32 import javax.management.MBeanRegistrationException;
235.33 import javax.management.MBeanServer;
235.34 import javax.management.NotCompliantMBeanException;
235.35 -import javax.management.Notification;
235.36 import javax.management.NotificationFilter;
235.37 import javax.management.ObjectInstance;
235.38 import javax.management.ObjectName;
235.39 import javax.management.QueryExp;
235.40 import javax.management.ReflectionException;
235.41 import javax.management.RuntimeOperationsException;
235.42 -import javax.management.event.EventClientDelegate;
235.43 -import javax.management.event.EventClientDelegateMBean;
235.44 -import javax.management.event.EventClientNotFoundException;
235.45 -import javax.management.event.FetchingEventForwarder;
235.46 -import javax.management.namespace.JMXNamespaces;
235.47 import javax.management.remote.JMXServerErrorException;
235.48 import javax.management.remote.NotificationResult;
235.49 import javax.management.remote.TargetedNotification;
235.50 @@ -168,6 +158,17 @@
235.51 this.env = env;
235.52 }
235.53
235.54 + private synchronized ServerNotifForwarder getServerNotifFwd() {
235.55 + // Lazily created when first use. Mainly when
235.56 + // addNotificationListener is first called.
235.57 + if (serverNotifForwarder == null)
235.58 + serverNotifForwarder =
235.59 + new ServerNotifForwarder(mbeanServer,
235.60 + env,
235.61 + rmiServer.getNotifBuffer(),
235.62 + connectionId);
235.63 + return serverNotifForwarder;
235.64 + }
235.65
235.66 public String getConnectionId() throws IOException {
235.67 // We should call reqIncomming() here... shouldn't we?
235.68 @@ -178,7 +179,6 @@
235.69 final boolean debug = logger.debugOn();
235.70 final String idstr = (debug?"["+this.toString()+"]":null);
235.71
235.72 - final SubscriptionManager mgr;
235.73 synchronized (this) {
235.74 if (terminated) {
235.75 if (debug) logger.debug("close",idstr + " already terminated.");
235.76 @@ -193,12 +193,11 @@
235.77 serverCommunicatorAdmin.terminate();
235.78 }
235.79
235.80 - mgr = subscriptionManager;
235.81 - subscriptionManager = null;
235.82 + if (serverNotifForwarder != null) {
235.83 + serverNotifForwarder.terminate();
235.84 + }
235.85 }
235.86
235.87 - if (mgr != null) mgr.terminate();
235.88 -
235.89 rmiServer.clientClosed(this);
235.90
235.91 if (debug) logger.debug("close",idstr + " closed.");
235.92 @@ -997,7 +996,8 @@
235.93 // remove all registered listeners
235.94 for (int j=0; j<i; j++) {
235.95 try {
235.96 - doRemoveListener(names[j],ids[j]);
235.97 + getServerNotifFwd().removeNotificationListener(names[j],
235.98 + ids[j]);
235.99 } catch (Exception eee) {
235.100 // strange
235.101 }
235.102 @@ -1247,330 +1247,22 @@
235.103 final long csn = clientSequenceNumber;
235.104 final int mn = maxNotifications;
235.105 final long t = timeout;
235.106 -
235.107 - final PrivilegedExceptionAction<NotificationResult> action =
235.108 - new PrivilegedExceptionAction<NotificationResult>() {
235.109 - public NotificationResult run() throws IOException {
235.110 - return doFetchNotifs(csn, t, mn);
235.111 + PrivilegedAction<NotificationResult> action =
235.112 + new PrivilegedAction<NotificationResult>() {
235.113 + public NotificationResult run() {
235.114 + return getServerNotifFwd().fetchNotifs(csn, t, mn);
235.115 }
235.116 };
235.117 - try {
235.118 - if (acc == null)
235.119 - return action.run();
235.120 - else
235.121 - return AccessController.doPrivileged(action, acc);
235.122 - } catch (IOException x) {
235.123 - throw x;
235.124 - } catch (RuntimeException x) {
235.125 - throw x;
235.126 - } catch (Exception x) {
235.127 - // should not happen
235.128 - throw new UndeclaredThrowableException(x);
235.129 - }
235.130 -
235.131 + if (acc == null)
235.132 + return action.run();
235.133 + else
235.134 + return AccessController.doPrivileged(action, acc);
235.135 } finally {
235.136 serverCommunicatorAdmin.rspOutgoing();
235.137 }
235.138 }
235.139
235.140 /**
235.141 - * This is an abstraction class that let us use the legacy
235.142 - * ServerNotifForwarder and the new EventClientDelegateMBean
235.143 - * indifferently.
235.144 - **/
235.145 - private static interface SubscriptionManager {
235.146 - public void removeNotificationListener(ObjectName name, Integer id)
235.147 - throws InstanceNotFoundException, ListenerNotFoundException, IOException;
235.148 - public void removeNotificationListener(ObjectName name, Integer[] ids)
235.149 - throws Exception;
235.150 - public NotificationResult fetchNotifications(long csn, long timeout, int maxcount)
235.151 - throws IOException;
235.152 - public Integer addNotificationListener(ObjectName name, NotificationFilter filter)
235.153 - throws InstanceNotFoundException, IOException;
235.154 - public void terminate()
235.155 - throws IOException;
235.156 - }
235.157 -
235.158 - /**
235.159 - * A SubscriptionManager that uses a ServerNotifForwarder.
235.160 - **/
235.161 - private static class LegacySubscriptionManager implements SubscriptionManager {
235.162 - private final ServerNotifForwarder forwarder;
235.163 - LegacySubscriptionManager(ServerNotifForwarder forwarder) {
235.164 - this.forwarder = forwarder;
235.165 - }
235.166 -
235.167 - public void removeNotificationListener(ObjectName name, Integer id)
235.168 - throws InstanceNotFoundException, ListenerNotFoundException,
235.169 - IOException {
235.170 - if (!JMXNamespaces.getContainingNamespace(name).equals("")) {
235.171 - logger.debug("removeNotificationListener",
235.172 - "This connector server is not configured to support " +
235.173 - "forwarding of notification subscriptions to name spaces");
235.174 - throw new RuntimeOperationsException(
235.175 - new UnsupportedOperationException(
235.176 - "removeNotificationListener on name space MBeans. "));
235.177 - }
235.178 - forwarder.removeNotificationListener(name,id);
235.179 - }
235.180 -
235.181 - public void removeNotificationListener(ObjectName name, Integer[] ids)
235.182 - throws Exception {
235.183 - if (!JMXNamespaces.getContainingNamespace(name).equals("")) {
235.184 - logger.debug("removeNotificationListener",
235.185 - "This connector server is not configured to support " +
235.186 - "forwarding of notification subscriptions to name spaces");
235.187 - throw new RuntimeOperationsException(
235.188 - new UnsupportedOperationException(
235.189 - "removeNotificationListener on name space MBeans. "));
235.190 - }
235.191 - forwarder.removeNotificationListener(name,ids);
235.192 - }
235.193 -
235.194 - public NotificationResult fetchNotifications(long csn, long timeout, int maxcount) {
235.195 - return forwarder.fetchNotifs(csn,timeout,maxcount);
235.196 - }
235.197 -
235.198 - public Integer addNotificationListener(ObjectName name,
235.199 - NotificationFilter filter)
235.200 - throws InstanceNotFoundException, IOException {
235.201 - if (!JMXNamespaces.getContainingNamespace(name).equals("")) {
235.202 - logger.debug("addNotificationListener",
235.203 - "This connector server is not configured to support " +
235.204 - "forwarding of notification subscriptions to name spaces");
235.205 - throw new RuntimeOperationsException(
235.206 - new UnsupportedOperationException(
235.207 - "addNotificationListener on name space MBeans. "));
235.208 - }
235.209 - return forwarder.addNotificationListener(name,filter);
235.210 - }
235.211 -
235.212 - public void terminate() {
235.213 - forwarder.terminate();
235.214 - }
235.215 - }
235.216 -
235.217 - /**
235.218 - * A SubscriptionManager that uses an EventClientDelegateMBean.
235.219 - **/
235.220 - private static class EventSubscriptionManager
235.221 - implements SubscriptionManager {
235.222 - private final MBeanServer mbeanServer;
235.223 - private final EventClientDelegateMBean delegate;
235.224 - private final NotificationAccessController notifAC;
235.225 - private final boolean checkNotificationEmission;
235.226 - private final String clientId;
235.227 - private final String connectionId;
235.228 - private volatile String mbeanServerName;
235.229 -
235.230 - EventSubscriptionManager(
235.231 - MBeanServer mbeanServer,
235.232 - EventClientDelegateMBean delegate,
235.233 - Map<String, ?> env,
235.234 - String clientId,
235.235 - String connectionId) {
235.236 - this.mbeanServer = mbeanServer;
235.237 - this.delegate = delegate;
235.238 - this.notifAC = EnvHelp.getNotificationAccessController(env);
235.239 - this.checkNotificationEmission =
235.240 - EnvHelp.computeBooleanFromString(
235.241 - env, "jmx.remote.x.check.notification.emission", false);
235.242 - this.clientId = clientId;
235.243 - this.connectionId = connectionId;
235.244 - }
235.245 -
235.246 - private String mbeanServerName() {
235.247 - if (mbeanServerName != null) return mbeanServerName;
235.248 - else return (mbeanServerName = getMBeanServerName(mbeanServer));
235.249 - }
235.250 -
235.251 - @SuppressWarnings("serial") // no serialVersionUID
235.252 - private class AccessControlFilter implements NotificationFilter {
235.253 - private final NotificationFilter wrapped;
235.254 - private final ObjectName name;
235.255 -
235.256 - AccessControlFilter(ObjectName name, NotificationFilter wrapped) {
235.257 - this.name = name;
235.258 - this.wrapped = wrapped;
235.259 - }
235.260 -
235.261 - public boolean isNotificationEnabled(Notification notification) {
235.262 - try {
235.263 - if (checkNotificationEmission) {
235.264 - ServerNotifForwarder.checkMBeanPermission(
235.265 - mbeanServerName(), mbeanServer, name,
235.266 - "addNotificationListener");
235.267 - }
235.268 - notifAC.fetchNotification(
235.269 - connectionId, name, notification, getSubject());
235.270 - return (wrapped == null) ? true :
235.271 - wrapped.isNotificationEnabled(notification);
235.272 - } catch (InstanceNotFoundException e) {
235.273 - return false;
235.274 - } catch (SecurityException e) {
235.275 - return false;
235.276 - }
235.277 - }
235.278 -
235.279 - }
235.280 -
235.281 - public Integer addNotificationListener(
235.282 - ObjectName name, NotificationFilter filter)
235.283 - throws InstanceNotFoundException, IOException {
235.284 - if (notifAC != null) {
235.285 - notifAC.addNotificationListener(connectionId, name, getSubject());
235.286 - filter = new AccessControlFilter(name, filter);
235.287 - }
235.288 - try {
235.289 - return delegate.addListener(clientId,name,filter);
235.290 - } catch (EventClientNotFoundException x) {
235.291 - throw new IOException("Unknown clientId: "+clientId,x);
235.292 - }
235.293 - }
235.294 -
235.295 - public void removeNotificationListener(ObjectName name, Integer id)
235.296 - throws InstanceNotFoundException, ListenerNotFoundException,
235.297 - IOException {
235.298 - if (notifAC != null)
235.299 - notifAC.removeNotificationListener(connectionId, name, getSubject());
235.300 - try {
235.301 - delegate.removeListenerOrSubscriber(clientId, id);
235.302 - } catch (EventClientNotFoundException x) {
235.303 - throw new IOException("Unknown clientId: "+clientId,x);
235.304 - }
235.305 - }
235.306 -
235.307 - public void removeNotificationListener(ObjectName name, Integer[] ids)
235.308 - throws InstanceNotFoundException, ListenerNotFoundException,
235.309 - IOException {
235.310 - if (notifAC != null)
235.311 - notifAC.removeNotificationListener(connectionId, name, getSubject());
235.312 - try {
235.313 - for (Integer id : ids)
235.314 - delegate.removeListenerOrSubscriber(clientId, id);
235.315 - } catch (EventClientNotFoundException x) {
235.316 - throw new IOException("Unknown clientId: "+clientId,x);
235.317 - }
235.318 - }
235.319 -
235.320 - public NotificationResult fetchNotifications(long csn, long timeout,
235.321 - int maxcount)
235.322 - throws IOException {
235.323 - try {
235.324 - // For some reason the delegate doesn't accept a negative
235.325 - // sequence number. However legacy clients will always call
235.326 - // fetchNotifications with a negative sequence number, when
235.327 - // they call it for the first time.
235.328 - // In that case, we will use 0 instead.
235.329 - //
235.330 - return delegate.fetchNotifications(
235.331 - clientId, Math.max(csn, 0), maxcount, timeout);
235.332 - } catch (EventClientNotFoundException x) {
235.333 - throw new IOException("Unknown clientId: "+clientId,x);
235.334 - }
235.335 - }
235.336 -
235.337 - public void terminate()
235.338 - throws IOException {
235.339 - try {
235.340 - delegate.removeClient(clientId);
235.341 - } catch (EventClientNotFoundException x) {
235.342 - throw new IOException("Unknown clientId: "+clientId,x);
235.343 - }
235.344 - }
235.345 -
235.346 - private static Subject getSubject() {
235.347 - return Subject.getSubject(AccessController.getContext());
235.348 - }
235.349 - }
235.350 -
235.351 - /**
235.352 - * Creates a SubscriptionManager that uses either the legacy notifications
235.353 - * mechanism (ServerNotifForwarder) or the new event service
235.354 - * (EventClientDelegateMBean) depending on which option was passed in
235.355 - * the connector's map.
235.356 - **/
235.357 - private SubscriptionManager createSubscriptionManager()
235.358 - throws IOException {
235.359 - if (EnvHelp.delegateToEventService(env) &&
235.360 - mbeanServer.isRegistered(EventClientDelegate.OBJECT_NAME)) {
235.361 - final EventClientDelegateMBean mbean =
235.362 - JMX.newMBeanProxy(mbeanServer,
235.363 - EventClientDelegate.OBJECT_NAME,
235.364 - EventClientDelegateMBean.class);
235.365 - String clientId;
235.366 - try {
235.367 - clientId =
235.368 - mbean.addClient(
235.369 - FetchingEventForwarder.class.getName(),
235.370 - new Object[] {EnvHelp.getNotifBufferSize(env)},
235.371 - new String[] {int.class.getName()});
235.372 - } catch (Exception e) {
235.373 - if (e instanceof IOException)
235.374 - throw (IOException) e;
235.375 - else
235.376 - throw new IOException(e);
235.377 - }
235.378 -
235.379 - // we're going to call remove client...
235.380 - try {
235.381 - mbean.lease(clientId, Long.MAX_VALUE);
235.382 - } catch (EventClientNotFoundException x) {
235.383 - throw new IOException("Unknown clientId: "+clientId,x);
235.384 - }
235.385 - return new EventSubscriptionManager(mbeanServer, mbean, env,
235.386 - clientId, connectionId);
235.387 - } else {
235.388 - final ServerNotifForwarder serverNotifForwarder =
235.389 - new ServerNotifForwarder(mbeanServer,
235.390 - env,
235.391 - rmiServer.getNotifBuffer(),
235.392 - connectionId);
235.393 - return new LegacySubscriptionManager(serverNotifForwarder);
235.394 - }
235.395 - }
235.396 -
235.397 - /**
235.398 - * Lazy creation of a SubscriptionManager.
235.399 - **/
235.400 - private synchronized SubscriptionManager getSubscriptionManager()
235.401 - throws IOException {
235.402 - // Lazily created when first use. Mainly when
235.403 - // addNotificationListener is first called.
235.404 -
235.405 - if (subscriptionManager == null) {
235.406 - subscriptionManager = createSubscriptionManager();
235.407 - }
235.408 - return subscriptionManager;
235.409 - }
235.410 -
235.411 - // calls SubscriptionManager.
235.412 - private void doRemoveListener(ObjectName name, Integer id)
235.413 - throws InstanceNotFoundException, ListenerNotFoundException,
235.414 - IOException {
235.415 - getSubscriptionManager().removeNotificationListener(name,id);
235.416 - }
235.417 -
235.418 - // calls SubscriptionManager.
235.419 - private void doRemoveListener(ObjectName name, Integer[] ids)
235.420 - throws Exception {
235.421 - getSubscriptionManager().removeNotificationListener(name,ids);
235.422 - }
235.423 -
235.424 - // calls SubscriptionManager.
235.425 - private NotificationResult doFetchNotifs(long csn, long timeout, int maxcount)
235.426 - throws IOException {
235.427 - return getSubscriptionManager().fetchNotifications(csn, timeout, maxcount);
235.428 - }
235.429 -
235.430 - // calls SubscriptionManager.
235.431 - private Integer doAddListener(ObjectName name, NotificationFilter filter)
235.432 - throws InstanceNotFoundException, IOException {
235.433 - return getSubscriptionManager().addNotificationListener(name,filter);
235.434 - }
235.435 -
235.436 -
235.437 - /**
235.438 * <p>Returns a string representation of this object. In general,
235.439 * the <code>toString</code> method returns a string that
235.440 * "textually represents" this object. The result should be a
235.441 @@ -1787,8 +1479,9 @@
235.442 return null;
235.443
235.444 case ADD_NOTIFICATION_LISTENERS:
235.445 - return doAddListener((ObjectName)params[0],
235.446 - (NotificationFilter)params[1]);
235.447 + return getServerNotifFwd().addNotificationListener(
235.448 + (ObjectName)params[0],
235.449 + (NotificationFilter)params[1]);
235.450
235.451 case ADD_NOTIFICATION_LISTENER_OBJECTNAME:
235.452 mbeanServer.addNotificationListener((ObjectName)params[0],
235.453 @@ -1798,7 +1491,9 @@
235.454 return null;
235.455
235.456 case REMOVE_NOTIFICATION_LISTENER:
235.457 - doRemoveListener((ObjectName)params[0],(Integer[])params[1]);
235.458 + getServerNotifFwd().removeNotificationListener(
235.459 + (ObjectName)params[0],
235.460 + (Integer[])params[1]);
235.461 return null;
235.462
235.463 case REMOVE_NOTIFICATION_LISTENER_OBJECTNAME:
235.464 @@ -1909,15 +1604,6 @@
235.465 return e;
235.466 }
235.467
235.468 - private static String getMBeanServerName(final MBeanServer server) {
235.469 - final PrivilegedAction<String> action = new PrivilegedAction<String>() {
235.470 - public String run() {
235.471 - return Util.getMBeanServerSecurityName(server);
235.472 - }
235.473 - };
235.474 - return AccessController.doPrivileged(action);
235.475 - }
235.476 -
235.477 private static final Object[] NO_OBJECTS = new Object[0];
235.478 private static final String[] NO_STRINGS = new String[0];
235.479
235.480 @@ -2033,7 +1719,7 @@
235.481 // SERVER NOTIFICATION
235.482 //--------------------
235.483
235.484 - private SubscriptionManager subscriptionManager;
235.485 + private ServerNotifForwarder serverNotifForwarder;
235.486 private Map<String, ?> env;
235.487
235.488 // TRACES & DEBUG
236.1 --- a/src/share/classes/javax/management/remote/rmi/RMIConnector.java Mon Nov 23 10:04:47 2009 +0000
236.2 +++ b/src/share/classes/javax/management/remote/rmi/RMIConnector.java Wed Nov 25 11:08:25 2009 -0800
236.3 @@ -25,15 +25,12 @@
236.4
236.5 package javax.management.remote.rmi;
236.6
236.7 -import com.sun.jmx.event.DaemonThreadFactory;
236.8 -import com.sun.jmx.event.EventConnection;
236.9 -import com.sun.jmx.mbeanserver.PerThreadGroupPool;
236.10 import com.sun.jmx.mbeanserver.Util;
236.11 import com.sun.jmx.remote.internal.ClientCommunicatorAdmin;
236.12 import com.sun.jmx.remote.internal.ClientListenerInfo;
236.13 import com.sun.jmx.remote.internal.ClientNotifForwarder;
236.14 -import com.sun.jmx.remote.internal.ProxyInputStream;
236.15 import com.sun.jmx.remote.internal.ProxyRef;
236.16 +import com.sun.jmx.remote.internal.IIOPHelper;
236.17 import com.sun.jmx.remote.util.ClassLogger;
236.18 import com.sun.jmx.remote.util.EnvHelp;
236.19 import java.io.ByteArrayInputStream;
236.20 @@ -72,11 +69,6 @@
236.21 import java.util.Properties;
236.22 import java.util.Set;
236.23 import java.util.WeakHashMap;
236.24 -import java.util.concurrent.Executor;
236.25 -import java.util.concurrent.LinkedBlockingQueue;
236.26 -import java.util.concurrent.ThreadFactory;
236.27 -import java.util.concurrent.ThreadPoolExecutor;
236.28 -import java.util.concurrent.TimeUnit;
236.29 import javax.management.Attribute;
236.30 import javax.management.AttributeList;
236.31 import javax.management.AttributeNotFoundException;
236.32 @@ -84,7 +76,6 @@
236.33 import javax.management.InstanceNotFoundException;
236.34 import javax.management.IntrospectionException;
236.35 import javax.management.InvalidAttributeValueException;
236.36 -import javax.management.JMX;
236.37 import javax.management.ListenerNotFoundException;
236.38 import javax.management.MBeanException;
236.39 import javax.management.MBeanInfo;
236.40 @@ -102,8 +93,6 @@
236.41 import javax.management.ObjectName;
236.42 import javax.management.QueryExp;
236.43 import javax.management.ReflectionException;
236.44 -import javax.management.event.EventClient;
236.45 -import javax.management.event.EventClientDelegateMBean;
236.46 import javax.management.remote.JMXConnectionNotification;
236.47 import javax.management.remote.JMXConnector;
236.48 import javax.management.remote.JMXConnectorFactory;
236.49 @@ -112,12 +101,8 @@
236.50 import javax.management.remote.JMXAddressable;
236.51 import javax.naming.InitialContext;
236.52 import javax.naming.NamingException;
236.53 -import javax.rmi.CORBA.Stub;
236.54 -import javax.rmi.PortableRemoteObject;
236.55 import javax.rmi.ssl.SslRMIClientSocketFactory;
236.56 import javax.security.auth.Subject;
236.57 -import org.omg.CORBA.BAD_OPERATION;
236.58 -import org.omg.CORBA.ORB;
236.59 import sun.rmi.server.UnicastRef2;
236.60 import sun.rmi.transport.LiveRef;
236.61
236.62 @@ -224,6 +209,7 @@
236.63 *
236.64 * @return a String representation of this object.
236.65 **/
236.66 + @Override
236.67 public String toString() {
236.68 final StringBuilder b = new StringBuilder(this.getClass().getName());
236.69 b.append(":");
236.70 @@ -330,8 +316,6 @@
236.71 //
236.72 connectionId = getConnectionId();
236.73
236.74 - eventServiceEnabled = EnvHelp.eventServiceEnabled(env);
236.75 -
236.76 Notification connectedNotif =
236.77 new JMXConnectionNotification(JMXConnectionNotification.OPENED,
236.78 this,
236.79 @@ -341,8 +325,6 @@
236.80 null);
236.81 sendNotification(connectedNotif);
236.82
236.83 - // whether or not event service
236.84 -
236.85 if (tracing) logger.trace("connect",idstr + " done...");
236.86 } catch (IOException e) {
236.87 if (tracing)
236.88 @@ -400,38 +382,10 @@
236.89 }
236.90
236.91 rmbsc = new RemoteMBeanServerConnection(delegationSubject);
236.92 - if (eventServiceEnabled) {
236.93 - EventClientDelegateMBean ecd = JMX.newMBeanProxy(
236.94 - rmbsc, EventClientDelegateMBean.OBJECT_NAME,
236.95 - EventClientDelegateMBean.class);
236.96 - EventClient ec = new EventClient(ecd, null, defaultExecutor(), null,
236.97 - EventClient.DEFAULT_REQUESTED_LEASE_TIME);
236.98 -
236.99 - rmbsc = EventConnection.Factory.make(rmbsc, ec);
236.100 - ec.addEventClientListener(
236.101 - lostNotifListener, null, null);
236.102 - }
236.103 rmbscMap.put(delegationSubject, rmbsc);
236.104 return rmbsc;
236.105 }
236.106
236.107 - private static Executor defaultExecutor() {
236.108 - PerThreadGroupPool.Create<ThreadPoolExecutor> create =
236.109 - new PerThreadGroupPool.Create<ThreadPoolExecutor>() {
236.110 - public ThreadPoolExecutor createThreadPool(ThreadGroup group) {
236.111 - ThreadFactory daemonThreadFactory = new DaemonThreadFactory(
236.112 - "JMX RMIConnector listener dispatch %d");
236.113 - ThreadPoolExecutor executor = new ThreadPoolExecutor(
236.114 - 1, 10, 1, TimeUnit.SECONDS,
236.115 - new LinkedBlockingQueue<Runnable>(),
236.116 - daemonThreadFactory);
236.117 - executor.allowCoreThreadTimeOut(true);
236.118 - return executor;
236.119 - }
236.120 - };
236.121 - return listenerDispatchThreadPool.getThreadPoolExecutor(create);
236.122 - }
236.123 -
236.124 public void
236.125 addConnectionNotificationListener(NotificationListener listener,
236.126 NotificationFilter filter,
236.127 @@ -511,17 +465,6 @@
236.128 communicatorAdmin.terminate();
236.129 }
236.130
236.131 - // close all EventClient
236.132 - for (MBeanServerConnection rmbsc : rmbscMap.values()) {
236.133 - if (rmbsc instanceof EventConnection) {
236.134 - try {
236.135 - ((EventConnection)rmbsc).getEventClient().close();
236.136 - } catch (Exception e) {
236.137 - // OK
236.138 - }
236.139 - }
236.140 - }
236.141 -
236.142 if (rmiNotifClient != null) {
236.143 try {
236.144 rmiNotifClient.terminate();
236.145 @@ -660,8 +603,6 @@
236.146 private class RemoteMBeanServerConnection implements MBeanServerConnection {
236.147 private Subject delegationSubject;
236.148
236.149 - public EventClient eventClient = null;
236.150 -
236.151 public RemoteMBeanServerConnection() {
236.152 this(null);
236.153 }
236.154 @@ -1504,6 +1445,7 @@
236.155 super(period);
236.156 }
236.157
236.158 + @Override
236.159 public void gotIOException(IOException ioe) throws IOException {
236.160 if (ioe instanceof NoSuchObjectException) {
236.161 // need to restart
236.162 @@ -1747,12 +1689,12 @@
236.163 static RMIServer connectStub(RMIServer rmiServer,
236.164 Map<String, ?> environment)
236.165 throws IOException {
236.166 - if (rmiServer instanceof javax.rmi.CORBA.Stub) {
236.167 - javax.rmi.CORBA.Stub stub = (javax.rmi.CORBA.Stub) rmiServer;
236.168 + if (IIOPHelper.isStub(rmiServer)) {
236.169 try {
236.170 - stub._orb();
236.171 - } catch (BAD_OPERATION x) {
236.172 - stub.connect(resolveOrb(environment));
236.173 + IIOPHelper.getOrb(rmiServer);
236.174 + } catch (UnsupportedOperationException x) {
236.175 + // BAD_OPERATION
236.176 + IIOPHelper.connect(rmiServer, resolveOrb(environment));
236.177 }
236.178 }
236.179 return rmiServer;
236.180 @@ -1779,22 +1721,22 @@
236.181 * does not point to an {@link org.omg.CORBA.ORB ORB}.
236.182 * @exception IOException if the ORB initialization failed.
236.183 **/
236.184 - static ORB resolveOrb(Map<String, ?> environment)
236.185 + static Object resolveOrb(Map<String, ?> environment)
236.186 throws IOException {
236.187 if (environment != null) {
236.188 final Object orb = environment.get(EnvHelp.DEFAULT_ORB);
236.189 - if (orb != null && !(orb instanceof ORB))
236.190 + if (orb != null && !(IIOPHelper.isOrb(orb)))
236.191 throw new IllegalArgumentException(EnvHelp.DEFAULT_ORB +
236.192 " must be an instance of org.omg.CORBA.ORB.");
236.193 - if (orb != null) return (ORB)orb;
236.194 + if (orb != null) return orb;
236.195 }
236.196 - final ORB orb =
236.197 + final Object orb =
236.198 (RMIConnector.orb==null)?null:RMIConnector.orb.get();
236.199 if (orb != null) return orb;
236.200
236.201 - final ORB newOrb =
236.202 - ORB.init((String[])null, (Properties)null);
236.203 - RMIConnector.orb = new WeakReference<ORB>(newOrb);
236.204 + final Object newOrb =
236.205 + IIOPHelper.createOrb((String[])null, (Properties)null);
236.206 + RMIConnector.orb = new WeakReference<Object>(newOrb);
236.207 return newOrb;
236.208 }
236.209
236.210 @@ -1865,26 +1807,6 @@
236.211 terminated = false;
236.212
236.213 connectionBroadcaster = new NotificationBroadcasterSupport();
236.214 -
236.215 - lostNotifListener =
236.216 - new NotificationListener() {
236.217 - public void handleNotification(Notification n, Object hb) {
236.218 - if (n != null && EventClient.NOTIFS_LOST.equals(n.getType())) {
236.219 - Long lost = (Long)n.getUserData();
236.220 - final String msg =
236.221 - "May have lost up to " + lost +
236.222 - " notification" + (lost.longValue() == 1 ? "" : "s");
236.223 - sendNotification(new JMXConnectionNotification(
236.224 - JMXConnectionNotification.NOTIFS_LOST,
236.225 - RMIConnector.this,
236.226 - connectionId,
236.227 - clientNotifCounter++,
236.228 - msg,
236.229 - lost));
236.230 -
236.231 - }
236.232 - }
236.233 - };
236.234 }
236.235
236.236 //--------------------------------------------------------------------
236.237 @@ -1952,9 +1874,11 @@
236.238 return findRMIServerJNDI(path.substring(6,end), environment, isIiop);
236.239 else if (path.startsWith("/stub/"))
236.240 return findRMIServerJRMP(path.substring(6,end), environment, isIiop);
236.241 - else if (path.startsWith("/ior/"))
236.242 + else if (path.startsWith("/ior/")) {
236.243 + if (!IIOPHelper.isAvailable())
236.244 + throw new IOException("iiop protocol not available");
236.245 return findRMIServerIIOP(path.substring(5,end), environment, isIiop);
236.246 - else {
236.247 + } else {
236.248 final String msg = "URL path must begin with /jndi/ or /stub/ " +
236.249 "or /ior/: " + path;
236.250 throw new MalformedURLException(msg);
236.251 @@ -1996,8 +1920,7 @@
236.252
236.253 private static RMIServer narrowIIOPServer(Object objref) {
236.254 try {
236.255 - return (RMIServer)
236.256 - PortableRemoteObject.narrow(objref, RMIServer.class);
236.257 + return IIOPHelper.narrow(objref, RMIServer.class);
236.258 } catch (ClassCastException e) {
236.259 if (logger.traceOn())
236.260 logger.trace("narrowIIOPServer","Failed to narrow objref=" +
236.261 @@ -2009,10 +1932,9 @@
236.262
236.263 private RMIServer findRMIServerIIOP(String ior, Map<String, ?> env, boolean isIiop) {
236.264 // could forbid "rmi:" URL here -- but do we need to?
236.265 - final ORB orb = (ORB)
236.266 - env.get(EnvHelp.DEFAULT_ORB);
236.267 - final Object stub = orb.string_to_object(ior);
236.268 - return (RMIServer) PortableRemoteObject.narrow(stub, RMIServer.class);
236.269 + final Object orb = env.get(EnvHelp.DEFAULT_ORB);
236.270 + final Object stub = IIOPHelper.stringToObject(orb, ior);
236.271 + return IIOPHelper.narrow(stub, RMIServer.class);
236.272 }
236.273
236.274 private RMIServer findRMIServerJRMP(String base64, Map<String, ?> env, boolean isIiop)
236.275 @@ -2038,7 +1960,7 @@
236.276 } catch (ClassNotFoundException e) {
236.277 throw new MalformedURLException("Class not found: " + e);
236.278 }
236.279 - return (RMIServer) PortableRemoteObject.narrow(stub, RMIServer.class);
236.280 + return (RMIServer)stub;
236.281 }
236.282
236.283 private static final class ObjectInputStreamWithLoader
236.284 @@ -2279,9 +2201,9 @@
236.285 again, using reflection.
236.286
236.287 The strings below encode the following two Java classes,
236.288 - compiled using J2SE 1.4.2 with javac -g:none.
236.289 + compiled using javac -g:none.
236.290
236.291 - package com.sun.jmx.remote.internal;
236.292 + package com.sun.jmx.remote.protocol.iiop;
236.293
236.294 import org.omg.stub.javax.management.remote.rmi._RMIConnection_Stub;
236.295
236.296 @@ -2302,12 +2224,13 @@
236.297 }
236.298
236.299 public void _releaseReply(InputStream in) {
236.300 - PInputStream pis = (PInputStream) in;
236.301 - super._releaseReply(pis.getProxiedInputStream());
236.302 + if (in != null)
236.303 + in = ((PInputStream)in).getProxiedInputStream();
236.304 + super._releaseReply(in);
236.305 }
236.306 }
236.307
236.308 - package com.sun.jmx.remote.internal;
236.309 + package com.sun.jmx.remote.protocol.iiop;
236.310
236.311 public class PInputStream extends ProxyInputStream {
236.312 public PInputStream(org.omg.CORBA.portable.InputStream in) {
236.313 @@ -2326,49 +2249,52 @@
236.314
236.315 */
236.316 private static final String iiopConnectionStubClassName =
236.317 - "org.omg.stub.javax.management.remote.rmi._RMIConnection_Stub";
236.318 + "org.omg.stub.javax.management.remote.rmi._RMIConnection_Stub";
236.319 private static final String proxyStubClassName =
236.320 - "com.sun.jmx.remote.internal.ProxyStub";
236.321 + "com.sun.jmx.remote.protocol.iiop.ProxyStub";
236.322 + private static final String ProxyInputStreamClassName =
236.323 + "com.sun.jmx.remote.protocol.iiop.ProxyInputStream";
236.324 private static final String pInputStreamClassName =
236.325 - "com.sun.jmx.remote.internal.PInputStream";
236.326 + "com.sun.jmx.remote.protocol.iiop.PInputStream";
236.327 private static final Class<?> proxyStubClass;
236.328 static {
236.329 final String proxyStubByteCodeString =
236.330 - "\312\376\272\276\0\0\0.\0)\12\0\14\0\26\7\0\27\12\0\14\0\30\12"+
236.331 - "\0\2\0\31\7\0\32\12\0\5\0\33\12\0\5\0\34\12\0\5\0\35\12\0\2\0"+
236.332 - "\36\12\0\14\0\37\7\0\40\7\0!\1\0\6<init>\1\0\3()V\1\0\4Code\1"+
236.333 - "\0\7_invoke\1\0K(Lorg/omg/CORBA/portable/OutputStream;)Lorg/o"+
236.334 - "mg/CORBA/portable/InputStream;\1\0\12Exceptions\7\0\"\1\0\15_"+
236.335 - "releaseReply\1\0'(Lorg/omg/CORBA/portable/InputStream;)V\14\0"+
236.336 - "\15\0\16\1\0(com/sun/jmx/remote/internal/PInputStream\14\0\20"+
236.337 - "\0\21\14\0\15\0\25\1\0+org/omg/CORBA/portable/ApplicationExce"+
236.338 - "ption\14\0#\0$\14\0%\0&\14\0\15\0'\14\0(\0$\14\0\24\0\25\1\0%"+
236.339 - "com/sun/jmx/remote/internal/ProxyStub\1\0<org/omg/stub/javax/"+
236.340 - "management/remote/rmi/_RMIConnection_Stub\1\0)org/omg/CORBA/p"+
236.341 - "ortable/RemarshalException\1\0\16getInputStream\1\0&()Lorg/om"+
236.342 - "g/CORBA/portable/InputStream;\1\0\5getId\1\0\24()Ljava/lang/S"+
236.343 - "tring;\1\09(Ljava/lang/String;Lorg/omg/CORBA/portable/InputSt"+
236.344 - "ream;)V\1\0\25getProxiedInputStream\0!\0\13\0\14\0\0\0\0\0\3\0"+
236.345 - "\1\0\15\0\16\0\1\0\17\0\0\0\21\0\1\0\1\0\0\0\5*\267\0\1\261\0"+
236.346 - "\0\0\0\0\1\0\20\0\21\0\2\0\17\0\0\0;\0\4\0\4\0\0\0'\273\0\2Y*"+
236.347 - "+\267\0\3\267\0\4\260M\273\0\2Y,\266\0\6\267\0\4N\273\0\5Y,\266"+
236.348 - "\0\7-\267\0\10\277\0\1\0\0\0\14\0\15\0\5\0\0\0\22\0\0\0\6\0\2"+
236.349 - "\0\5\0\23\0\1\0\24\0\25\0\1\0\17\0\0\0\36\0\2\0\2\0\0\0\22+\306"+
236.350 - "\0\13+\300\0\2\266\0\11L*+\267\0\12\261\0\0\0\0\0\0";
236.351 + "\312\376\272\276\0\0\0\63\0+\12\0\14\0\30\7\0\31\12\0\14\0\32\12"+
236.352 + "\0\2\0\33\7\0\34\12\0\5\0\35\12\0\5\0\36\12\0\5\0\37\12\0\2\0 "+
236.353 + "\12\0\14\0!\7\0\"\7\0#\1\0\6<init>\1\0\3()V\1\0\4Code\1\0\7_in"+
236.354 + "voke\1\0K(Lorg/omg/CORBA/portable/OutputStream;)Lorg/omg/CORBA"+
236.355 + "/portable/InputStream;\1\0\15StackMapTable\7\0\34\1\0\12Except"+
236.356 + "ions\7\0$\1\0\15_releaseReply\1\0'(Lorg/omg/CORBA/portable/Inp"+
236.357 + "utStream;)V\14\0\15\0\16\1\0-com/sun/jmx/remote/protocol/iiop/"+
236.358 + "PInputStream\14\0\20\0\21\14\0\15\0\27\1\0+org/omg/CORBA/porta"+
236.359 + "ble/ApplicationException\14\0%\0&\14\0'\0(\14\0\15\0)\14\0*\0&"+
236.360 + "\14\0\26\0\27\1\0*com/sun/jmx/remote/protocol/iiop/ProxyStub\1"+
236.361 + "\0<org/omg/stub/javax/management/remote/rmi/_RMIConnection_Stu"+
236.362 + "b\1\0)org/omg/CORBA/portable/RemarshalException\1\0\16getInput"+
236.363 + "Stream\1\0&()Lorg/omg/CORBA/portable/InputStream;\1\0\5getId\1"+
236.364 + "\0\24()Ljava/lang/String;\1\09(Ljava/lang/String;Lorg/omg/CORB"+
236.365 + "A/portable/InputStream;)V\1\0\25getProxiedInputStream\0!\0\13\0"+
236.366 + "\14\0\0\0\0\0\3\0\1\0\15\0\16\0\1\0\17\0\0\0\21\0\1\0\1\0\0\0\5"+
236.367 + "*\267\0\1\261\0\0\0\0\0\1\0\20\0\21\0\2\0\17\0\0\0G\0\4\0\4\0\0"+
236.368 + "\0'\273\0\2Y*+\267\0\3\267\0\4\260M\273\0\2Y,\266\0\6\267\0\4N"+
236.369 + "\273\0\5Y,\266\0\7-\267\0\10\277\0\1\0\0\0\14\0\15\0\5\0\1\0\22"+
236.370 + "\0\0\0\6\0\1M\7\0\23\0\24\0\0\0\6\0\2\0\5\0\25\0\1\0\26\0\27\0"+
236.371 + "\1\0\17\0\0\0'\0\2\0\2\0\0\0\22+\306\0\13+\300\0\2\266\0\11L*+"+
236.372 + "\267\0\12\261\0\0\0\1\0\22\0\0\0\3\0\1\14\0\0";
236.373 final String pInputStreamByteCodeString =
236.374 - "\312\376\272\276\0\0\0.\0\36\12\0\7\0\17\11\0\6\0\20\12\0\21\0"+
236.375 - "\22\12\0\6\0\23\12\0\24\0\25\7\0\26\7\0\27\1\0\6<init>\1\0'(L"+
236.376 - "org/omg/CORBA/portable/InputStream;)V\1\0\4Code\1\0\10read_an"+
236.377 - "y\1\0\25()Lorg/omg/CORBA/Any;\1\0\12read_value\1\0)(Ljava/lan"+
236.378 - "g/Class;)Ljava/io/Serializable;\14\0\10\0\11\14\0\30\0\31\7\0"+
236.379 - "\32\14\0\13\0\14\14\0\33\0\34\7\0\35\14\0\15\0\16\1\0(com/sun"+
236.380 - "/jmx/remote/internal/PInputStream\1\0,com/sun/jmx/remote/inte"+
236.381 - "rnal/ProxyInputStream\1\0\2in\1\0$Lorg/omg/CORBA/portable/Inp"+
236.382 - "utStream;\1\0\"org/omg/CORBA/portable/InputStream\1\0\6narrow"+
236.383 - "\1\0*()Lorg/omg/CORBA_2_3/portable/InputStream;\1\0&org/omg/C"+
236.384 - "ORBA_2_3/portable/InputStream\0!\0\6\0\7\0\0\0\0\0\3\0\1\0\10"+
236.385 - "\0\11\0\1\0\12\0\0\0\22\0\2\0\2\0\0\0\6*+\267\0\1\261\0\0\0\0"+
236.386 - "\0\1\0\13\0\14\0\1\0\12\0\0\0\24\0\1\0\1\0\0\0\10*\264\0\2\266"+
236.387 + "\312\376\272\276\0\0\0\63\0\36\12\0\7\0\17\11\0\6\0\20\12\0\21"+
236.388 + "\0\22\12\0\6\0\23\12\0\24\0\25\7\0\26\7\0\27\1\0\6<init>\1\0'("+
236.389 + "Lorg/omg/CORBA/portable/InputStream;)V\1\0\4Code\1\0\10read_an"+
236.390 + "y\1\0\25()Lorg/omg/CORBA/Any;\1\0\12read_value\1\0)(Ljava/lang"+
236.391 + "/Class;)Ljava/io/Serializable;\14\0\10\0\11\14\0\30\0\31\7\0\32"+
236.392 + "\14\0\13\0\14\14\0\33\0\34\7\0\35\14\0\15\0\16\1\0-com/sun/jmx"+
236.393 + "/remote/protocol/iiop/PInputStream\1\0\61com/sun/jmx/remote/pr"+
236.394 + "otocol/iiop/ProxyInputStream\1\0\2in\1\0$Lorg/omg/CORBA/portab"+
236.395 + "le/InputStream;\1\0\"org/omg/CORBA/portable/InputStream\1\0\6n"+
236.396 + "arrow\1\0*()Lorg/omg/CORBA_2_3/portable/InputStream;\1\0&org/o"+
236.397 + "mg/CORBA_2_3/portable/InputStream\0!\0\6\0\7\0\0\0\0\0\3\0\1\0"+
236.398 + "\10\0\11\0\1\0\12\0\0\0\22\0\2\0\2\0\0\0\6*+\267\0\1\261\0\0\0"+
236.399 + "\0\0\1\0\13\0\14\0\1\0\12\0\0\0\24\0\1\0\1\0\0\0\10*\264\0\2\266"+
236.400 "\0\3\260\0\0\0\0\0\1\0\15\0\16\0\1\0\12\0\0\0\25\0\2\0\2\0\0\0"+
236.401 "\11*\266\0\4+\266\0\5\260\0\0\0\0\0\0";
236.402 final byte[] proxyStubByteCode =
236.403 @@ -2379,12 +2305,12 @@
236.404 final byte[][] byteCodes = {proxyStubByteCode, pInputStreamByteCode};
236.405 final String[] otherClassNames = {
236.406 iiopConnectionStubClassName,
236.407 - ProxyInputStream.class.getName(),
236.408 + ProxyInputStreamClassName,
236.409 };
236.410 - PrivilegedExceptionAction<Class<?>> action =
236.411 + if (IIOPHelper.isAvailable()) {
236.412 + PrivilegedExceptionAction<Class<?>> action =
236.413 new PrivilegedExceptionAction<Class<?>>() {
236.414 - public Class<?> run() throws Exception {
236.415 -
236.416 + public Class<?> run() throws Exception {
236.417 Class thisClass = RMIConnector.class;
236.418 ClassLoader thisLoader = thisClass.getClassLoader();
236.419 ProtectionDomain thisProtectionDomain =
236.420 @@ -2396,24 +2322,27 @@
236.421 thisLoader,
236.422 thisProtectionDomain);
236.423 return cl.loadClass(proxyStubClassName);
236.424 + }
236.425 + };
236.426 + Class<?> stubClass;
236.427 + try {
236.428 + stubClass = AccessController.doPrivileged(action);
236.429 + } catch (Exception e) {
236.430 + logger.error("<clinit>",
236.431 + "Unexpected exception making shadow IIOP stub class: "+e);
236.432 + logger.debug("<clinit>",e);
236.433 + stubClass = null;
236.434 }
236.435 - };
236.436 - Class<?> stubClass;
236.437 - try {
236.438 - stubClass = AccessController.doPrivileged(action);
236.439 - } catch (Exception e) {
236.440 - logger.error("<clinit>",
236.441 - "Unexpected exception making shadow IIOP stub class: "+e);
236.442 - logger.debug("<clinit>",e);
236.443 - stubClass = null;
236.444 + proxyStubClass = stubClass;
236.445 + } else {
236.446 + proxyStubClass = null;
236.447 }
236.448 - proxyStubClass = stubClass;
236.449 }
236.450
236.451 - private static RMIConnection shadowIiopStub(Stub stub)
236.452 + private static RMIConnection shadowIiopStub(Object stub)
236.453 throws InstantiationException, IllegalAccessException {
236.454 - Stub proxyStub = (Stub) proxyStubClass.newInstance();
236.455 - proxyStub._set_delegate(stub._get_delegate());
236.456 + Object proxyStub = proxyStubClass.newInstance();
236.457 + IIOPHelper.setDelegate(proxyStub, IIOPHelper.getDelegate(stub));
236.458 return (RMIConnection) proxyStub;
236.459 }
236.460
236.461 @@ -2427,7 +2356,7 @@
236.462 if (c.getClass() == rmiConnectionImplStubClass)
236.463 return shadowJrmpStub((RemoteObject) c);
236.464 if (c.getClass().getName().equals(iiopConnectionStubClassName))
236.465 - return shadowIiopStub((Stub) c);
236.466 + return shadowIiopStub(c);
236.467 logger.trace("getConnection",
236.468 "Did not wrap " + c.getClass() + " to foil " +
236.469 "stack search for classes: class loading semantics " +
236.470 @@ -2609,16 +2538,11 @@
236.471
236.472 private transient ClientCommunicatorAdmin communicatorAdmin;
236.473
236.474 - private boolean eventServiceEnabled;
236.475 -// private transient EventRelay eventRelay;
236.476 -
236.477 - private transient NotificationListener lostNotifListener;
236.478 -
236.479 /**
236.480 * A static WeakReference to an {@link org.omg.CORBA.ORB ORB} to
236.481 * connect unconnected stubs.
236.482 **/
236.483 - private static volatile WeakReference<ORB> orb = null;
236.484 + private static volatile WeakReference<Object> orb = null;
236.485
236.486 // TRACES & DEBUG
236.487 //---------------
236.488 @@ -2632,7 +2556,4 @@
236.489 private static String strings(final String[] strs) {
236.490 return objects(strs);
236.491 }
236.492 -
236.493 - private static final PerThreadGroupPool<ThreadPoolExecutor> listenerDispatchThreadPool =
236.494 - PerThreadGroupPool.make();
236.495 }
237.1 --- a/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java Mon Nov 23 10:04:47 2009 +0000
237.2 +++ b/src/share/classes/javax/management/remote/rmi/RMIConnectorServer.java Wed Nov 25 11:08:25 2009 -0800
237.3 @@ -27,6 +27,7 @@
237.4
237.5
237.6 import com.sun.jmx.remote.security.MBeanServerFileAccessController;
237.7 +import com.sun.jmx.remote.internal.IIOPHelper;
237.8 import com.sun.jmx.remote.util.ClassLogger;
237.9 import com.sun.jmx.remote.util.EnvHelp;
237.10
237.11 @@ -230,8 +231,6 @@
237.12
237.13 this.address = url;
237.14 this.rmiServerImpl = rmiServerImpl;
237.15 -
237.16 - installStandardForwarders(this.attributes);
237.17 }
237.18
237.19 /**
237.20 @@ -383,7 +382,7 @@
237.21 try {
237.22 if (tracing) logger.trace("start", "setting default class loader");
237.23 defaultClassLoader = EnvHelp.resolveServerClassLoader(
237.24 - attributes, getSystemMBeanServerForwarder());
237.25 + attributes, getMBeanServer());
237.26 } catch (InstanceNotFoundException infc) {
237.27 IllegalArgumentException x = new
237.28 IllegalArgumentException("ClassLoader not found: "+infc);
237.29 @@ -398,7 +397,7 @@
237.30 else
237.31 rmiServer = newServer();
237.32
237.33 - rmiServer.setMBeanServer(getSystemMBeanServerForwarder());
237.34 + rmiServer.setMBeanServer(getMBeanServer());
237.35 rmiServer.setDefaultClassLoader(defaultClassLoader);
237.36 rmiServer.setRMIConnectorServer(this);
237.37 rmiServer.export();
237.38 @@ -592,34 +591,12 @@
237.39 return Collections.unmodifiableMap(map);
237.40 }
237.41
237.42 - /**
237.43 - * {@inheritDoc}
237.44 - * @return true, since this connector server does support a system chain
237.45 - * of forwarders.
237.46 - */
237.47 @Override
237.48 - public boolean supportsSystemMBeanServerForwarder() {
237.49 - return true;
237.50 - }
237.51 -
237.52 - /**
237.53 - * {@inheritDoc}
237.54 - * <P>The {@code RMIConnectorServer} class does support closing a specified
237.55 - * client connection.
237.56 - * @throws IllegalStateException if the server is not started or is closed.
237.57 - * @throws IllegalArgumentException if {@code connectionId} is null or is
237.58 - * not the id of any open connection.
237.59 - * @since 1.7
237.60 - */
237.61 - @Override
237.62 - public void closeConnection(String connectionId)
237.63 - throws IOException {
237.64 - if (isActive()) {
237.65 - rmiServerImpl.closeConnection(connectionId);
237.66 - } else {
237.67 - throw new IllegalStateException(
237.68 - "The server is not started or is closed.");
237.69 - }
237.70 + public synchronized
237.71 + void setMBeanServerForwarder(MBeanServerForwarder mbsf) {
237.72 + super.setMBeanServerForwarder(mbsf);
237.73 + if (rmiServerImpl != null)
237.74 + rmiServerImpl.setMBeanServer(getMBeanServer());
237.75 }
237.76
237.77 /* We repeat the definitions of connection{Opened,Closed,Failed}
237.78 @@ -698,7 +675,7 @@
237.79 final int port;
237.80
237.81 if (address == null) {
237.82 - if (rmiServer instanceof javax.rmi.CORBA.Stub)
237.83 + if (IIOPHelper.isStub(rmiServer))
237.84 protocol = "iiop";
237.85 else
237.86 protocol = "rmi";
237.87 @@ -736,7 +713,7 @@
237.88 **/
237.89 static String encodeStub(
237.90 RMIServer rmiServer, Map<String, ?> env) throws IOException {
237.91 - if (rmiServer instanceof javax.rmi.CORBA.Stub)
237.92 + if (IIOPHelper.isStub(rmiServer))
237.93 return "/ior/" + encodeIIOPStub(rmiServer, env);
237.94 else
237.95 return "/stub/" + encodeJRMPStub(rmiServer, env);
237.96 @@ -757,10 +734,9 @@
237.97 RMIServer rmiServer, Map<String, ?> env)
237.98 throws IOException {
237.99 try {
237.100 - javax.rmi.CORBA.Stub stub =
237.101 - (javax.rmi.CORBA.Stub) rmiServer;
237.102 - return stub._orb().object_to_string(stub);
237.103 - } catch (org.omg.CORBA.BAD_OPERATION x) {
237.104 + Object orb = IIOPHelper.getOrb(rmiServer);
237.105 + return IIOPHelper.objectToString(orb, rmiServer);
237.106 + } catch (RuntimeException x) {
237.107 throw newIOException(x.getMessage(), x);
237.108 }
237.109 }
238.1 --- a/src/share/classes/javax/management/remote/rmi/RMIIIOPServerImpl.java Mon Nov 23 10:04:47 2009 +0000
238.2 +++ b/src/share/classes/javax/management/remote/rmi/RMIIIOPServerImpl.java Wed Nov 25 11:08:25 2009 -0800
238.3 @@ -33,9 +33,10 @@
238.4 import java.security.PrivilegedExceptionAction;
238.5 import java.util.Map;
238.6 import java.util.Collections;
238.7 -import javax.rmi.PortableRemoteObject;
238.8 import javax.security.auth.Subject;
238.9
238.10 +import com.sun.jmx.remote.internal.IIOPHelper;
238.11 +
238.12 /**
238.13 * <p>An {@link RMIServerImpl} that is exported through IIOP and that
238.14 * creates client connections as RMI objects exported through IIOP.
238.15 @@ -65,7 +66,7 @@
238.16 }
238.17
238.18 protected void export() throws IOException {
238.19 - PortableRemoteObject.exportObject(this);
238.20 + IIOPHelper.exportObject(this);
238.21 }
238.22
238.23 protected String getProtocol() {
238.24 @@ -83,7 +84,7 @@
238.25 public Remote toStub() throws IOException {
238.26 // javax.rmi.CORBA.Stub stub =
238.27 // (javax.rmi.CORBA.Stub) PortableRemoteObject.toStub(this);
238.28 - final Remote stub = PortableRemoteObject.toStub(this);
238.29 + final Remote stub = IIOPHelper.toStub(this);
238.30 // java.lang.System.out.println("NON CONNECTED STUB " + stub);
238.31 // org.omg.CORBA.ORB orb =
238.32 // org.omg.CORBA.ORB.init((String[])null, (Properties)null);
238.33 @@ -117,12 +118,12 @@
238.34 RMIConnection client =
238.35 new RMIConnectionImpl(this, connectionId, getDefaultClassLoader(),
238.36 subject, env);
238.37 - PortableRemoteObject.exportObject(client);
238.38 + IIOPHelper.exportObject(client);
238.39 return client;
238.40 }
238.41
238.42 protected void closeClient(RMIConnection client) throws IOException {
238.43 - PortableRemoteObject.unexportObject(client);
238.44 + IIOPHelper.unexportObject(client);
238.45 }
238.46
238.47 /**
238.48 @@ -134,7 +135,7 @@
238.49 * server failed.
238.50 */
238.51 protected void closeServer() throws IOException {
238.52 - PortableRemoteObject.unexportObject(this);
238.53 + IIOPHelper.unexportObject(this);
238.54 }
238.55
238.56 @Override
239.1 --- a/src/share/classes/javax/management/remote/rmi/RMIServerImpl.java Mon Nov 23 10:04:47 2009 +0000
239.2 +++ b/src/share/classes/javax/management/remote/rmi/RMIServerImpl.java Wed Nov 25 11:08:25 2009 -0800
239.3 @@ -271,52 +271,6 @@
239.4 }
239.5
239.6 /**
239.7 - * Closes a client connection.
239.8 - * @param connectionId the id of the client connection to be closed.
239.9 - * @throws IllegalArgumentException if {@code connectionId} is null or is
239.10 - * not the id of any open connection.
239.11 - * @throws java.io.IOException if an I/O error appears when closing the
239.12 - * connection.
239.13 - *
239.14 - * @since 1.7
239.15 - */
239.16 - public void closeConnection(String connectionId)
239.17 - throws IOException {
239.18 - final boolean debug = logger.debugOn();
239.19 -
239.20 - if (debug) logger.trace("closeConnection","cconnectionId="+connectionId);
239.21 -
239.22 - if (connectionId == null)
239.23 - throw new IllegalArgumentException("Null connectionId.");
239.24 -
239.25 - RMIConnection client = null;
239.26 - synchronized (clientList) {
239.27 - dropDeadReferences();
239.28 - for (Iterator<WeakReference<RMIConnection>> it = clientList.iterator();
239.29 - it.hasNext(); ) {
239.30 - client = it.next().get();
239.31 - if (client != null && connectionId.equals(client.getConnectionId())) {
239.32 - it.remove();
239.33 - break;
239.34 - }
239.35 - }
239.36 - }
239.37 -
239.38 - if (client == null) {
239.39 - throw new IllegalArgumentException("Unknown id: "+connectionId);
239.40 - }
239.41 -
239.42 - if (debug) logger.trace("closeConnection", "closing client connection.");
239.43 - closeClient(client);
239.44 -
239.45 - if (debug) logger.trace("closeConnection", "sending notif");
239.46 - connServer.connectionClosed(connectionId,
239.47 - "Client connection closed", null);
239.48 -
239.49 - if (debug) logger.trace("closeConnection","done");
239.50 - }
239.51 -
239.52 - /**
239.53 * <p>Creates a new client connection. This method is called by
239.54 * the public method {@link #newClient(Object)}.</p>
239.55 *
240.1 --- a/src/share/classes/javax/print/attribute/standard/PrinterStateReasons.java Mon Nov 23 10:04:47 2009 +0000
240.2 +++ b/src/share/classes/javax/print/attribute/standard/PrinterStateReasons.java Wed Nov 25 11:08:25 2009 -0800
240.3 @@ -65,7 +65,7 @@
240.4 * PrinterStateReason PrinterStateReason} objects to an existing
240.5 * PrinterStateReasons object and remove them again. However, like class
240.6 * {@link java.util.HashMap java.util.HashMap}, class PrinterStateReasons is
240.7 - * bot multiple thread safe. If a PrinterStateReasons object will be used by
240.8 + * not multiple thread safe. If a PrinterStateReasons object will be used by
240.9 * multiple threads, be sure to synchronize its operations (e.g., using a
240.10 * synchronized map view obtained from class {@link java.util.Collections
240.11 * java.util.Collections}).
241.1 --- a/src/share/classes/javax/swing/JComponent.java Mon Nov 23 10:04:47 2009 +0000
241.2 +++ b/src/share/classes/javax/swing/JComponent.java Wed Nov 25 11:08:25 2009 -0800
241.3 @@ -795,7 +795,6 @@
241.4 * @see java.awt.Container#paint
241.5 */
241.6 protected void paintChildren(Graphics g) {
241.7 - boolean isJComponent;
241.8 Graphics sg = g;
241.9
241.10 synchronized(getTreeLock()) {
241.11 @@ -826,12 +825,21 @@
241.12 }
241.13 }
241.14 boolean printing = getFlag(IS_PRINTING);
241.15 + final Window window = SwingUtilities.getWindowAncestor(this);
241.16 + final boolean isWindowOpaque = window == null || window.isOpaque();
241.17 for (; i >= 0 ; i--) {
241.18 Component comp = getComponent(i);
241.19 - isJComponent = (comp instanceof JComponent);
241.20 - if (comp != null &&
241.21 - (isJComponent || isLightweightComponent(comp)) &&
241.22 - (comp.isVisible() == true)) {
241.23 + if (comp == null) {
241.24 + continue;
241.25 + }
241.26 +
241.27 + final boolean isJComponent = comp instanceof JComponent;
241.28 +
241.29 + // Enable painting of heavyweights in non-opaque windows.
241.30 + // See 6884960
241.31 + if ((!isWindowOpaque || isJComponent ||
241.32 + isLightweightComponent(comp)) && comp.isVisible())
241.33 + {
241.34 Rectangle cr;
241.35
241.36 cr = comp.getBounds(tmpRect);
241.37 @@ -887,6 +895,8 @@
241.38 }
241.39 }
241.40 } else {
241.41 + // The component is either lightweight, or
241.42 + // heavyweight in a non-opaque window
241.43 if (!printing) {
241.44 comp.paint(cg);
241.45 }
241.46 @@ -4868,7 +4878,9 @@
241.47 * @see #revalidate
241.48 * @see java.awt.Component#invalidate
241.49 * @see java.awt.Container#validate
241.50 - */
241.51 + * @see java.awt.Container#isValidateRoot
241.52 + */
241.53 + @Override
241.54 public boolean isValidateRoot() {
241.55 return false;
241.56 }
242.1 --- a/src/share/classes/javax/swing/JEditorPane.java Mon Nov 23 10:04:47 2009 +0000
242.2 +++ b/src/share/classes/javax/swing/JEditorPane.java Wed Nov 25 11:08:25 2009 -0800
242.3 @@ -1330,7 +1330,7 @@
242.4 */
242.5 public Dimension getPreferredSize() {
242.6 Dimension d = super.getPreferredSize();
242.7 - JViewport port = SwingUtilities2.getViewport(this);
242.8 + JViewport port = SwingUtilities.getParentViewport(this);
242.9 if (port != null) {
242.10 TextUI ui = getUI();
242.11 int prefWidth = d.width;
242.12 @@ -1452,7 +1452,7 @@
242.13 * match its own, false otherwise
242.14 */
242.15 public boolean getScrollableTracksViewportWidth() {
242.16 - JViewport port = SwingUtilities2.getViewport(this);
242.17 + JViewport port = SwingUtilities.getParentViewport(this);
242.18 if (port != null) {
242.19 TextUI ui = getUI();
242.20 int w = port.getWidth();
242.21 @@ -1474,7 +1474,7 @@
242.22 * false otherwise
242.23 */
242.24 public boolean getScrollableTracksViewportHeight() {
242.25 - JViewport port = SwingUtilities2.getViewport(this);
242.26 + JViewport port = SwingUtilities.getParentViewport(this);
242.27 if (port != null) {
242.28 TextUI ui = getUI();
242.29 int h = port.getHeight();
243.1 --- a/src/share/classes/javax/swing/JList.java Mon Nov 23 10:04:47 2009 +0000
243.2 +++ b/src/share/classes/javax/swing/JList.java Wed Nov 25 11:08:25 2009 -0800
243.3 @@ -2722,7 +2722,7 @@
243.4 getVisibleRowCount() <= 0) {
243.5 return true;
243.6 }
243.7 - JViewport port = SwingUtilities2.getViewport(this);
243.8 + JViewport port = SwingUtilities.getParentViewport(this);
243.9 if (port != null) {
243.10 return port.getWidth() > getPreferredSize().width;
243.11 }
243.12 @@ -2748,7 +2748,7 @@
243.13 getVisibleRowCount() <= 0) {
243.14 return true;
243.15 }
243.16 - JViewport port = SwingUtilities2.getViewport(this);
243.17 + JViewport port = SwingUtilities.getParentViewport(this);
243.18 if (port != null) {
243.19 return port.getHeight() > getPreferredSize().height;
243.20 }
244.1 --- a/src/share/classes/javax/swing/JRootPane.java Mon Nov 23 10:04:47 2009 +0000
244.2 +++ b/src/share/classes/javax/swing/JRootPane.java Wed Nov 25 11:08:25 2009 -0800
244.3 @@ -725,8 +725,10 @@
244.4 * because both classes override <code>isValidateRoot</code> to return true.
244.5 *
244.6 * @see JComponent#isValidateRoot
244.7 + * @see java.awt.Container#isValidateRoot
244.8 * @return true
244.9 */
244.10 + @Override
244.11 public boolean isValidateRoot() {
244.12 return true;
244.13 }
245.1 --- a/src/share/classes/javax/swing/JScrollPane.java Mon Nov 23 10:04:47 2009 +0000
245.2 +++ b/src/share/classes/javax/swing/JScrollPane.java Wed Nov 25 11:08:25 2009 -0800
245.3 @@ -453,10 +453,12 @@
245.4 * @see java.awt.Container#validate
245.5 * @see JComponent#revalidate
245.6 * @see JComponent#isValidateRoot
245.7 + * @see java.awt.Container#isValidateRoot
245.8 *
245.9 * @beaninfo
245.10 * hidden: true
245.11 */
245.12 + @Override
245.13 public boolean isValidateRoot() {
245.14 return true;
245.15 }
246.1 --- a/src/share/classes/javax/swing/JSplitPane.java Mon Nov 23 10:04:47 2009 +0000
246.2 +++ b/src/share/classes/javax/swing/JSplitPane.java Wed Nov 25 11:08:25 2009 -0800
246.3 @@ -947,10 +947,12 @@
246.4 *
246.5 * @return true
246.6 * @see JComponent#revalidate
246.7 + * @see java.awt.Container#isValidateRoot
246.8 *
246.9 * @beaninfo
246.10 * hidden: true
246.11 */
246.12 + @Override
246.13 public boolean isValidateRoot() {
246.14 return true;
246.15 }
247.1 --- a/src/share/classes/javax/swing/JTable.java Mon Nov 23 10:04:47 2009 +0000
247.2 +++ b/src/share/classes/javax/swing/JTable.java Wed Nov 25 11:08:25 2009 -0800
247.3 @@ -57,6 +57,7 @@
247.4 import sun.swing.SwingUtilities2.Section;
247.5 import static sun.swing.SwingUtilities2.Section.*;
247.6 import sun.swing.PrintingStatus;
247.7 +import sun.swing.SwingLazyValue;
247.8
247.9 /**
247.10 * The <code>JTable</code> is used to display and edit regular two-dimensional tables
247.11 @@ -718,7 +719,7 @@
247.12 * @see #addNotify
247.13 */
247.14 protected void configureEnclosingScrollPane() {
247.15 - JViewport port = SwingUtilities2.getViewport(this);
247.16 + JViewport port = SwingUtilities.getParentViewport(this);
247.17 if (port != null) {
247.18 Container gp = port.getParent();
247.19 if (gp instanceof JScrollPane) {
247.20 @@ -727,7 +728,8 @@
247.21 // example, the rowHeaderView of the scrollPane -
247.22 // an implementor of fixed columns might do this.
247.23 JViewport viewport = scrollPane.getViewport();
247.24 - if (viewport == null || viewport.getView() != this) {
247.25 + if (viewport == null ||
247.26 + SwingUtilities.getUnwrappedView(viewport) != this) {
247.27 return;
247.28 }
247.29 scrollPane.setColumnHeaderView(getTableHeader());
247.30 @@ -750,7 +752,7 @@
247.31 * from configureEnclosingScrollPane() and updateUI() in a safe manor.
247.32 */
247.33 private void configureEnclosingScrollPaneUI() {
247.34 - JViewport port = SwingUtilities2.getViewport(this);
247.35 + JViewport port = SwingUtilities.getParentViewport(this);
247.36 if (port != null) {
247.37 Container gp = port.getParent();
247.38 if (gp instanceof JScrollPane) {
247.39 @@ -759,7 +761,8 @@
247.40 // example, the rowHeaderView of the scrollPane -
247.41 // an implementor of fixed columns might do this.
247.42 JViewport viewport = scrollPane.getViewport();
247.43 - if (viewport == null || viewport.getView() != this) {
247.44 + if (viewport == null ||
247.45 + SwingUtilities.getUnwrappedView(viewport) != this) {
247.46 return;
247.47 }
247.48 // scrollPane.getViewport().setBackingStoreEnabled(true);
247.49 @@ -819,7 +822,7 @@
247.50 * @since 1.3
247.51 */
247.52 protected void unconfigureEnclosingScrollPane() {
247.53 - JViewport port = SwingUtilities2.getViewport(this);
247.54 + JViewport port = SwingUtilities.getParentViewport(this);
247.55 if (port != null) {
247.56 Container gp = port.getParent();
247.57 if (gp instanceof JScrollPane) {
247.58 @@ -828,7 +831,8 @@
247.59 // example, the rowHeaderView of the scrollPane -
247.60 // an implementor of fixed columns might do this.
247.61 JViewport viewport = scrollPane.getViewport();
247.62 - if (viewport == null || viewport.getView() != this) {
247.63 + if (viewport == null ||
247.64 + SwingUtilities.getUnwrappedView(viewport) != this) {
247.65 return;
247.66 }
247.67 scrollPane.setColumnHeaderView(null);
247.68 @@ -5215,7 +5219,7 @@
247.69 * @see #getFillsViewportHeight
247.70 */
247.71 public boolean getScrollableTracksViewportHeight() {
247.72 - JViewport port = SwingUtilities2.getViewport(this);
247.73 + JViewport port = SwingUtilities.getParentViewport(this);
247.74 return getFillsViewportHeight()
247.75 && port != null
247.76 && port.getHeight() > getPreferredSize().height;
247.77 @@ -5316,7 +5320,7 @@
247.78 }
247.79
247.80 private void setLazyValue(Hashtable h, Class c, String s) {
247.81 - h.put(c, new UIDefaults.ProxyLazyValue(s));
247.82 + h.put(c, new SwingLazyValue(s));
247.83 }
247.84
247.85 private void setLazyRenderer(Class c, String s) {
248.1 --- a/src/share/classes/javax/swing/JTextField.java Mon Nov 23 10:04:47 2009 +0000
248.2 +++ b/src/share/classes/javax/swing/JTextField.java Wed Nov 25 11:08:25 2009 -0800
248.3 @@ -288,9 +288,11 @@
248.4 *
248.5 * @see JComponent#revalidate
248.6 * @see JComponent#isValidateRoot
248.7 + * @see java.awt.Container#isValidateRoot
248.8 */
248.9 + @Override
248.10 public boolean isValidateRoot() {
248.11 - return SwingUtilities2.getViewport(this) == null;
248.12 + return SwingUtilities.getParentViewport(this) == null;
248.13 }
248.14
248.15
249.1 --- a/src/share/classes/javax/swing/JTree.java Mon Nov 23 10:04:47 2009 +0000
249.2 +++ b/src/share/classes/javax/swing/JTree.java Wed Nov 25 11:08:25 2009 -0800
249.3 @@ -3498,7 +3498,7 @@
249.4 * @see Scrollable#getScrollableTracksViewportWidth
249.5 */
249.6 public boolean getScrollableTracksViewportWidth() {
249.7 - JViewport port = SwingUtilities2.getViewport(this);
249.8 + JViewport port = SwingUtilities.getParentViewport(this);
249.9 if (port != null) {
249.10 return port.getWidth() > getPreferredSize().width;
249.11 }
249.12 @@ -3515,7 +3515,7 @@
249.13 * @see Scrollable#getScrollableTracksViewportHeight
249.14 */
249.15 public boolean getScrollableTracksViewportHeight() {
249.16 - JViewport port = SwingUtilities2.getViewport(this);
249.17 + JViewport port = SwingUtilities.getParentViewport(this);
249.18 if (port != null) {
249.19 return port.getHeight() > getPreferredSize().height;
249.20 }
250.1 --- a/src/share/classes/javax/swing/JViewport.java Mon Nov 23 10:04:47 2009 +0000
250.2 +++ b/src/share/classes/javax/swing/JViewport.java Wed Nov 25 11:08:25 2009 -0800
250.3 @@ -469,49 +469,12 @@
250.4 * is the synchronous version of a <code>revalidate</code>.
250.5 */
250.6 private void validateView() {
250.7 - Component validateRoot = null;
250.8 + Component validateRoot = SwingUtilities.getValidateRoot(this, false);
250.9
250.10 - /* Find the first JComponent ancestor of this component whose
250.11 - * isValidateRoot() method returns true.
250.12 - */
250.13 - for(Component c = this; c != null; c = c.getParent()) {
250.14 - if ((c instanceof CellRendererPane) || (c.getPeer() == null)) {
250.15 - return;
250.16 - }
250.17 - if ((c instanceof JComponent) &&
250.18 - (((JComponent)c).isValidateRoot())) {
250.19 - validateRoot = c;
250.20 - break;
250.21 - }
250.22 - }
250.23 -
250.24 - // If no validateRoot, nothing to validate from.
250.25 if (validateRoot == null) {
250.26 return;
250.27 }
250.28
250.29 - // Make sure all ancestors are visible.
250.30 - Component root = null;
250.31 -
250.32 - for(Component c = validateRoot; c != null; c = c.getParent()) {
250.33 - // We don't check isVisible here, otherwise if the component
250.34 - // is contained in something like a JTabbedPane when the
250.35 - // component is made visible again it won't have scrolled
250.36 - // to the correct location.
250.37 - if (c.getPeer() == null) {
250.38 - return;
250.39 - }
250.40 - if ((c instanceof Window) || (c instanceof Applet)) {
250.41 - root = c;
250.42 - break;
250.43 - }
250.44 - }
250.45 -
250.46 - // Make sure there is a Window ancestor.
250.47 - if (root == null) {
250.48 - return;
250.49 - }
250.50 -
250.51 // Validate the root.
250.52 validateRoot.validate();
250.53
251.1 --- a/src/share/classes/javax/swing/RepaintManager.java Mon Nov 23 10:04:47 2009 +0000
251.2 +++ b/src/share/classes/javax/swing/RepaintManager.java Wed Nov 25 11:08:25 2009 -0800
251.3 @@ -310,47 +310,13 @@
251.4 delegate.addInvalidComponent(invalidComponent);
251.5 return;
251.6 }
251.7 - Component validateRoot = null;
251.8 + Component validateRoot =
251.9 + SwingUtilities.getValidateRoot(invalidComponent, true);
251.10
251.11 - /* Find the first JComponent ancestor of this component whose
251.12 - * isValidateRoot() method returns true.
251.13 - */
251.14 - for(Component c = invalidComponent; c != null; c = c.getParent()) {
251.15 - if ((c instanceof CellRendererPane) || (c.getPeer() == null)) {
251.16 - return;
251.17 - }
251.18 - if ((c instanceof JComponent) && (((JComponent)c).isValidateRoot())) {
251.19 - validateRoot = c;
251.20 - break;
251.21 - }
251.22 - }
251.23 -
251.24 - /* There's no validateRoot to apply validate to, so we're done.
251.25 - */
251.26 if (validateRoot == null) {
251.27 return;
251.28 }
251.29
251.30 - /* If the validateRoot and all of its ancestors aren't visible
251.31 - * then we don't do anything. While we're walking up the tree
251.32 - * we find the root Window or Applet.
251.33 - */
251.34 - Component root = null;
251.35 -
251.36 - for(Component c = validateRoot; c != null; c = c.getParent()) {
251.37 - if (!c.isVisible() || (c.getPeer() == null)) {
251.38 - return;
251.39 - }
251.40 - if ((c instanceof Window) || (c instanceof Applet)) {
251.41 - root = c;
251.42 - break;
251.43 - }
251.44 - }
251.45 -
251.46 - if (root == null) {
251.47 - return;
251.48 - }
251.49 -
251.50 /* Lazily create the invalidateComponents vector and add the
251.51 * validateRoot if it's not there already. If this validateRoot
251.52 * is already in the vector, we're done.
252.1 --- a/src/share/classes/javax/swing/SwingUtilities.java Mon Nov 23 10:04:47 2009 +0000
252.2 +++ b/src/share/classes/javax/swing/SwingUtilities.java Wed Nov 25 11:08:25 2009 -0800
252.3 @@ -1967,4 +1967,114 @@
252.4 SwingUtilities.updateComponentTreeUI(component);
252.5 }
252.6 }
252.7 +
252.8 + /**
252.9 + * Looks for the first ancestor of the {@code component}
252.10 + * which is not an instance of {@link JLayer}.
252.11 + * If this ancestor is an instance of {@code JViewport},
252.12 + * this {@code JViewport} is returned, otherwise returns {@code null}.
252.13 + * The following way of obtaining the parent {@code JViewport}
252.14 + * is not recommended any more:
252.15 + * <pre>
252.16 + * JViewport port = null;
252.17 + * Container parent = component.getParent();
252.18 + * // not recommended any more
252.19 + * if(parent instanceof JViewport) {
252.20 + * port = (JViewport) parent;
252.21 + * }
252.22 + * </pre>
252.23 + * Here is the way to go:
252.24 + * <pre>
252.25 + * // the correct way:
252.26 + * JViewport port = SwingUtilities.getParentViewport(component);
252.27 + * </pre>
252.28 + * @param component {@code Component} to get the parent {@code JViewport} of.
252.29 + * @return the {@code JViewport} instance for the {@code component}
252.30 + * or {@code null}
252.31 + * @throws NullPointerException if {@code component} is {@code null}
252.32 + *
252.33 + * @since 1.7
252.34 + */
252.35 + public static JViewport getParentViewport(Component component) {
252.36 + do {
252.37 + component = component.getParent();
252.38 + if (component instanceof JViewport) {
252.39 + return (JViewport) component;
252.40 + }
252.41 + } while(component instanceof JLayer);
252.42 + return null;
252.43 + }
252.44 +
252.45 + /**
252.46 + * Returns the first {@code JViewport}'s descendant
252.47 + * which is not an instance of {@code JLayer} or {@code null}.
252.48 + *
252.49 + * If the {@code viewport}'s view component is not a {@code JLayer},
252.50 + * this method is equal to {@link JViewport#getView()}
252.51 + * otherwise {@link JLayer#getView()} will be recursively tested
252.52 + *
252.53 + * @return the first {@code JViewport}'s descendant
252.54 + * which is not an instance of {@code JLayer} or {@code null}.
252.55 + *
252.56 + * @throws NullPointerException if {@code viewport} is {@code null}
252.57 + * @see JViewport#getView()
252.58 + * @see JLayer
252.59 + */
252.60 + static Component getUnwrappedView(JViewport viewport) {
252.61 + Component view = viewport.getView();
252.62 + while (view instanceof JLayer) {
252.63 + view = ((JLayer)view).getView();
252.64 + }
252.65 + return view;
252.66 + }
252.67 +
252.68 + /**
252.69 + * Retrieves the validate root of a given container.
252.70 + *
252.71 + * If the container is contained within a {@code CellRendererPane}, this
252.72 + * method returns {@code null} due to the synthetic nature of the {@code
252.73 + * CellRendererPane}.
252.74 + * <p>
252.75 + * The component hierarchy must be displayable up to the toplevel component
252.76 + * (either a {@code Frame} or an {@code Applet} object.) Otherwise this
252.77 + * method returns {@code null}.
252.78 + * <p>
252.79 + * If the {@code visibleOnly} argument is {@code true}, the found validate
252.80 + * root and all its parents up to the toplevel component must also be
252.81 + * visible. Otherwise this method returns {@code null}.
252.82 + *
252.83 + * @return the validate root of the given container or null
252.84 + * @see java.awt.Component#isDisplayable()
252.85 + * @see java.awt.Component#isVisible()
252.86 + * @since 1.7
252.87 + */
252.88 + static Container getValidateRoot(Container c, boolean visibleOnly) {
252.89 + Container root = null;
252.90 +
252.91 + for (; c != null; c = c.getParent())
252.92 + {
252.93 + if (!c.isDisplayable() || c instanceof CellRendererPane) {
252.94 + return null;
252.95 + }
252.96 + if (c.isValidateRoot()) {
252.97 + root = c;
252.98 + break;
252.99 + }
252.100 + }
252.101 +
252.102 + if (root == null) {
252.103 + return null;
252.104 + }
252.105 +
252.106 + for (; c != null; c = c.getParent()) {
252.107 + if (!c.isDisplayable() || (visibleOnly && !c.isVisible())) {
252.108 + return null;
252.109 + }
252.110 + if (c instanceof Window || c instanceof Applet) {
252.111 + return root;
252.112 + }
252.113 + }
252.114 +
252.115 + return null;
252.116 + }
252.117 }
253.1 --- a/src/share/classes/javax/swing/ToolTipManager.java Mon Nov 23 10:04:47 2009 +0000
253.2 +++ b/src/share/classes/javax/swing/ToolTipManager.java Wed Nov 25 11:08:25 2009 -0800
253.3 @@ -1,5 +1,5 @@
253.4 /*
253.5 - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
253.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
253.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
253.8 *
253.9 * This code is free software; you can redistribute it and/or modify it
253.10 @@ -27,10 +27,7 @@
253.11 package javax.swing;
253.12
253.13 import java.awt.event.*;
253.14 -import java.applet.*;
253.15 import java.awt.*;
253.16 -import java.io.Serializable;
253.17 -import sun.swing.UIAction;
253.18
253.19 /**
253.20 * Manages all the <code>ToolTips</code> in the system.
253.21 @@ -60,7 +57,7 @@
253.22 JComponent insideComponent;
253.23 MouseEvent mouseEvent;
253.24 boolean showImmediately;
253.25 - final static ToolTipManager sharedInstance = new ToolTipManager();
253.26 + private static final Object TOOL_TIP_MANAGER_KEY = new Object();
253.27 transient Popup tipWindow;
253.28 /** The Window tip is being displayed in. This will be non-null if
253.29 * the Window tip is in differs from that of insideComponent's Window.
253.30 @@ -345,7 +342,13 @@
253.31 * @return a shared <code>ToolTipManager</code> object
253.32 */
253.33 public static ToolTipManager sharedInstance() {
253.34 - return sharedInstance;
253.35 + Object value = SwingUtilities.appContextGet(TOOL_TIP_MANAGER_KEY);
253.36 + if (value instanceof ToolTipManager) {
253.37 + return (ToolTipManager) value;
253.38 + }
253.39 + ToolTipManager manager = new ToolTipManager();
253.40 + SwingUtilities.appContextPut(TOOL_TIP_MANAGER_KEY, manager);
253.41 + return manager;
253.42 }
253.43
253.44 // add keylistener here to trigger tip for access
254.1 --- a/src/share/classes/javax/swing/UIManager.java Mon Nov 23 10:04:47 2009 +0000
254.2 +++ b/src/share/classes/javax/swing/UIManager.java Wed Nov 25 11:08:25 2009 -0800
254.3 @@ -1,5 +1,5 @@
254.4 /*
254.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
254.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
254.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
254.8 *
254.9 * This code is free software; you can redistribute it and/or modify it
254.10 @@ -197,6 +197,8 @@
254.11 Vector<LookAndFeel> auxLookAndFeels = null;
254.12 SwingPropertyChangeSupport changeSupport;
254.13
254.14 + LookAndFeelInfo[] installedLAFs;
254.15 +
254.16 UIDefaults getLookAndFeelDefaults() { return tables[0]; }
254.17 void setLookAndFeelDefaults(UIDefaults x) { tables[0] = x; }
254.18
254.19 @@ -227,18 +229,6 @@
254.20 */
254.21 private static final Object classLock = new Object();
254.22
254.23 -
254.24 - /* Cache the last referenced LAFState to improve performance
254.25 - * when accessing it. The cache is based on last thread rather
254.26 - * than last AppContext because of the cost of looking up the
254.27 - * AppContext each time. Since most Swing UI work is on the
254.28 - * EventDispatchThread, this hits often enough to justify the
254.29 - * overhead. (4193032)
254.30 - */
254.31 - private static Thread currentLAFStateThread = null;
254.32 - private static LAFState currentLAFState = null;
254.33 -
254.34 -
254.35 /**
254.36 * Return the <code>LAFState</code> object, lazily create one if necessary.
254.37 * All access to the <code>LAFState</code> fields is done via this method,
254.38 @@ -248,13 +238,6 @@
254.39 * </pre>
254.40 */
254.41 private static LAFState getLAFState() {
254.42 - // First check whether we're running on the same thread as
254.43 - // the last request.
254.44 - Thread thisThread = Thread.currentThread();
254.45 - if (thisThread == currentLAFStateThread) {
254.46 - return currentLAFState;
254.47 - }
254.48 -
254.49 LAFState rv = (LAFState)SwingUtilities.appContextGet(
254.50 SwingUtilities2.LAF_STATE_KEY);
254.51 if (rv == null) {
254.52 @@ -268,10 +251,6 @@
254.53 }
254.54 }
254.55 }
254.56 -
254.57 - currentLAFStateThread = thisThread;
254.58 - currentLAFState = rv;
254.59 -
254.60 return rv;
254.61 }
254.62
254.63 @@ -431,7 +410,10 @@
254.64 */
254.65 public static LookAndFeelInfo[] getInstalledLookAndFeels() {
254.66 maybeInitialize();
254.67 - LookAndFeelInfo[] ilafs = installedLAFs;
254.68 + LookAndFeelInfo[] ilafs = getLAFState().installedLAFs;
254.69 + if (ilafs == null) {
254.70 + ilafs = installedLAFs;
254.71 + }
254.72 LookAndFeelInfo[] rv = new LookAndFeelInfo[ilafs.length];
254.73 System.arraycopy(ilafs, 0, rv, 0, ilafs.length);
254.74 return rv;
254.75 @@ -453,9 +435,10 @@
254.76 public static void setInstalledLookAndFeels(LookAndFeelInfo[] infos)
254.77 throws SecurityException
254.78 {
254.79 + maybeInitialize();
254.80 LookAndFeelInfo[] newInfos = new LookAndFeelInfo[infos.length];
254.81 System.arraycopy(infos, 0, newInfos, 0, infos.length);
254.82 - installedLAFs = newInfos;
254.83 + getLAFState().installedLAFs = newInfos;
254.84 }
254.85
254.86
254.87 @@ -1307,10 +1290,11 @@
254.88 }
254.89 }
254.90
254.91 - installedLAFs = new LookAndFeelInfo[ilafs.size()];
254.92 + LookAndFeelInfo[] installedLAFs = new LookAndFeelInfo[ilafs.size()];
254.93 for(int i = 0; i < ilafs.size(); i++) {
254.94 installedLAFs[i] = ilafs.elementAt(i);
254.95 }
254.96 + getLAFState().installedLAFs = installedLAFs;
254.97 }
254.98
254.99
255.1 --- a/src/share/classes/javax/swing/filechooser/FileSystemView.java Mon Nov 23 10:04:47 2009 +0000
255.2 +++ b/src/share/classes/javax/swing/filechooser/FileSystemView.java Wed Nov 25 11:08:25 2009 -0800
255.3 @@ -33,7 +33,8 @@
255.4 import java.io.FileNotFoundException;
255.5 import java.io.IOException;
255.6 import java.text.MessageFormat;
255.7 -import java.util.Vector;
255.8 +import java.util.List;
255.9 +import java.util.ArrayList;
255.10 import java.lang.ref.WeakReference;
255.11 import java.beans.PropertyChangeListener;
255.12 import java.beans.PropertyChangeEvent;
255.13 @@ -173,22 +174,27 @@
255.14 * @since 1.4
255.15 */
255.16 public String getSystemDisplayName(File f) {
255.17 - String name = null;
255.18 - if (f != null) {
255.19 - name = f.getName();
255.20 - if (!name.equals("..") && !name.equals(".") &&
255.21 - (useSystemExtensionHiding ||
255.22 - !isFileSystem(f) ||
255.23 - isFileSystemRoot(f)) &&
255.24 - ((f instanceof ShellFolder) ||
255.25 - f.exists())) {
255.26 + if (f == null) {
255.27 + return null;
255.28 + }
255.29
255.30 + String name = f.getName();
255.31 +
255.32 + if (!name.equals("..") && !name.equals(".") &&
255.33 + (useSystemExtensionHiding || !isFileSystem(f) || isFileSystemRoot(f)) &&
255.34 + (f instanceof ShellFolder || f.exists())) {
255.35 +
255.36 + try {
255.37 name = getShellFolder(f).getDisplayName();
255.38 - if (name == null || name.length() == 0) {
255.39 - name = f.getPath(); // e.g. "/"
255.40 - }
255.41 + } catch (FileNotFoundException e) {
255.42 + return null;
255.43 + }
255.44 +
255.45 + if (name == null || name.length() == 0) {
255.46 + name = f.getPath(); // e.g. "/"
255.47 }
255.48 }
255.49 +
255.50 return name;
255.51 }
255.52
255.53 @@ -222,16 +228,24 @@
255.54 * @since 1.4
255.55 */
255.56 public Icon getSystemIcon(File f) {
255.57 - if (f != null) {
255.58 - ShellFolder sf = getShellFolder(f);
255.59 - Image img = sf.getIcon(false);
255.60 - if (img != null) {
255.61 - return new ImageIcon(img, sf.getFolderType());
255.62 - } else {
255.63 - return UIManager.getIcon(f.isDirectory() ? "FileView.directoryIcon" : "FileView.fileIcon");
255.64 - }
255.65 + if (f == null) {
255.66 + return null;
255.67 + }
255.68 +
255.69 + ShellFolder sf;
255.70 +
255.71 + try {
255.72 + sf = getShellFolder(f);
255.73 + } catch (FileNotFoundException e) {
255.74 + return null;
255.75 + }
255.76 +
255.77 + Image img = sf.getIcon(false);
255.78 +
255.79 + if (img != null) {
255.80 + return new ImageIcon(img, sf.getFolderType());
255.81 } else {
255.82 - return null;
255.83 + return UIManager.getIcon(f.isDirectory() ? "FileView.directoryIcon" : "FileView.fileIcon");
255.84 }
255.85 }
255.86
255.87 @@ -446,24 +460,28 @@
255.88 * Gets the list of shown (i.e. not hidden) files.
255.89 */
255.90 public File[] getFiles(File dir, boolean useFileHiding) {
255.91 - Vector<File> files = new Vector<File>();
255.92 -
255.93 + List<File> files = new ArrayList<File>();
255.94
255.95 // add all files in dir
255.96 - File[] names;
255.97 - if (!(dir instanceof ShellFolder)) {
255.98 + if (!(dir instanceof ShellFolder)) {
255.99 + try {
255.100 dir = getShellFolder(dir);
255.101 + } catch (FileNotFoundException e) {
255.102 + return new File[0];
255.103 }
255.104 + }
255.105
255.106 - names = ((ShellFolder)dir).listFiles(!useFileHiding);
255.107 - File f;
255.108 + File[] names = ((ShellFolder) dir).listFiles(!useFileHiding);
255.109
255.110 - int nameCount = (names == null) ? 0 : names.length;
255.111 - for (int i = 0; i < nameCount; i++) {
255.112 + if (names == null) {
255.113 + return new File[0];
255.114 + }
255.115 +
255.116 + for (File f : names) {
255.117 if (Thread.currentThread().isInterrupted()) {
255.118 break;
255.119 }
255.120 - f = names[i];
255.121 +
255.122 if (!(f instanceof ShellFolder)) {
255.123 if (isFileSystemRoot(f)) {
255.124 f = createFileSystemRoot(f);
255.125 @@ -481,7 +499,7 @@
255.126 }
255.127 }
255.128 if (!useFileHiding || !isHiddenFile(f)) {
255.129 - files.addElement(f);
255.130 + files.add(f);
255.131 }
255.132 }
255.133
255.134 @@ -497,42 +515,50 @@
255.135 * <code>null</code> if <code>dir</code> is <code>null</code>
255.136 */
255.137 public File getParentDirectory(File dir) {
255.138 - if (dir != null && dir.exists()) {
255.139 - ShellFolder sf = getShellFolder(dir);
255.140 - File psf = sf.getParentFile();
255.141 - if (psf != null) {
255.142 - if (isFileSystem(psf)) {
255.143 - File f = psf;
255.144 - if (f != null && !f.exists()) {
255.145 - // This could be a node under "Network Neighborhood".
255.146 - File ppsf = psf.getParentFile();
255.147 - if (ppsf == null || !isFileSystem(ppsf)) {
255.148 - // We're mostly after the exists() override for windows below.
255.149 - f = createFileSystemRoot(f);
255.150 - }
255.151 - }
255.152 - return f;
255.153 - } else {
255.154 - return psf;
255.155 + if (dir == null || !dir.exists()) {
255.156 + return null;
255.157 + }
255.158 +
255.159 + ShellFolder sf;
255.160 +
255.161 + try {
255.162 + sf = getShellFolder(dir);
255.163 + } catch (FileNotFoundException e) {
255.164 + return null;
255.165 + }
255.166 +
255.167 + File psf = sf.getParentFile();
255.168 +
255.169 + if (psf == null) {
255.170 + return null;
255.171 + }
255.172 +
255.173 + if (isFileSystem(psf)) {
255.174 + File f = psf;
255.175 + if (!f.exists()) {
255.176 + // This could be a node under "Network Neighborhood".
255.177 + File ppsf = psf.getParentFile();
255.178 + if (ppsf == null || !isFileSystem(ppsf)) {
255.179 + // We're mostly after the exists() override for windows below.
255.180 + f = createFileSystemRoot(f);
255.181 }
255.182 }
255.183 + return f;
255.184 + } else {
255.185 + return psf;
255.186 }
255.187 - return null;
255.188 }
255.189
255.190 - ShellFolder getShellFolder(File f) {
255.191 - if (!(f instanceof ShellFolder)
255.192 - && !(f instanceof FileSystemRoot)
255.193 - && isFileSystemRoot(f)) {
255.194 -
255.195 + /**
255.196 + * Throws {@code FileNotFoundException} if file not found or current thread was interrupted
255.197 + */
255.198 + ShellFolder getShellFolder(File f) throws FileNotFoundException {
255.199 + if (!(f instanceof ShellFolder) && !(f instanceof FileSystemRoot) && isFileSystemRoot(f)) {
255.200 f = createFileSystemRoot(f);
255.201 }
255.202 +
255.203 try {
255.204 return ShellFolder.getShellFolder(f);
255.205 - } catch (FileNotFoundException e) {
255.206 - System.err.println("FileSystemView.getShellFolder: f="+f);
255.207 - e.printStackTrace();
255.208 - return null;
255.209 } catch (InternalError e) {
255.210 System.err.println("FileSystemView.getShellFolder: f="+f);
255.211 e.printStackTrace();
255.212 @@ -596,9 +622,9 @@
255.213 // Unix - using OpenWindows' default folder name. Can't find one for Motif/CDE.
255.214 newFolder = createFileObject(containingDir, newFolderString);
255.215 int i = 1;
255.216 - while (newFolder.exists() && (i < 100)) {
255.217 + while (newFolder.exists() && i < 100) {
255.218 newFolder = createFileObject(containingDir, MessageFormat.format(
255.219 - newFolderNextString, new Object[] { new Integer(i) }));
255.220 + newFolderNextString, new Integer(i)));
255.221 i++;
255.222 }
255.223
255.224 @@ -612,7 +638,7 @@
255.225 }
255.226
255.227 public boolean isFileSystemRoot(File dir) {
255.228 - return (dir != null && dir.getAbsolutePath().equals("/"));
255.229 + return dir != null && dir.getAbsolutePath().equals("/");
255.230 }
255.231
255.232 public boolean isDrive(File dir) {
255.233 @@ -654,7 +680,7 @@
255.234
255.235 public File getChild(File parent, String fileName) {
255.236 if (fileName.startsWith("\\")
255.237 - && !(fileName.startsWith("\\\\"))
255.238 + && !fileName.startsWith("\\\\")
255.239 && isFileSystem(parent)) {
255.240
255.241 //Path is relative to the root of parent's drive
255.242 @@ -677,9 +703,13 @@
255.243 * The Windows implementation gets information from the ShellFolder class.
255.244 */
255.245 public String getSystemTypeDescription(File f) {
255.246 - if (f != null) {
255.247 + if (f == null) {
255.248 + return null;
255.249 + }
255.250 +
255.251 + try {
255.252 return getShellFolder(f).getFolderType();
255.253 - } else {
255.254 + } catch (FileNotFoundException e) {
255.255 return null;
255.256 }
255.257 }
255.258 @@ -701,9 +731,9 @@
255.259 // Using NT's default folder name
255.260 File newFolder = createFileObject(containingDir, newFolderString);
255.261 int i = 2;
255.262 - while (newFolder.exists() && (i < 100)) {
255.263 + while (newFolder.exists() && i < 100) {
255.264 newFolder = createFileObject(containingDir, MessageFormat.format(
255.265 - newFolderNextString, new Object[] { new Integer(i) }));
255.266 + newFolderNextString, new Integer(i)));
255.267 i++;
255.268 }
255.269
255.270 @@ -727,7 +757,7 @@
255.271 }
255.272 });
255.273
255.274 - return (path != null && (path.equals("A:\\") || path.equals("B:\\")));
255.275 + return path != null && (path.equals("A:\\") || path.equals("B:\\"));
255.276 }
255.277
255.278 /**
256.1 --- a/src/share/classes/javax/swing/plaf/LayerUI.java Mon Nov 23 10:04:47 2009 +0000
256.2 +++ b/src/share/classes/javax/swing/plaf/LayerUI.java Wed Nov 25 11:08:25 2009 -0800
256.3 @@ -71,33 +71,410 @@
256.4 * Subclasses should override this method and use
256.5 * the specified {@code Graphics} object to
256.6 * render the content of the component.
256.7 + * <p/>
256.8 + * If {@code g} is not an instance of {@code Graphics2D},
256.9 + * this method is no-op.
256.10 *
256.11 * @param g the {@code Graphics} context in which to paint;
256.12 * @param c the component being painted;
256.13 - * it can be safely cast to the {@code JLayer<V>}
256.14 + * it can be safely cast to {@code JLayer<? extends V>}
256.15 + *
256.16 + * @see #configureGraphics(Graphics2D, JLayer)
256.17 + * @see #paintLayer(Graphics2D, JLayer)
256.18 */
256.19 - @Override
256.20 public void paint(Graphics g, JComponent c) {
256.21 - c.paint(g);
256.22 + if (g instanceof Graphics2D) {
256.23 + Graphics2D g2 = (Graphics2D) g.create();
256.24 + JLayer<? extends V> l = (JLayer<? extends V>) c;
256.25 + configureGraphics(g2, l);
256.26 + paintLayer(g2, l);
256.27 + g2.dispose();
256.28 + }
256.29 + }
256.30 +
256.31 + /**
256.32 + * This method is called by the {@link #paint} method prior to
256.33 + * {@link #paintLayer} to configure the {@code Graphics2D} object.
256.34 + * The default implementation is empty.
256.35 + *
256.36 + * @param g2 the {@code Graphics2D} object to configure
256.37 + * @param l the {@code JLayer} being painted
256.38 + *
256.39 + * @see #paintLayer(Graphics2D, JLayer)
256.40 + */
256.41 + protected void configureGraphics(Graphics2D g2, JLayer<? extends V> l) {
256.42 + }
256.43 +
256.44 + /**
256.45 + * Called by the {@link #paint} method,
256.46 + * subclasses should override this method
256.47 + * to perform any custom painting operations.
256.48 + * <p/>
256.49 + * The default implementation paints the passed {@code JLayer} as is.
256.50 + *
256.51 + * @param g2 the {@code Graphics2D} context in which to paint
256.52 + * @param l the {@code JLayer} being painted
256.53 + *
256.54 + * @see #configureGraphics(Graphics2D, JLayer)
256.55 + */
256.56 + protected void paintLayer(Graphics2D g2, JLayer<? extends V> l) {
256.57 + l.paint(g2);
256.58 }
256.59
256.60 /**
256.61 * Dispatches {@code AWTEvent}s for {@code JLayer}
256.62 - * and <b>all it subcomponents</b> to this {@code LayerUI} instance.
256.63 - * <p>
256.64 - * To enable the {@code AWTEvent} of the particular type,
256.65 - * you call {@link javax.swing.JLayer#setLayerEventMask}
256.66 + * and <b>all its subcomponents</b> to this {@code LayerUI} instance.
256.67 + * <p/>
256.68 + * To enable the {@code AWTEvent}s of a particular type,
256.69 + * you call {@link JLayer#setLayerEventMask}
256.70 * in {@link #installUI(javax.swing.JComponent)}
256.71 * and set the layer event mask to {@code 0}
256.72 - * in {@link #uninstallUI(javax.swing.JComponent)} after that
256.73 + * in {@link #uninstallUI(javax.swing.JComponent)} after that.
256.74 + * By default this method calls the appropriate
256.75 + * {@code process<event type>Event}
256.76 + * method for the given class of event.
256.77 *
256.78 * @param e the event to be dispatched
256.79 * @param l the layer this LayerUI is set to
256.80 *
256.81 * @see JLayer#setLayerEventMask(long)
256.82 - * @see javax.swing.JLayer#getLayerEventMask()
256.83 + * @see #installUI(javax.swing.JComponent)
256.84 + * @see #uninstallUI(javax.swing.JComponent)
256.85 + * @see #processComponentEvent
256.86 + * @see #processFocusEvent
256.87 + * @see #processKeyEvent
256.88 + * @see #processMouseEvent
256.89 + * @see #processMouseMotionEvent
256.90 + * @see #processInputMethodEvent
256.91 + * @see #processHierarchyEvent
256.92 + * @see #processMouseWheelEvent
256.93 */
256.94 public void eventDispatched(AWTEvent e, JLayer<? extends V> l){
256.95 + if (e instanceof FocusEvent) {
256.96 + processFocusEvent((FocusEvent)e, l);
256.97 +
256.98 + } else if (e instanceof MouseEvent) {
256.99 + switch(e.getID()) {
256.100 + case MouseEvent.MOUSE_PRESSED:
256.101 + case MouseEvent.MOUSE_RELEASED:
256.102 + case MouseEvent.MOUSE_CLICKED:
256.103 + case MouseEvent.MOUSE_ENTERED:
256.104 + case MouseEvent.MOUSE_EXITED:
256.105 + processMouseEvent((MouseEvent)e, l);
256.106 + break;
256.107 + case MouseEvent.MOUSE_MOVED:
256.108 + case MouseEvent.MOUSE_DRAGGED:
256.109 + processMouseMotionEvent((MouseEvent)e, l);
256.110 + break;
256.111 + case MouseEvent.MOUSE_WHEEL:
256.112 + processMouseWheelEvent((MouseWheelEvent)e, l);
256.113 + break;
256.114 + }
256.115 + } else if (e instanceof KeyEvent) {
256.116 + processKeyEvent((KeyEvent)e, l);
256.117 + } else if (e instanceof ComponentEvent) {
256.118 + processComponentEvent((ComponentEvent)e, l);
256.119 + } else if (e instanceof InputMethodEvent) {
256.120 + processInputMethodEvent((InputMethodEvent)e, l);
256.121 + } else if (e instanceof HierarchyEvent) {
256.122 + switch (e.getID()) {
256.123 + case HierarchyEvent.HIERARCHY_CHANGED:
256.124 + processHierarchyEvent((HierarchyEvent)e, l);
256.125 + break;
256.126 + case HierarchyEvent.ANCESTOR_MOVED:
256.127 + case HierarchyEvent.ANCESTOR_RESIZED:
256.128 + processHierarchyBoundsEvent((HierarchyEvent)e, l);
256.129 + break;
256.130 + }
256.131 + }
256.132 + }
256.133 +
256.134 + /**
256.135 + * Processes component events occurring on the {@link JLayer}
256.136 + * or any of its subcomponents.
256.137 + * <p/>
256.138 + * This method is not called unless component events are
256.139 + * enabled for the {@code JLayer} objects, this {@code LayerUI} is set to.
256.140 + * Component events are enabled in the overridden {@link #installUI} method
256.141 + * and should be disabled in the {@link #uninstallUI} method after that.
256.142 + * <pre>
256.143 + * public void installUI(JComponent c) {
256.144 + * super.installUI(c);
256.145 + * JLayer l = (JLayer) c;
256.146 + * l.setLayerEventMask(AWTEvent.COMPONENT_EVENT_MASK);
256.147 + * }
256.148 + *
256.149 + * public void unistallUI(JComponent c) {
256.150 + * super.uninstallUI(c);
256.151 + * JLayer l = (JLayer) c;
256.152 + * l.setLayerEventMask(0);
256.153 + * }
256.154 + * </pre>
256.155 + *
256.156 + * @param e the {@code ComponentEvent} to be processed
256.157 + * @param l the layer this {@code LayerUI} instance is set to
256.158 + *
256.159 + * @see JLayer#setLayerEventMask(long)
256.160 + * @see #installUI(javax.swing.JComponent)
256.161 + * @see #uninstallUI(javax.swing.JComponent)
256.162 + */
256.163 + protected void processComponentEvent(ComponentEvent e, JLayer<? extends V> l) {
256.164 + }
256.165 +
256.166 + /**
256.167 + * Processes focus events occurring on the {@link JLayer}
256.168 + * or any of its subcomponents.
256.169 + * <p/>
256.170 + * This method is not called unless focus events are
256.171 + * enabled for the {@code JLayer} objects, this {@code LayerUI} is set to.
256.172 + * Focus events are enabled in the overridden {@link #installUI} method
256.173 + * and should be disabled in the {@link #uninstallUI} method after that.
256.174 + * <pre>
256.175 + * public void installUI(JComponent c) {
256.176 + * super.installUI(c);
256.177 + * JLayer l = (JLayer) c;
256.178 + * l.setLayerEventMask(AWTEvent.FOCUS_EVENT_MASK);
256.179 + * }
256.180 + *
256.181 + * public void unistallUI(JComponent c) {
256.182 + * super.uninstallUI(c);
256.183 + * JLayer l = (JLayer) c;
256.184 + * l.setLayerEventMask(0);
256.185 + * }
256.186 + * </pre>
256.187 + *
256.188 + * @param e the {@code FocusEvent} to be processed
256.189 + * @param l the layer this {@code LayerUI} instance is set to
256.190 + *
256.191 + * @see JLayer#setLayerEventMask(long)
256.192 + * @see #installUI(javax.swing.JComponent)
256.193 + * @see #uninstallUI(javax.swing.JComponent)
256.194 + */
256.195 + protected void processFocusEvent(FocusEvent e, JLayer<? extends V> l) {
256.196 + }
256.197 +
256.198 + /**
256.199 + * Processes key events occurring on the {@link JLayer}
256.200 + * or any of its subcomponents.
256.201 + * <p/>
256.202 + * This method is not called unless key events are
256.203 + * enabled for the {@code JLayer} objects, this {@code LayerUI} is set to.
256.204 + * Key events are enabled in the overridden {@link #installUI} method
256.205 + * and should be disabled in the {@link #uninstallUI} method after that.
256.206 + * <pre>
256.207 + * public void installUI(JComponent c) {
256.208 + * super.installUI(c);
256.209 + * JLayer l = (JLayer) c;
256.210 + * l.setLayerEventMask(AWTEvent.KEY_EVENT_MASK);
256.211 + * }
256.212 + *
256.213 + * public void unistallUI(JComponent c) {
256.214 + * super.uninstallUI(c);
256.215 + * JLayer l = (JLayer) c;
256.216 + * l.setLayerEventMask(0);
256.217 + * }
256.218 + * </pre>
256.219 + *
256.220 + * @param e the {@code KeyEvent} to be processed
256.221 + * @param l the layer this {@code LayerUI} instance is set to
256.222 + *
256.223 + * @see JLayer#setLayerEventMask(long)
256.224 + * @see #installUI(javax.swing.JComponent)
256.225 + * @see #uninstallUI(javax.swing.JComponent)
256.226 + */
256.227 + protected void processKeyEvent(KeyEvent e, JLayer<? extends V> l) {
256.228 + }
256.229 +
256.230 + /**
256.231 + * Processes mouse events occurring on the {@link JLayer}
256.232 + * or any of its subcomponents.
256.233 + * <p/>
256.234 + * This method is not called unless mouse events are
256.235 + * enabled for the {@code JLayer} objects, this {@code LayerUI} is set to.
256.236 + * Mouse events are enabled in the overridden {@link #installUI} method
256.237 + * and should be disabled in the {@link #uninstallUI} method after that.
256.238 + * <pre>
256.239 + * public void installUI(JComponent c) {
256.240 + * super.installUI(c);
256.241 + * JLayer l = (JLayer) c;
256.242 + * l.setLayerEventMask(AWTEvent.MOUSE_EVENT_MASK);
256.243 + * }
256.244 + *
256.245 + * public void unistallUI(JComponent c) {
256.246 + * super.uninstallUI(c);
256.247 + * JLayer l = (JLayer) c;
256.248 + * l.setLayerEventMask(0);
256.249 + * }
256.250 + * </pre>
256.251 + *
256.252 + * @param e the {@code MouseEvent} to be processed
256.253 + * @param l the layer this {@code LayerUI} instance is set to
256.254 + *
256.255 + * @see JLayer#setLayerEventMask(long)
256.256 + * @see #installUI(javax.swing.JComponent)
256.257 + * @see #uninstallUI(javax.swing.JComponent)
256.258 + */
256.259 + protected void processMouseEvent(MouseEvent e, JLayer<? extends V> l) {
256.260 + }
256.261 +
256.262 + /**
256.263 + * Processes mouse motion event occurring on the {@link JLayer}
256.264 + * or any of its subcomponents.
256.265 + * <p/>
256.266 + * This method is not called unless mouse motion events are
256.267 + * enabled for the {@code JLayer} objects, this {@code LayerUI} is set to.
256.268 + * Mouse motion events are enabled in the overridden {@link #installUI} method
256.269 + * and should be disabled in the {@link #uninstallUI} method after that.
256.270 + * <pre>
256.271 + * public void installUI(JComponent c) {
256.272 + * super.installUI(c);
256.273 + * JLayer l = (JLayer) c;
256.274 + * l.setLayerEventMask(AWTEvent.MOUSE_MOTION_EVENT_MASK);
256.275 + * }
256.276 + *
256.277 + * public void unistallUI(JComponent c) {
256.278 + * super.uninstallUI(c);
256.279 + * JLayer l = (JLayer) c;
256.280 + * l.setLayerEventMask(0);
256.281 + * }
256.282 + * </pre>
256.283 + *
256.284 + * @param e the {@code MouseEvent} to be processed
256.285 + * @param l the layer this {@code LayerUI} instance is set to
256.286 + *
256.287 + * @see JLayer#setLayerEventMask(long)
256.288 + * @see #installUI(javax.swing.JComponent)
256.289 + * @see #uninstallUI(javax.swing.JComponent)
256.290 + */
256.291 + protected void processMouseMotionEvent(MouseEvent e, JLayer<? extends V> l) {
256.292 + }
256.293 +
256.294 + /**
256.295 + * Processes mouse wheel event occurring on the {@link JLayer}
256.296 + * or any of its subcomponents.
256.297 + * <p/>
256.298 + * This method is not called unless mouse wheel events are
256.299 + * enabled for the {@code JLayer} objects, this {@code LayerUI} is set to.
256.300 + * Mouse wheel events are enabled in the overridden {@link #installUI} method
256.301 + * and should be disabled in the {@link #uninstallUI} method after that.
256.302 + * <pre>
256.303 + * public void installUI(JComponent c) {
256.304 + * super.installUI(c);
256.305 + * JLayer l = (JLayer) c;
256.306 + * l.setLayerEventMask(AWTEvent.MOUSE_WHEEL_EVENT_MASK);
256.307 + * }
256.308 + *
256.309 + * public void unistallUI(JComponent c) {
256.310 + * super.uninstallUI(c);
256.311 + * JLayer l = (JLayer) c;
256.312 + * l.setLayerEventMask(0);
256.313 + * }
256.314 + * </pre>
256.315 + *
256.316 + * @param e the {@code MouseEvent} to be processed
256.317 + * @param l the layer this {@code LayerUI} instance is set to
256.318 + *
256.319 + * @see JLayer#setLayerEventMask(long)
256.320 + * @see #installUI(javax.swing.JComponent)
256.321 + * @see #uninstallUI(javax.swing.JComponent)
256.322 + */
256.323 + protected void processMouseWheelEvent(MouseWheelEvent e, JLayer<? extends V> l) {
256.324 + }
256.325 +
256.326 + /**
256.327 + * Processes input event occurring on the {@link JLayer}
256.328 + * or any of its subcomponents.
256.329 + * <p/>
256.330 + * This method is not called unless input events are
256.331 + * enabled for the {@code JLayer} objects, this {@code LayerUI} is set to.
256.332 + * Input events are enabled in the overridden {@link #installUI} method
256.333 + * and should be disabled in the {@link #uninstallUI} method after that.
256.334 + * <pre>
256.335 + * public void installUI(JComponent c) {
256.336 + * super.installUI(c);
256.337 + * JLayer l = (JLayer) c;
256.338 + * l.setLayerEventMask(AWTEvent.INPUT_METHOD_EVENT_MASK);
256.339 + * }
256.340 + *
256.341 + * public void unistallUI(JComponent c) {
256.342 + * super.uninstallUI(c);
256.343 + * JLayer l = (JLayer) c;
256.344 + * l.setLayerEventMask(0);
256.345 + * }
256.346 + * </pre>
256.347 + *
256.348 + * @param e the {@code InputMethodEvent} to be processed
256.349 + * @param l the layer this {@code LayerUI} instance is set to
256.350 + *
256.351 + * @see JLayer#setLayerEventMask(long)
256.352 + * @see #installUI(javax.swing.JComponent)
256.353 + * @see #uninstallUI(javax.swing.JComponent)
256.354 + */
256.355 + protected void processInputMethodEvent(InputMethodEvent e, JLayer<? extends V> l) {
256.356 + }
256.357 +
256.358 + /**
256.359 + * Processes hierarchy event occurring on the {@link JLayer}
256.360 + * or any of its subcomponents.
256.361 + * <p/>
256.362 + * This method is not called unless hierarchy events are
256.363 + * enabled for the {@code JLayer} objects, this {@code LayerUI} is set to.
256.364 + * Hierarchy events are enabled in the overridden {@link #installUI} method
256.365 + * and should be disabled in the {@link #uninstallUI} method after that.
256.366 + * <pre>
256.367 + * public void installUI(JComponent c) {
256.368 + * super.installUI(c);
256.369 + * JLayer l = (JLayer) c;
256.370 + * l.setLayerEventMask(AWTEvent.HIERARCHY_EVENT_MASK);
256.371 + * }
256.372 + *
256.373 + * public void unistallUI(JComponent c) {
256.374 + * super.uninstallUI(c);
256.375 + * JLayer l = (JLayer) c;
256.376 + * l.setLayerEventMask(0);
256.377 + * }
256.378 + * </pre>
256.379 + *
256.380 + * @param e the {@code HierarchyEvent} to be processed
256.381 + * @param l the layer this {@code LayerUI} instance is set to
256.382 + *
256.383 + * @see JLayer#setLayerEventMask(long)
256.384 + * @see #installUI(javax.swing.JComponent)
256.385 + * @see #uninstallUI(javax.swing.JComponent)
256.386 + */
256.387 + protected void processHierarchyEvent(HierarchyEvent e, JLayer<? extends V> l) {
256.388 + }
256.389 +
256.390 + /**
256.391 + * Processes hierarchy bounds event occurring on the {@link JLayer}
256.392 + * or any of its subcomponents.
256.393 + * <p/>
256.394 + * This method is not called unless hierarchy bounds events are
256.395 + * enabled for the {@code JLayer} objects, this {@code LayerUI} is set to.
256.396 + * Hierarchy bounds events are enabled in the overridden {@link #installUI}
256.397 + * method and should be disabled in the {@link #uninstallUI} method after that.
256.398 + * <pre>
256.399 + * public void installUI(JComponent c) {
256.400 + * super.installUI(c);
256.401 + * JLayer l = (JLayer) c;
256.402 + * l.setLayerEventMask(AWTEvent.HIERARCHY_BOUNDS_EVENT_MASK);
256.403 + * }
256.404 + *
256.405 + * public void unistallUI(JComponent c) {
256.406 + * super.uninstallUI(c);
256.407 + * JLayer l = (JLayer) c;
256.408 + * l.setLayerEventMask(0);
256.409 + * }
256.410 + * </pre>
256.411 + *
256.412 + * @param e the {@code HierarchyEvent} to be processed
256.413 + * @param l the layer this {@code LayerUI} instance is set to
256.414 + *
256.415 + * @see JLayer#setLayerEventMask(long)
256.416 + * @see #installUI(javax.swing.JComponent)
256.417 + * @see #uninstallUI(javax.swing.JComponent)
256.418 + */
256.419 + protected void processHierarchyBoundsEvent(HierarchyEvent e, JLayer<? extends V> l) {
256.420 }
256.421
256.422 /**
256.423 @@ -251,13 +628,28 @@
256.424 }
256.425
256.426 /**
256.427 + * Repaints all {@code JLayer} instances this {@code LayerUI} is set to.
256.428 + * Call this method when the state of this {@code LayerUI} is changed
256.429 + * and the visual appearance of its {@code JLayer} objects needs to be updated.
256.430 + *
256.431 + * @see Component#repaint()
256.432 + */
256.433 + protected void repaintLayer() {
256.434 + firePropertyChange("dirty", null, null);
256.435 + }
256.436 +
256.437 + /**
256.438 * Notifies the {@code LayerUI} when any of its property are changed
256.439 - * and enables updating every {@code JLayer} this {@code LayerUI} instance is set to.
256.440 + * and enables updating every {@code JLayer}
256.441 + * this {@code LayerUI} instance is set to.
256.442 *
256.443 * @param evt the PropertyChangeEvent generated by this {@code LayerUI}
256.444 * @param l the {@code JLayer} this LayerUI is set to
256.445 */
256.446 public void applyPropertyChange(PropertyChangeEvent evt, JLayer<? extends V> l) {
256.447 + if ("dirty".equals(evt.getPropertyName())) {
256.448 + l.repaint();
256.449 + }
256.450 }
256.451
256.452 /**
257.1 --- a/src/share/classes/javax/swing/plaf/basic/BasicButtonUI.java Mon Nov 23 10:04:47 2009 +0000
257.2 +++ b/src/share/classes/javax/swing/plaf/basic/BasicButtonUI.java Wed Nov 25 11:08:25 2009 -0800
257.3 @@ -26,6 +26,8 @@
257.4 package javax.swing.plaf.basic;
257.5
257.6 import sun.swing.SwingUtilities2;
257.7 +import sun.awt.AppContext;
257.8 +
257.9 import java.awt.*;
257.10 import java.awt.event.*;
257.11 import java.io.Serializable;
257.12 @@ -44,9 +46,6 @@
257.13 * @author Jeff Dinkins
257.14 */
257.15 public class BasicButtonUI extends ButtonUI{
257.16 - // Shared UI object
257.17 - private final static BasicButtonUI buttonUI = new BasicButtonUI();
257.18 -
257.19 // Visual constants
257.20 // NOTE: This is not used or set any where. Were we allowed to remove
257.21 // fields, this would be removed.
257.22 @@ -61,10 +60,19 @@
257.23
257.24 private final static String propertyPrefix = "Button" + ".";
257.25
257.26 + private static final Object BASIC_BUTTON_UI_KEY = new Object();
257.27 +
257.28 // ********************************
257.29 // Create PLAF
257.30 // ********************************
257.31 public static ComponentUI createUI(JComponent c) {
257.32 + AppContext appContext = AppContext.getAppContext();
257.33 + BasicButtonUI buttonUI =
257.34 + (BasicButtonUI) appContext.get(BASIC_BUTTON_UI_KEY);
257.35 + if (buttonUI == null) {
257.36 + buttonUI = new BasicButtonUI();
257.37 + appContext.put(BASIC_BUTTON_UI_KEY, buttonUI);
257.38 + }
257.39 return buttonUI;
257.40 }
257.41
258.1 --- a/src/share/classes/javax/swing/plaf/basic/BasicCheckBoxUI.java Mon Nov 23 10:04:47 2009 +0000
258.2 +++ b/src/share/classes/javax/swing/plaf/basic/BasicCheckBoxUI.java Wed Nov 25 11:08:25 2009 -0800
258.3 @@ -25,6 +25,8 @@
258.4
258.5 package javax.swing.plaf.basic;
258.6
258.7 +import sun.awt.AppContext;
258.8 +
258.9 import javax.swing.*;
258.10
258.11 import java.awt.*;
258.12 @@ -49,7 +51,7 @@
258.13 */
258.14 public class BasicCheckBoxUI extends BasicRadioButtonUI {
258.15
258.16 - private final static BasicCheckBoxUI checkboxUI = new BasicCheckBoxUI();
258.17 + private static final Object BASIC_CHECK_BOX_UI_KEY = new Object();
258.18
258.19 private final static String propertyPrefix = "CheckBox" + ".";
258.20
258.21 @@ -57,6 +59,13 @@
258.22 // Create PLAF
258.23 // ********************************
258.24 public static ComponentUI createUI(JComponent b) {
258.25 + AppContext appContext = AppContext.getAppContext();
258.26 + BasicCheckBoxUI checkboxUI =
258.27 + (BasicCheckBoxUI) appContext.get(BASIC_CHECK_BOX_UI_KEY);
258.28 + if (checkboxUI == null) {
258.29 + checkboxUI = new BasicCheckBoxUI();
258.30 + appContext.put(BASIC_CHECK_BOX_UI_KEY, checkboxUI);
258.31 + }
258.32 return checkboxUI;
258.33 }
258.34
259.1 --- a/src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java Mon Nov 23 10:04:47 2009 +0000
259.2 +++ b/src/share/classes/javax/swing/plaf/basic/BasicDirectoryModel.java Wed Nov 25 11:08:25 2009 -0800
259.3 @@ -486,7 +486,7 @@
259.4 }
259.5 if (remSize > 0 && addSize == 0) {
259.6 fireIntervalRemoved(BasicDirectoryModel.this, remStart, remStart + remSize - 1);
259.7 - } else if (addSize > 0 && remSize == 0 && fileCache.size() > addSize) {
259.8 + } else if (addSize > 0 && remSize == 0 && addStart + addSize <= fileCache.size()) {
259.9 fireIntervalAdded(BasicDirectoryModel.this, addStart, addStart + addSize - 1);
259.10 } else {
259.11 fireContentsChanged();
260.1 --- a/src/share/classes/javax/swing/plaf/basic/BasicLabelUI.java Mon Nov 23 10:04:47 2009 +0000
260.2 +++ b/src/share/classes/javax/swing/plaf/basic/BasicLabelUI.java Wed Nov 25 11:08:25 2009 -0800
260.3 @@ -28,6 +28,8 @@
260.4 import sun.swing.SwingUtilities2;
260.5 import sun.swing.DefaultLookup;
260.6 import sun.swing.UIAction;
260.7 +import sun.awt.AppContext;
260.8 +
260.9 import javax.swing.*;
260.10 import javax.swing.plaf.*;
260.11 import javax.swing.text.View;
260.12 @@ -63,7 +65,7 @@
260.13 * name in defaults table under the key "LabelUI".
260.14 */
260.15 protected static BasicLabelUI labelUI = new BasicLabelUI();
260.16 - private final static BasicLabelUI SAFE_BASIC_LABEL_UI = new BasicLabelUI();
260.17 + private static final Object BASIC_LABEL_UI_KEY = new Object();
260.18
260.19 private Rectangle paintIconR = new Rectangle();
260.20 private Rectangle paintTextR = new Rectangle();
260.21 @@ -394,10 +396,16 @@
260.22
260.23 public static ComponentUI createUI(JComponent c) {
260.24 if (System.getSecurityManager() != null) {
260.25 - return SAFE_BASIC_LABEL_UI;
260.26 - } else {
260.27 - return labelUI;
260.28 + AppContext appContext = AppContext.getAppContext();
260.29 + BasicLabelUI safeBasicLabelUI =
260.30 + (BasicLabelUI) appContext.get(BASIC_LABEL_UI_KEY);
260.31 + if (safeBasicLabelUI == null) {
260.32 + safeBasicLabelUI = new BasicLabelUI();
260.33 + appContext.put(BASIC_LABEL_UI_KEY, safeBasicLabelUI);
260.34 + }
260.35 + return safeBasicLabelUI;
260.36 }
260.37 + return labelUI;
260.38 }
260.39
260.40 public void propertyChange(PropertyChangeEvent e) {
261.1 --- a/src/share/classes/javax/swing/plaf/basic/BasicRadioButtonUI.java Mon Nov 23 10:04:47 2009 +0000
261.2 +++ b/src/share/classes/javax/swing/plaf/basic/BasicRadioButtonUI.java Wed Nov 25 11:08:25 2009 -0800
261.3 @@ -32,6 +32,7 @@
261.4 import javax.swing.plaf.*;
261.5 import javax.swing.text.View;
261.6 import sun.swing.SwingUtilities2;
261.7 +import sun.awt.AppContext;
261.8
261.9
261.10 /**
261.11 @@ -41,7 +42,7 @@
261.12 */
261.13 public class BasicRadioButtonUI extends BasicToggleButtonUI
261.14 {
261.15 - private final static BasicRadioButtonUI radioButtonUI = new BasicRadioButtonUI();
261.16 + private static final Object BASIC_RADIO_BUTTON_UI_KEY = new Object();
261.17
261.18 protected Icon icon;
261.19
261.20 @@ -53,6 +54,13 @@
261.21 // Create PLAF
261.22 // ********************************
261.23 public static ComponentUI createUI(JComponent b) {
261.24 + AppContext appContext = AppContext.getAppContext();
261.25 + BasicRadioButtonUI radioButtonUI =
261.26 + (BasicRadioButtonUI) appContext.get(BASIC_RADIO_BUTTON_UI_KEY);
261.27 + if (radioButtonUI == null) {
261.28 + radioButtonUI = new BasicRadioButtonUI();
261.29 + appContext.put(BASIC_RADIO_BUTTON_UI_KEY, radioButtonUI);
261.30 + }
261.31 return radioButtonUI;
261.32 }
261.33
262.1 --- a/src/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java Mon Nov 23 10:04:47 2009 +0000
262.2 +++ b/src/share/classes/javax/swing/plaf/basic/BasicSplitPaneUI.java Wed Nov 25 11:08:25 2009 -0800
262.3 @@ -1,5 +1,5 @@
262.4 /*
262.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
262.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
262.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
262.8 *
262.9 * This code is free software; you can redistribute it and/or modify it
262.10 @@ -31,14 +31,12 @@
262.11 import sun.swing.UIAction;
262.12 import javax.swing.*;
262.13 import javax.swing.border.Border;
262.14 -import javax.swing.event.*;
262.15 import java.awt.*;
262.16 import java.awt.event.*;
262.17 import java.awt.peer.ComponentPeer;
262.18 import java.awt.peer.LightweightPeer;
262.19 import java.beans.*;
262.20 import java.util.*;
262.21 -import javax.swing.plaf.ActionMapUIResource;
262.22 import javax.swing.plaf.SplitPaneUI;
262.23 import javax.swing.plaf.ComponentUI;
262.24 import javax.swing.plaf.UIResource;
262.25 @@ -106,13 +104,13 @@
262.26 * Keys to use for forward focus traversal when the JComponent is
262.27 * managing focus.
262.28 */
262.29 - private static Set<KeyStroke> managingFocusForwardTraversalKeys;
262.30 + private Set<KeyStroke> managingFocusForwardTraversalKeys;
262.31
262.32 /**
262.33 * Keys to use for backward focus traversal when the JComponent is
262.34 * managing focus.
262.35 */
262.36 - private static Set<KeyStroke> managingFocusBackwardTraversalKeys;
262.37 + private Set<KeyStroke> managingFocusBackwardTraversalKeys;
262.38
262.39
262.40 /**
262.41 @@ -675,7 +673,7 @@
262.42 * @return increment via keyboard methods.
262.43 */
262.44 int getKeyboardMoveIncrement() {
262.45 - return KEYBOARD_DIVIDER_MOVE_OFFSET;
262.46 + return 3;
262.47 }
262.48
262.49 /**
263.1 --- a/src/share/classes/javax/swing/plaf/basic/BasicToggleButtonUI.java Mon Nov 23 10:04:47 2009 +0000
263.2 +++ b/src/share/classes/javax/swing/plaf/basic/BasicToggleButtonUI.java Wed Nov 25 11:08:25 2009 -0800
263.3 @@ -25,6 +25,8 @@
263.4
263.5 package javax.swing.plaf.basic;
263.6
263.7 +import sun.awt.AppContext;
263.8 +
263.9 import java.awt.*;
263.10 import java.awt.event.*;
263.11
263.12 @@ -43,7 +45,7 @@
263.13 */
263.14 public class BasicToggleButtonUI extends BasicButtonUI {
263.15
263.16 - private final static BasicToggleButtonUI toggleButtonUI = new BasicToggleButtonUI();
263.17 + private static final Object BASIC_TOGGLE_BUTTON_UI_KEY = new Object();
263.18
263.19 private final static String propertyPrefix = "ToggleButton" + ".";
263.20
263.21 @@ -51,6 +53,13 @@
263.22 // Create PLAF
263.23 // ********************************
263.24 public static ComponentUI createUI(JComponent b) {
263.25 + AppContext appContext = AppContext.getAppContext();
263.26 + BasicToggleButtonUI toggleButtonUI =
263.27 + (BasicToggleButtonUI) appContext.get(BASIC_TOGGLE_BUTTON_UI_KEY);
263.28 + if (toggleButtonUI == null) {
263.29 + toggleButtonUI = new BasicToggleButtonUI();
263.30 + appContext.put(BASIC_TOGGLE_BUTTON_UI_KEY, toggleButtonUI);
263.31 + }
263.32 return toggleButtonUI;
263.33 }
263.34
264.1 --- a/src/share/classes/javax/swing/plaf/metal/MetalBumps.java Mon Nov 23 10:04:47 2009 +0000
264.2 +++ b/src/share/classes/javax/swing/plaf/metal/MetalBumps.java Wed Nov 25 11:08:25 2009 -0800
264.3 @@ -1,5 +1,5 @@
264.4 /*
264.5 - * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
264.6 + * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
264.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
264.8 *
264.9 * This code is free software; you can redistribute it and/or modify it
264.10 @@ -28,8 +28,9 @@
264.11 import java.awt.*;
264.12 import java.awt.image.*;
264.13 import javax.swing.*;
264.14 -import java.io.*;
264.15 -import java.util.*;
264.16 +import java.util.ArrayList;
264.17 +import java.util.List;
264.18 +import sun.awt.AppContext;
264.19
264.20 /**
264.21 * Implements the bumps used throughout the Metal Look and Feel.
264.22 @@ -49,19 +50,9 @@
264.23 protected Color shadowColor;
264.24 protected Color backColor;
264.25
264.26 - protected static Vector<BumpBuffer> buffers = new Vector<BumpBuffer>();
264.27 + private static final Object METAL_BUMPS = new Object();
264.28 protected BumpBuffer buffer;
264.29
264.30 - public MetalBumps( Dimension bumpArea ) {
264.31 - this( bumpArea.width, bumpArea.height );
264.32 - }
264.33 -
264.34 - public MetalBumps( int width, int height ) {
264.35 - this(width, height, MetalLookAndFeel.getPrimaryControlHighlight(),
264.36 - MetalLookAndFeel.getPrimaryControlDarkShadow(),
264.37 - MetalLookAndFeel.getPrimaryControlShadow());
264.38 - }
264.39 -
264.40 /**
264.41 * Creates MetalBumps of the specified size with the specified colors.
264.42 * If <code>newBackColor</code> is null, the background will be
264.43 @@ -73,26 +64,22 @@
264.44 setBumpColors( newTopColor, newShadowColor, newBackColor );
264.45 }
264.46
264.47 - private BumpBuffer getBuffer(GraphicsConfiguration gc, Color aTopColor,
264.48 - Color aShadowColor, Color aBackColor) {
264.49 - if (buffer != null && buffer.hasSameConfiguration(
264.50 - gc, aTopColor, aShadowColor, aBackColor)) {
264.51 - return buffer;
264.52 + private static BumpBuffer createBuffer(GraphicsConfiguration gc,
264.53 + Color topColor, Color shadowColor, Color backColor) {
264.54 + AppContext context = AppContext.getAppContext();
264.55 + List<BumpBuffer> buffers = (List<BumpBuffer>) context.get(METAL_BUMPS);
264.56 + if (buffers == null) {
264.57 + buffers = new ArrayList<BumpBuffer>();
264.58 + context.put(METAL_BUMPS, buffers);
264.59 }
264.60 - BumpBuffer result = null;
264.61 -
264.62 - for (BumpBuffer aBuffer : buffers) {
264.63 - if ( aBuffer.hasSameConfiguration(gc, aTopColor, aShadowColor,
264.64 - aBackColor)) {
264.65 - result = aBuffer;
264.66 - break;
264.67 + for (BumpBuffer buffer : buffers) {
264.68 + if (buffer.hasSameConfiguration(gc, topColor, shadowColor, backColor)) {
264.69 + return buffer;
264.70 }
264.71 }
264.72 - if (result == null) {
264.73 - result = new BumpBuffer(gc, topColor, shadowColor, backColor);
264.74 - buffers.addElement(result);
264.75 - }
264.76 - return result;
264.77 + BumpBuffer buffer = new BumpBuffer(gc, topColor, shadowColor, backColor);
264.78 + buffers.add(buffer);
264.79 + return buffer;
264.80 }
264.81
264.82 public void setBumpArea( Dimension bumpArea ) {
264.83 @@ -119,10 +106,12 @@
264.84 GraphicsConfiguration gc = (g instanceof Graphics2D) ?
264.85 ((Graphics2D) g).getDeviceConfiguration() : null;
264.86
264.87 - buffer = getBuffer(gc, topColor, shadowColor, backColor);
264.88 + if ((buffer == null) || !buffer.hasSameConfiguration(gc, topColor, shadowColor, backColor)) {
264.89 + buffer = createBuffer(gc, topColor, shadowColor, backColor);
264.90 + }
264.91
264.92 - int bufferWidth = buffer.getImageSize().width;
264.93 - int bufferHeight = buffer.getImageSize().height;
264.94 + int bufferWidth = BumpBuffer.IMAGE_SIZE;
264.95 + int bufferHeight = BumpBuffer.IMAGE_SIZE;
264.96 int iconWidth = getIconWidth();
264.97 int iconHeight = getIconHeight();
264.98 int x2 = x + iconWidth;
264.99 @@ -155,7 +144,6 @@
264.100 class BumpBuffer {
264.101
264.102 static final int IMAGE_SIZE = 64;
264.103 - static Dimension imageSize = new Dimension( IMAGE_SIZE, IMAGE_SIZE );
264.104
264.105 transient Image image;
264.106 Color topColor;
264.107 @@ -197,10 +185,6 @@
264.108 return image;
264.109 }
264.110
264.111 - public Dimension getImageSize() {
264.112 - return imageSize;
264.113 - }
264.114 -
264.115 /**
264.116 * Paints the bumps into the current image.
264.117 */
265.1 --- a/src/share/classes/javax/swing/plaf/metal/MetalButtonUI.java Mon Nov 23 10:04:47 2009 +0000
265.2 +++ b/src/share/classes/javax/swing/plaf/metal/MetalButtonUI.java Wed Nov 25 11:08:25 2009 -0800
265.3 @@ -26,6 +26,8 @@
265.4 package javax.swing.plaf.metal;
265.5
265.6 import sun.swing.SwingUtilities2;
265.7 +import sun.awt.AppContext;
265.8 +
265.9 import javax.swing.*;
265.10 import javax.swing.border.*;
265.11 import javax.swing.plaf.basic.*;
265.12 @@ -49,19 +51,25 @@
265.13 * @author Tom Santos
265.14 */
265.15 public class MetalButtonUI extends BasicButtonUI {
265.16 -
265.17 - private final static MetalButtonUI metalButtonUI = new MetalButtonUI();
265.18 -
265.19 // NOTE: These are not really needed, but at this point we can't pull
265.20 // them. Their values are updated purely for historical reasons.
265.21 protected Color focusColor;
265.22 protected Color selectColor;
265.23 protected Color disabledTextColor;
265.24
265.25 + private static final Object METAL_BUTTON_UI_KEY = new Object();
265.26 +
265.27 // ********************************
265.28 // Create PLAF
265.29 // ********************************
265.30 public static ComponentUI createUI(JComponent c) {
265.31 + AppContext appContext = AppContext.getAppContext();
265.32 + MetalButtonUI metalButtonUI =
265.33 + (MetalButtonUI) appContext.get(METAL_BUTTON_UI_KEY);
265.34 + if (metalButtonUI == null) {
265.35 + metalButtonUI = new MetalButtonUI();
265.36 + appContext.put(METAL_BUTTON_UI_KEY, metalButtonUI);
265.37 + }
265.38 return metalButtonUI;
265.39 }
265.40
266.1 --- a/src/share/classes/javax/swing/plaf/metal/MetalCheckBoxUI.java Mon Nov 23 10:04:47 2009 +0000
266.2 +++ b/src/share/classes/javax/swing/plaf/metal/MetalCheckBoxUI.java Wed Nov 25 11:08:25 2009 -0800
266.3 @@ -25,6 +25,8 @@
266.4
266.5 package javax.swing.plaf.metal;
266.6
266.7 +import sun.awt.AppContext;
266.8 +
266.9 import javax.swing.*;
266.10 import javax.swing.plaf.basic.BasicCheckBoxUI;
266.11
266.12 @@ -55,7 +57,7 @@
266.13 // of BasicCheckBoxUI because we want to pick up all the
266.14 // painting changes made in MetalRadioButtonUI.
266.15
266.16 - private final static MetalCheckBoxUI checkboxUI = new MetalCheckBoxUI();
266.17 + private static final Object METAL_CHECK_BOX_UI_KEY = new Object();
266.18
266.19 private final static String propertyPrefix = "CheckBox" + ".";
266.20
266.21 @@ -65,6 +67,13 @@
266.22 // Create PlAF
266.23 // ********************************
266.24 public static ComponentUI createUI(JComponent b) {
266.25 + AppContext appContext = AppContext.getAppContext();
266.26 + MetalCheckBoxUI checkboxUI =
266.27 + (MetalCheckBoxUI) appContext.get(METAL_CHECK_BOX_UI_KEY);
266.28 + if (checkboxUI == null) {
266.29 + checkboxUI = new MetalCheckBoxUI();
266.30 + appContext.put(METAL_CHECK_BOX_UI_KEY, checkboxUI);
266.31 + }
266.32 return checkboxUI;
266.33 }
266.34
267.1 --- a/src/share/classes/javax/swing/plaf/metal/MetalInternalFrameUI.java Mon Nov 23 10:04:47 2009 +0000
267.2 +++ b/src/share/classes/javax/swing/plaf/metal/MetalInternalFrameUI.java Wed Nov 25 11:08:25 2009 -0800
267.3 @@ -1,5 +1,5 @@
267.4 /*
267.5 - * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved.
267.6 + * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
267.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
267.8 *
267.9 * This code is free software; you can redistribute it and/or modify it
267.10 @@ -31,10 +31,8 @@
267.11 import javax.swing.event.*;
267.12 import javax.swing.border.*;
267.13 import javax.swing.plaf.basic.*;
267.14 -import java.util.EventListener;
267.15 import java.beans.PropertyChangeListener;
267.16 import java.beans.PropertyChangeEvent;
267.17 -import java.beans.PropertyVetoException;
267.18 import javax.swing.plaf.*;
267.19
267.20 /**
267.21 @@ -51,7 +49,7 @@
267.22 private static final Border handyEmptyBorder = new EmptyBorder(0,0,0,0);
267.23
267.24 protected static String IS_PALETTE = "JInternalFrame.isPalette";
267.25 -
267.26 + private static String IS_PALETTE_KEY = "JInternalFrame.isPalette";
267.27 private static String FRAME_TYPE = "JInternalFrame.frameType";
267.28 private static String NORMAL_FRAME = "normal";
267.29 private static String PALETTE_FRAME = "palette";
267.30 @@ -68,7 +66,7 @@
267.31 public void installUI(JComponent c) {
267.32 super.installUI(c);
267.33
267.34 - Object paletteProp = c.getClientProperty( IS_PALETTE );
267.35 + Object paletteProp = c.getClientProperty(IS_PALETTE_KEY);
267.36 if ( paletteProp != null ) {
267.37 setPalette( ((Boolean)paletteProp).booleanValue() );
267.38 }
267.39 @@ -187,7 +185,7 @@
267.40 ui.setFrameType( (String) e.getNewValue() );
267.41 }
267.42 }
267.43 - else if ( name.equals( IS_PALETTE ) )
267.44 + else if ( name.equals(IS_PALETTE_KEY) )
267.45 {
267.46 if ( e.getNewValue() != null )
267.47 {
268.1 --- a/src/share/classes/javax/swing/plaf/metal/MetalLabelUI.java Mon Nov 23 10:04:47 2009 +0000
268.2 +++ b/src/share/classes/javax/swing/plaf/metal/MetalLabelUI.java Wed Nov 25 11:08:25 2009 -0800
268.3 @@ -26,6 +26,8 @@
268.4 package javax.swing.plaf.metal;
268.5
268.6 import sun.swing.SwingUtilities2;
268.7 +import sun.awt.AppContext;
268.8 +
268.9 import javax.swing.*;
268.10 import javax.swing.plaf.*;
268.11 import javax.swing.plaf.basic.*;
268.12 @@ -51,15 +53,21 @@
268.13 * name in defaults table under the key "LabelUI".
268.14 */
268.15 protected static MetalLabelUI metalLabelUI = new MetalLabelUI();
268.16 - private final static MetalLabelUI SAFE_METAL_LABEL_UI = new MetalLabelUI();
268.17
268.18 + private static final Object METAL_LABEL_UI_KEY = new Object();
268.19
268.20 public static ComponentUI createUI(JComponent c) {
268.21 if (System.getSecurityManager() != null) {
268.22 - return SAFE_METAL_LABEL_UI;
268.23 - } else {
268.24 - return metalLabelUI;
268.25 + AppContext appContext = AppContext.getAppContext();
268.26 + MetalLabelUI safeMetalLabelUI =
268.27 + (MetalLabelUI) appContext.get(METAL_LABEL_UI_KEY);
268.28 + if (safeMetalLabelUI == null) {
268.29 + safeMetalLabelUI = new MetalLabelUI();
268.30 + appContext.put(METAL_LABEL_UI_KEY, safeMetalLabelUI);
268.31 + }
268.32 + return safeMetalLabelUI;
268.33 }
268.34 + return metalLabelUI;
268.35 }
268.36
268.37 /**
269.1 --- a/src/share/classes/javax/swing/plaf/metal/MetalRadioButtonUI.java Mon Nov 23 10:04:47 2009 +0000
269.2 +++ b/src/share/classes/javax/swing/plaf/metal/MetalRadioButtonUI.java Wed Nov 25 11:08:25 2009 -0800
269.3 @@ -26,6 +26,8 @@
269.4 package javax.swing.plaf.metal;
269.5
269.6 import sun.swing.SwingUtilities2;
269.7 +import sun.awt.AppContext;
269.8 +
269.9 import java.awt.*;
269.10 import java.awt.event.*;
269.11 import javax.swing.*;
269.12 @@ -53,7 +55,7 @@
269.13 */
269.14 public class MetalRadioButtonUI extends BasicRadioButtonUI {
269.15
269.16 - private static final MetalRadioButtonUI metalRadioButtonUI = new MetalRadioButtonUI();
269.17 + private static final Object METAL_RADIO_BUTTON_UI_KEY = new Object();
269.18
269.19 protected Color focusColor;
269.20 protected Color selectColor;
269.21 @@ -65,6 +67,13 @@
269.22 // Create PlAF
269.23 // ********************************
269.24 public static ComponentUI createUI(JComponent c) {
269.25 + AppContext appContext = AppContext.getAppContext();
269.26 + MetalRadioButtonUI metalRadioButtonUI =
269.27 + (MetalRadioButtonUI) appContext.get(METAL_RADIO_BUTTON_UI_KEY);
269.28 + if (metalRadioButtonUI == null) {
269.29 + metalRadioButtonUI = new MetalRadioButtonUI();
269.30 + appContext.put(METAL_RADIO_BUTTON_UI_KEY, metalRadioButtonUI);
269.31 + }
269.32 return metalRadioButtonUI;
269.33 }
269.34
270.1 --- a/src/share/classes/javax/swing/plaf/metal/MetalSliderUI.java Mon Nov 23 10:04:47 2009 +0000
270.2 +++ b/src/share/classes/javax/swing/plaf/metal/MetalSliderUI.java Wed Nov 25 11:08:25 2009 -0800
270.3 @@ -1,5 +1,5 @@
270.4 /*
270.5 - * Copyright 1998-2008 Sun Microsystems, Inc. All Rights Reserved.
270.6 + * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
270.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
270.8 *
270.9 * This code is free software; you can redistribute it and/or modify it
270.10 @@ -54,12 +54,13 @@
270.11
270.12 protected final int TICK_BUFFER = 4;
270.13 protected boolean filledSlider = false;
270.14 - // NOTE: these next three variables are currently unused.
270.15 + // NOTE: these next five variables are currently unused.
270.16 protected static Color thumbColor;
270.17 protected static Color highlightColor;
270.18 protected static Color darkShadowColor;
270.19 protected static int trackWidth;
270.20 protected static int tickLength;
270.21 + private int safeLength;
270.22
270.23 /**
270.24 * A default horizontal thumb <code>Icon</code>. This field might not be
270.25 @@ -107,7 +108,7 @@
270.26
270.27 public void installUI( JComponent c ) {
270.28 trackWidth = ((Integer)UIManager.get( "Slider.trackWidth" )).intValue();
270.29 - tickLength = ((Integer)UIManager.get( "Slider.majorTickLength" )).intValue();
270.30 + tickLength = safeLength = ((Integer)UIManager.get( "Slider.majorTickLength" )).intValue();
270.31 horizThumbIcon = SAFE_HORIZ_THUMB_ICON =
270.32 UIManager.getIcon( "Slider.horizontalThumbIcon" );
270.33 vertThumbIcon = SAFE_VERT_THUMB_ICON =
270.34 @@ -477,8 +478,8 @@
270.35 * determine the tick area rectangle.
270.36 */
270.37 public int getTickLength() {
270.38 - return slider.getOrientation() == JSlider.HORIZONTAL ? tickLength + TICK_BUFFER + 1 :
270.39 - tickLength + TICK_BUFFER + 3;
270.40 + return slider.getOrientation() == JSlider.HORIZONTAL ? safeLength + TICK_BUFFER + 1 :
270.41 + safeLength + TICK_BUFFER + 3;
270.42 }
270.43
270.44 /**
270.45 @@ -523,22 +524,22 @@
270.46
270.47 protected void paintMinorTickForHorizSlider( Graphics g, Rectangle tickBounds, int x ) {
270.48 g.setColor( slider.isEnabled() ? slider.getForeground() : MetalLookAndFeel.getControlShadow() );
270.49 - g.drawLine( x, TICK_BUFFER, x, TICK_BUFFER + (tickLength / 2) );
270.50 + g.drawLine( x, TICK_BUFFER, x, TICK_BUFFER + (safeLength / 2) );
270.51 }
270.52
270.53 protected void paintMajorTickForHorizSlider( Graphics g, Rectangle tickBounds, int x ) {
270.54 g.setColor( slider.isEnabled() ? slider.getForeground() : MetalLookAndFeel.getControlShadow() );
270.55 - g.drawLine( x, TICK_BUFFER , x, TICK_BUFFER + (tickLength - 1) );
270.56 + g.drawLine( x, TICK_BUFFER , x, TICK_BUFFER + (safeLength - 1) );
270.57 }
270.58
270.59 protected void paintMinorTickForVertSlider( Graphics g, Rectangle tickBounds, int y ) {
270.60 g.setColor( slider.isEnabled() ? slider.getForeground() : MetalLookAndFeel.getControlShadow() );
270.61
270.62 if (MetalUtils.isLeftToRight(slider)) {
270.63 - g.drawLine( TICK_BUFFER, y, TICK_BUFFER + (tickLength / 2), y );
270.64 + g.drawLine( TICK_BUFFER, y, TICK_BUFFER + (safeLength / 2), y );
270.65 }
270.66 else {
270.67 - g.drawLine( 0, y, tickLength/2, y );
270.68 + g.drawLine( 0, y, safeLength/2, y );
270.69 }
270.70 }
270.71
270.72 @@ -546,10 +547,10 @@
270.73 g.setColor( slider.isEnabled() ? slider.getForeground() : MetalLookAndFeel.getControlShadow() );
270.74
270.75 if (MetalUtils.isLeftToRight(slider)) {
270.76 - g.drawLine( TICK_BUFFER, y, TICK_BUFFER + tickLength, y );
270.77 + g.drawLine( TICK_BUFFER, y, TICK_BUFFER + safeLength, y );
270.78 }
270.79 else {
270.80 - g.drawLine( 0, y, tickLength, y );
270.81 + g.drawLine( 0, y, safeLength, y );
270.82 }
270.83 }
270.84 }
271.1 --- a/src/share/classes/javax/swing/plaf/metal/MetalToggleButtonUI.java Mon Nov 23 10:04:47 2009 +0000
271.2 +++ b/src/share/classes/javax/swing/plaf/metal/MetalToggleButtonUI.java Wed Nov 25 11:08:25 2009 -0800
271.3 @@ -26,6 +26,8 @@
271.4 package javax.swing.plaf.metal;
271.5
271.6 import sun.swing.SwingUtilities2;
271.7 +import sun.awt.AppContext;
271.8 +
271.9 import java.awt.*;
271.10 import java.awt.event.*;
271.11 import java.lang.ref.*;
271.12 @@ -55,7 +57,7 @@
271.13 */
271.14 public class MetalToggleButtonUI extends BasicToggleButtonUI {
271.15
271.16 - private static final MetalToggleButtonUI metalToggleButtonUI = new MetalToggleButtonUI();
271.17 + private static final Object METAL_TOGGLE_BUTTON_UI_KEY = new Object();
271.18
271.19 protected Color focusColor;
271.20 protected Color selectColor;
271.21 @@ -67,6 +69,13 @@
271.22 // Create PLAF
271.23 // ********************************
271.24 public static ComponentUI createUI(JComponent b) {
271.25 + AppContext appContext = AppContext.getAppContext();
271.26 + MetalToggleButtonUI metalToggleButtonUI =
271.27 + (MetalToggleButtonUI) appContext.get(METAL_TOGGLE_BUTTON_UI_KEY);
271.28 + if (metalToggleButtonUI == null) {
271.29 + metalToggleButtonUI = new MetalToggleButtonUI();
271.30 + appContext.put(METAL_TOGGLE_BUTTON_UI_KEY, metalToggleButtonUI);
271.31 + }
271.32 return metalToggleButtonUI;
271.33 }
271.34
272.1 --- a/src/share/classes/javax/swing/plaf/metal/OceanTheme.java Mon Nov 23 10:04:47 2009 +0000
272.2 +++ b/src/share/classes/javax/swing/plaf/metal/OceanTheme.java Wed Nov 25 11:08:25 2009 -0800
272.3 @@ -32,6 +32,7 @@
272.4 import javax.swing.plaf.*;
272.5 import sun.swing.SwingUtilities2;
272.6 import sun.swing.PrintColorUIResource;
272.7 +import sun.swing.SwingLazyValue;
272.8
272.9 /**
272.10 * The default theme for the {@code MetalLookAndFeel}.
272.11 @@ -128,7 +129,7 @@
272.12 * @throws NullPointerException if {@code table} is {@code null}
272.13 */
272.14 public void addCustomEntriesToTable(UIDefaults table) {
272.15 - Object focusBorder = new UIDefaults.ProxyLazyValue(
272.16 + Object focusBorder = new SwingLazyValue(
272.17 "javax.swing.plaf.BorderUIResource$LineBorderUIResource",
272.18 new Object[] {getPrimary1()});
272.19 // .30 0 DDE8F3 white secondary2
273.1 --- a/src/share/classes/javax/swing/plaf/synth/SynthTableUI.java Mon Nov 23 10:04:47 2009 +0000
273.2 +++ b/src/share/classes/javax/swing/plaf/synth/SynthTableUI.java Wed Nov 25 11:08:25 2009 -0800
273.3 @@ -638,7 +638,7 @@
273.4 if ((b == null || b instanceof UIResource
273.5 || component instanceof SynthBooleanTableCellRenderer)
273.6 && !table.isCellSelected(row, column)) {
273.7 - if (alternateColor != null && row % 2 == 0) {
273.8 + if (alternateColor != null && row % 2 != 0) {
273.9 component.setBackground(alternateColor);
273.10 }
273.11 }
274.1 --- a/src/share/classes/javax/swing/table/DefaultTableCellRenderer.java Mon Nov 23 10:04:47 2009 +0000
274.2 +++ b/src/share/classes/javax/swing/table/DefaultTableCellRenderer.java Wed Nov 25 11:08:25 2009 -0800
274.3 @@ -214,8 +214,9 @@
274.4 : table.getBackground();
274.5 if (background == null || background instanceof javax.swing.plaf.UIResource) {
274.6 Color alternateColor = DefaultLookup.getColor(this, ui, "Table.alternateRowColor");
274.7 - if (alternateColor != null && row % 2 == 0)
274.8 + if (alternateColor != null && row % 2 != 0) {
274.9 background = alternateColor;
274.10 + }
274.11 }
274.12 super.setForeground(unselectedForeground != null
274.13 ? unselectedForeground
275.1 --- a/src/share/classes/javax/swing/text/JTextComponent.java Mon Nov 23 10:04:47 2009 +0000
275.2 +++ b/src/share/classes/javax/swing/text/JTextComponent.java Wed Nov 25 11:08:25 2009 -0800
275.3 @@ -2069,7 +2069,7 @@
275.4 * width to match its own
275.5 */
275.6 public boolean getScrollableTracksViewportWidth() {
275.7 - JViewport port = SwingUtilities2.getViewport(this);
275.8 + JViewport port = SwingUtilities.getParentViewport(this);
275.9 if (port != null) {
275.10 return port.getWidth() > getPreferredSize().width;
275.11 }
275.12 @@ -2090,7 +2090,7 @@
275.13 * to match its own
275.14 */
275.15 public boolean getScrollableTracksViewportHeight() {
275.16 - JViewport port = SwingUtilities2.getViewport(this);
275.17 + JViewport port = SwingUtilities.getParentViewport(this);
275.18 if (port != null) {
275.19 return (port.getHeight() > getPreferredSize().height);
275.20 }
276.1 --- a/src/share/classes/sun/applet/AppletClassLoader.java Mon Nov 23 10:04:47 2009 +0000
276.2 +++ b/src/share/classes/sun/applet/AppletClassLoader.java Wed Nov 25 11:08:25 2009 -0800
276.3 @@ -1,5 +1,5 @@
276.4 /*
276.5 - * Copyright 1995-2005 Sun Microsystems, Inc. All Rights Reserved.
276.6 + * Copyright 1995-2009 Sun Microsystems, Inc. All Rights Reserved.
276.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
276.8 *
276.9 * This code is free software; you can redistribute it and/or modify it
276.10 @@ -51,6 +51,7 @@
276.11 import java.security.PermissionCollection;
276.12 import sun.awt.AppContext;
276.13 import sun.awt.SunToolkit;
276.14 +import sun.misc.IOUtils;
276.15 import sun.net.www.ParseUtil;
276.16 import sun.security.util.SecurityConstants;
276.17
276.18 @@ -331,36 +332,7 @@
276.19
276.20 byte[] b;
276.21 try {
276.22 - if (len != -1) {
276.23 - // Read exactly len bytes from the input stream
276.24 - b = new byte[len];
276.25 - while (len > 0) {
276.26 - int n = in.read(b, b.length - len, len);
276.27 - if (n == -1) {
276.28 - throw new IOException("unexpected EOF");
276.29 - }
276.30 - len -= n;
276.31 - }
276.32 - } else {
276.33 - // Read until end of stream is reached - use 8K buffer
276.34 - // to speed up performance [stanleyh]
276.35 - b = new byte[8192];
276.36 - int total = 0;
276.37 - while ((len = in.read(b, total, b.length - total)) != -1) {
276.38 - total += len;
276.39 - if (total >= b.length) {
276.40 - byte[] tmp = new byte[total * 2];
276.41 - System.arraycopy(b, 0, tmp, 0, total);
276.42 - b = tmp;
276.43 - }
276.44 - }
276.45 - // Trim array to correct size, if necessary
276.46 - if (total != b.length) {
276.47 - byte[] tmp = new byte[total];
276.48 - System.arraycopy(b, 0, tmp, 0, total);
276.49 - b = tmp;
276.50 - }
276.51 - }
276.52 + b = IOUtils.readFully(in, len, true);
276.53 } finally {
276.54 in.close();
276.55 }
277.1 --- a/src/share/classes/sun/awt/datatransfer/DataTransferer.java Mon Nov 23 10:04:47 2009 +0000
277.2 +++ b/src/share/classes/sun/awt/datatransfer/DataTransferer.java Wed Nov 25 11:08:25 2009 -0800
277.3 @@ -63,8 +63,6 @@
277.4 import java.lang.reflect.Method;
277.5 import java.lang.reflect.Modifier;
277.6
277.7 -import java.rmi.MarshalledObject;
277.8 -
277.9 import java.security.AccessControlContext;
277.10 import java.security.AccessControlException;
277.11 import java.security.AccessController;
277.12 @@ -494,6 +492,13 @@
277.13 }
277.14
277.15 /**
277.16 + * Returns {@code true} if the given type is a java.rmi.Remote.
277.17 + */
277.18 + public static boolean isRemote(Class<?> type) {
277.19 + return RMI.isRemote(type);
277.20 + }
277.21 +
277.22 + /**
277.23 * Returns an Iterator which traverses a SortedSet of Strings which are
277.24 * a total order of the standard character sets supported by the JRE. The
277.25 * ordering follows the same principles as DataFlavor.selectBestTextFlavor.
277.26 @@ -1360,7 +1365,7 @@
277.27
277.28 // Source data is an RMI object
277.29 } else if (flavor.isRepresentationClassRemote()) {
277.30 - MarshalledObject mo = new MarshalledObject(obj);
277.31 + Object mo = RMI.newMarshalledObject(obj);
277.32 ObjectOutputStream oos = new ObjectOutputStream(bos);
277.33 oos.writeObject(mo);
277.34 oos.close();
277.35 @@ -1671,7 +1676,7 @@
277.36 try {
277.37 byte[] ba = inputStreamToByteArray(str);
277.38 ObjectInputStream ois = new ObjectInputStream(new ByteArrayInputStream(ba));
277.39 - Object ret = ((MarshalledObject)(ois.readObject())).get();
277.40 + Object ret = RMI.getMarshalledObject(ois.readObject());
277.41 ois.close();
277.42 str.close();
277.43 return ret;
277.44 @@ -2669,8 +2674,12 @@
277.45 Integer.valueOf(0));
277.46 nonTextRepresentationsMap.put(java.io.Serializable.class,
277.47 Integer.valueOf(1));
277.48 - nonTextRepresentationsMap.put(java.rmi.Remote.class,
277.49 - Integer.valueOf(2));
277.50 +
277.51 + Class<?> remoteClass = RMI.remoteClass();
277.52 + if (remoteClass != null) {
277.53 + nonTextRepresentationsMap.put(remoteClass,
277.54 + Integer.valueOf(2));
277.55 + }
277.56
277.57 nonTextRepresentations =
277.58 Collections.unmodifiableMap(nonTextRepresentationsMap);
277.59 @@ -2900,4 +2909,95 @@
277.60 }
277.61 }
277.62 }
277.63 +
277.64 + /**
277.65 + * A class that provides access to java.rmi.Remote and java.rmi.MarshalledObject
277.66 + * without creating a static dependency.
277.67 + */
277.68 + private static class RMI {
277.69 + private static final Class<?> remoteClass = getClass("java.rmi.Remote");
277.70 + private static final Class<?> marshallObjectClass =
277.71 + getClass("java.rmi.MarshalledObject");
277.72 + private static final Constructor<?> marshallCtor =
277.73 + getConstructor(marshallObjectClass, Object.class);
277.74 + private static final Method marshallGet =
277.75 + getMethod(marshallObjectClass, "get");
277.76 +
277.77 + private static Class<?> getClass(String name) {
277.78 + try {
277.79 + return Class.forName(name, true, null);
277.80 + } catch (ClassNotFoundException e) {
277.81 + return null;
277.82 + }
277.83 + }
277.84 +
277.85 + private static Constructor<?> getConstructor(Class<?> c, Class<?>... types) {
277.86 + try {
277.87 + return (c == null) ? null : c.getDeclaredConstructor(types);
277.88 + } catch (NoSuchMethodException x) {
277.89 + throw new AssertionError(x);
277.90 + }
277.91 + }
277.92 +
277.93 + private static Method getMethod(Class<?> c, String name, Class<?>... types) {
277.94 + try {
277.95 + return (c == null) ? null : c.getMethod(name, types);
277.96 + } catch (NoSuchMethodException e) {
277.97 + throw new AssertionError(e);
277.98 + }
277.99 + }
277.100 +
277.101 + /**
277.102 + * Returns {@code true} if the given class is java.rmi.Remote.
277.103 + */
277.104 + static boolean isRemote(Class<?> c) {
277.105 + return (remoteClass == null) ? null : remoteClass.isAssignableFrom(c);
277.106 + }
277.107 +
277.108 + /**
277.109 + * Returns java.rmi.Remote.class if RMI is present; otherwise {@code null}.
277.110 + */
277.111 + static Class<?> remoteClass() {
277.112 + return remoteClass;
277.113 + }
277.114 +
277.115 + /**
277.116 + * Returns a new MarshalledObject containing the serialized representation
277.117 + * of the given object.
277.118 + */
277.119 + static Object newMarshalledObject(Object obj) throws IOException {
277.120 + try {
277.121 + return marshallCtor.newInstance(obj);
277.122 + } catch (InstantiationException x) {
277.123 + throw new AssertionError(x);
277.124 + } catch (IllegalAccessException x) {
277.125 + throw new AssertionError(x);
277.126 + } catch (InvocationTargetException x) {
277.127 + Throwable cause = x.getCause();
277.128 + if (cause instanceof IOException)
277.129 + throw (IOException)cause;
277.130 + throw new AssertionError(x);
277.131 + }
277.132 + }
277.133 +
277.134 + /**
277.135 + * Returns a new copy of the contained marshalled object.
277.136 + */
277.137 + static Object getMarshalledObject(Object obj)
277.138 + throws IOException, ClassNotFoundException
277.139 + {
277.140 + try {
277.141 + return marshallGet.invoke(obj);
277.142 + } catch (IllegalAccessException x) {
277.143 + throw new AssertionError(x);
277.144 + } catch (InvocationTargetException x) {
277.145 + Throwable cause = x.getCause();
277.146 + if (cause instanceof IOException)
277.147 + throw (IOException)cause;
277.148 + if (cause instanceof ClassNotFoundException)
277.149 + throw (ClassNotFoundException)cause;
277.150 + throw new AssertionError(x);
277.151 + }
277.152 + }
277.153 + }
277.154 }
278.1 --- a/src/share/classes/sun/awt/im/InputMethodManager.java Mon Nov 23 10:04:47 2009 +0000
278.2 +++ b/src/share/classes/sun/awt/im/InputMethodManager.java Wed Nov 25 11:08:25 2009 -0800
278.3 @@ -358,7 +358,9 @@
278.4 AppContext requesterAppContext = SunToolkit.targetToAppContext(requester);
278.5 synchronized (lock) {
278.6 SunToolkit.postEvent(requesterAppContext, event);
278.7 - lock.wait();
278.8 + while (!event.isDispatched()) {
278.9 + lock.wait();
278.10 + }
278.11 }
278.12
278.13 Throwable eventThrowable = event.getThrowable();
279.1 --- a/src/share/classes/sun/awt/image/ImageRepresentation.java Mon Nov 23 10:04:47 2009 +0000
279.2 +++ b/src/share/classes/sun/awt/image/ImageRepresentation.java Wed Nov 25 11:08:25 2009 -0800
279.3 @@ -336,10 +336,6 @@
279.4 public native void setICMpixels(int x, int y, int w, int h, int[] lut,
279.5 byte[] pix, int off, int scansize,
279.6 IntegerComponentRaster ict);
279.7 -
279.8 - public native void setBytePixels(int x, int y, int w, int h, byte[] pix,
279.9 - int off, int scansize,
279.10 - ByteComponentRaster bct, int chanOff);
279.11 public native int setDiffICM(int x, int y, int w, int h, int[] lut,
279.12 int transPix, int numLut, IndexColorModel icm,
279.13 byte[] pix, int off, int scansize,
279.14 @@ -450,27 +446,17 @@
279.15 (biRaster instanceof ByteComponentRaster) &&
279.16 (biRaster.getNumDataElements() == 1)){
279.17 ByteComponentRaster bt = (ByteComponentRaster) biRaster;
279.18 - if (w*h > 200) {
279.19 - if (off == 0 && scansize == w) {
279.20 - bt.putByteData(x, y, w, h, pix);
279.21 - }
279.22 - else {
279.23 - byte[] bpix = new byte[w];
279.24 - poff = off;
279.25 - for (int yoff=y; yoff < y+h; yoff++) {
279.26 - System.arraycopy(pix, poff, bpix, 0, w);
279.27 - bt.putByteData(x, yoff, w, 1, bpix);
279.28 - poff += scansize;
279.29 - }
279.30 - }
279.31 + if (off == 0 && scansize == w) {
279.32 + bt.putByteData(x, y, w, h, pix);
279.33 }
279.34 else {
279.35 - // Only is faster if #pixels
279.36 - // Note that setBytePixels modifies the raster directly
279.37 - // so we must mark it as changed afterwards
279.38 - setBytePixels(x, y, w, h, pix, off, scansize, bt,
279.39 - bt.getDataOffset(0));
279.40 - bt.markDirty();
279.41 + byte[] bpix = new byte[w];
279.42 + poff = off;
279.43 + for (int yoff=y; yoff < y+h; yoff++) {
279.44 + System.arraycopy(pix, poff, bpix, 0, w);
279.45 + bt.putByteData(x, yoff, w, 1, bpix);
279.46 + poff += scansize;
279.47 + }
279.48 }
279.49 }
279.50 else {
280.1 --- a/src/share/classes/sun/awt/shell/ShellFolder.java Mon Nov 23 10:04:47 2009 +0000
280.2 +++ b/src/share/classes/sun/awt/shell/ShellFolder.java Wed Nov 25 11:08:25 2009 -0800
280.3 @@ -201,6 +201,8 @@
280.4
280.5 private static ShellFolderManager shellFolderManager;
280.6
280.7 + private static Invoker invoker;
280.8 +
280.9 static {
280.10 String managerClassName = (String)Toolkit.getDefaultToolkit().
280.11 getDesktopProperty("Shell.shellFolderManager");
280.12 @@ -225,6 +227,8 @@
280.13 throw new Error ("Could not access Shell Folder Manager: "
280.14 + managerClass.getName());
280.15 }
280.16 +
280.17 + invoker = shellFolderManager.createInvoker();
280.18 }
280.19
280.20 /**
280.21 @@ -486,21 +490,6 @@
280.22 return null;
280.23 }
280.24
280.25 - private static Invoker invoker;
280.26 -
280.27 - /**
280.28 - * Provides the single access point to the {@link Invoker}. It is guaranteed that the value
280.29 - * returned by this method will be always the same.
280.30 - *
280.31 - * @return the singleton instance of {@link Invoker}
280.32 - */
280.33 - public static Invoker getInvoker() {
280.34 - if (invoker == null) {
280.35 - invoker = shellFolderManager.createInvoker();
280.36 - }
280.37 - return invoker;
280.38 - }
280.39 -
280.40 /**
280.41 * Invokes the {@code task} which doesn't throw checked exceptions
280.42 * from its {@code call} method. If invokation is interrupted then Thread.currentThread().isInterrupted() will
280.43 @@ -522,7 +511,7 @@
280.44 public static <T, E extends Throwable> T invoke(Callable<T> task, Class<E> exceptionClass)
280.45 throws InterruptedException, E {
280.46 try {
280.47 - return getInvoker().invoke(task);
280.48 + return invoker.invoke(task);
280.49 } catch (Exception e) {
280.50 if (e instanceof RuntimeException) {
280.51 // Rethrow unchecked exceptions
281.1 --- a/src/share/classes/sun/dyn/anon/AnonymousClassLoader.java Mon Nov 23 10:04:47 2009 +0000
281.2 +++ b/src/share/classes/sun/dyn/anon/AnonymousClassLoader.java Wed Nov 25 11:08:25 2009 -0800
281.3 @@ -26,9 +26,9 @@
281.4 package sun.dyn.anon;
281.5
281.6 import java.io.IOException;
281.7 -import java.io.InputStream;
281.8 import java.lang.reflect.InvocationTargetException;
281.9 import java.lang.reflect.Method;
281.10 +import sun.misc.IOUtils;
281.11
281.12 /**
281.13 * Anonymous class loader. Will load any valid classfile, producing
281.14 @@ -285,13 +285,6 @@
281.15 if (contentLength < 0)
281.16 throw new IOException("invalid content length "+contentLength);
281.17
281.18 - byte[] classFile = new byte[contentLength];
281.19 - InputStream tcs = connection.getInputStream();
281.20 - for (int fill = 0, nr; fill < classFile.length; fill += nr) {
281.21 - nr = tcs.read(classFile, fill, classFile.length - fill);
281.22 - if (nr < 0)
281.23 - throw new IOException("premature end of file");
281.24 - }
281.25 - return classFile;
281.26 + return IOUtils.readFully(connection.getInputStream(), contentLength, true);
281.27 }
281.28 }
282.1 --- a/src/share/classes/sun/font/Font2D.java Mon Nov 23 10:04:47 2009 +0000
282.2 +++ b/src/share/classes/sun/font/Font2D.java Wed Nov 25 11:08:25 2009 -0800
282.3 @@ -320,21 +320,6 @@
282.4 lastFontStrike = new SoftReference(strike);
282.5 StrikeCache.refStrike(strike);
282.6 return strike;
282.7 - } else {
282.8 - /* We have found a cleared reference that has not yet
282.9 - * been removed by the disposer.
282.10 - * If we make this reference unreachable by removing it
282.11 - * from the map,or overwriting it with a new reference to
282.12 - * a new strike, then it is possible it may never be
282.13 - * enqueued for disposal. That is the implication of
282.14 - * the docs for java.lang.ref. So on finding a cleared
282.15 - * reference, we need to dispose the native resources,
282.16 - * if they haven't already been freed.
282.17 - * The reference object needs to have a reference to
282.18 - * the disposer instance for this to occur.
282.19 - */
282.20 - ((StrikeCache.DisposableStrike)strikeRef)
282.21 - .getDisposer().dispose();
282.22 }
282.23 }
282.24 /* When we create a new FontStrike instance, we *must*
283.1 --- a/src/share/classes/sun/font/FontDesignMetrics.java Mon Nov 23 10:04:47 2009 +0000
283.2 +++ b/src/share/classes/sun/font/FontDesignMetrics.java Wed Nov 25 11:08:25 2009 -0800
283.3 @@ -171,7 +171,7 @@
283.4 * out we can clear the keys from the table.
283.5 */
283.6 private static class KeyReference extends SoftReference
283.7 - implements DisposerRecord {
283.8 + implements DisposerRecord, Disposer.PollDisposable {
283.9
283.10 static ReferenceQueue queue = Disposer.getQueue();
283.11
284.1 --- a/src/share/classes/sun/font/FontStrikeDisposer.java Mon Nov 23 10:04:47 2009 +0000
284.2 +++ b/src/share/classes/sun/font/FontStrikeDisposer.java Wed Nov 25 11:08:25 2009 -0800
284.3 @@ -25,6 +25,7 @@
284.4
284.5 package sun.font;
284.6
284.7 +import sun.java2d.Disposer;
284.8 import sun.java2d.DisposerRecord;
284.9
284.10 /*
284.11 @@ -49,7 +50,8 @@
284.12 * entries would be removed much more promptly than we need.
284.13 */
284.14
284.15 -class FontStrikeDisposer implements DisposerRecord {
284.16 +class FontStrikeDisposer
284.17 + implements DisposerRecord, Disposer.PollDisposable {
284.18
284.19 Font2D font2D;
284.20 FontStrikeDesc desc;
285.1 --- a/src/share/classes/sun/font/StrikeCache.java Mon Nov 23 10:04:47 2009 +0000
285.2 +++ b/src/share/classes/sun/font/StrikeCache.java Wed Nov 25 11:08:25 2009 -0800
285.3 @@ -254,9 +254,20 @@
285.4 // because they may be accessed on that thread at the time of the
285.5 // disposal (for example, when the accel. cache is invalidated)
285.6
285.7 - // REMIND: this look a bit heavyweight, but should be ok
285.8 - // because strike disposal is a relatively infrequent operation,
285.9 - // more worrisome is the necessity of getting a GC here.
285.10 + // Whilst this is a bit heavyweight, in most applications
285.11 + // strike disposal is a relatively infrequent operation, so it
285.12 + // doesn't matter. But in some tests that use vast numbers
285.13 + // of strikes, the switching back and forth is measurable.
285.14 + // So the "pollRemove" call is added to batch up the work.
285.15 + // If we are polling we know we've already been called back
285.16 + // and can directly dispose the record.
285.17 + // Also worrisome is the necessity of getting a GC here.
285.18 +
285.19 + if (Disposer.pollingQueue) {
285.20 + doDispose(disposer);
285.21 + return;
285.22 + }
285.23 +
285.24 RenderQueue rq = null;
285.25 GraphicsEnvironment ge =
285.26 GraphicsEnvironment.getLocalGraphicsEnvironment();
285.27 @@ -277,6 +288,7 @@
285.28 rq.flushAndInvokeNow(new Runnable() {
285.29 public void run() {
285.30 doDispose(disposer);
285.31 + Disposer.pollRemove();
285.32 }
285.33 });
285.34 } finally {
286.1 --- a/src/share/classes/sun/java2d/Disposer.java Mon Nov 23 10:04:47 2009 +0000
286.2 +++ b/src/share/classes/sun/java2d/Disposer.java Wed Nov 25 11:08:25 2009 -0800
286.3 @@ -29,6 +29,7 @@
286.4 import java.lang.ref.ReferenceQueue;
286.5 import java.lang.ref.PhantomReference;
286.6 import java.lang.ref.WeakReference;
286.7 +import java.util.ArrayList;
286.8 import java.util.Hashtable;
286.9
286.10 /**
286.11 @@ -146,6 +147,7 @@
286.12 rec.dispose();
286.13 obj = null;
286.14 rec = null;
286.15 + clearDeferredRecords();
286.16 } catch (Exception e) {
286.17 System.out.println("Exception while removing reference: " + e);
286.18 e.printStackTrace();
286.19 @@ -153,6 +155,85 @@
286.20 }
286.21 }
286.22
286.23 + /*
286.24 + * This is a marker interface that, if implemented, means it
286.25 + * doesn't acquire any special locks, and is safe to
286.26 + * be disposed in the poll loop on whatever thread
286.27 + * which happens to be the Toolkit thread, is in use.
286.28 + */
286.29 + public static interface PollDisposable {
286.30 + };
286.31 +
286.32 + private static ArrayList<DisposerRecord> deferredRecords = null;
286.33 +
286.34 + private static void clearDeferredRecords() {
286.35 + if (deferredRecords == null || deferredRecords.isEmpty()) {
286.36 + return;
286.37 + }
286.38 + for (int i=0;i<deferredRecords.size(); i++) {
286.39 + try {
286.40 + DisposerRecord rec = deferredRecords.get(i);
286.41 + rec.dispose();
286.42 + } catch (Exception e) {
286.43 + System.out.println("Exception while disposing deferred rec.");
286.44 + e.printStackTrace();
286.45 + }
286.46 + }
286.47 + deferredRecords.clear();
286.48 + }
286.49 +
286.50 + /*
286.51 + * Set to indicate the queue is presently being polled.
286.52 + */
286.53 + public static volatile boolean pollingQueue = false;
286.54 +
286.55 + /*
286.56 + * The pollRemove() method is called back from a dispose method
286.57 + * that is running on the toolkit thread and wants to
286.58 + * dispose any pending refs that are safe to be disposed
286.59 + * on that thread.
286.60 + */
286.61 + public static void pollRemove() {
286.62 +
286.63 + /* This should never be called recursively, so this check
286.64 + * is just a safeguard against the unexpected.
286.65 + */
286.66 + if (pollingQueue) {
286.67 + return;
286.68 + }
286.69 + Object obj;
286.70 + pollingQueue = true;
286.71 + int freed = 0;
286.72 + int deferred = 0;
286.73 + try {
286.74 + while ((obj = queue.poll()) != null
286.75 + && freed < 10000 && deferred < 100) {
286.76 + freed++;
286.77 + ((Reference)obj).clear();
286.78 + DisposerRecord rec = (DisposerRecord)records.remove(obj);
286.79 + if (rec instanceof PollDisposable) {
286.80 + rec.dispose();
286.81 + obj = null;
286.82 + rec = null;
286.83 + } else {
286.84 + if (rec == null) { // shouldn't happen, but just in case.
286.85 + continue;
286.86 + }
286.87 + deferred++;
286.88 + if (deferredRecords == null) {
286.89 + deferredRecords = new ArrayList<DisposerRecord>(5);
286.90 + }
286.91 + deferredRecords.add(rec);
286.92 + }
286.93 + }
286.94 + } catch (Exception e) {
286.95 + System.out.println("Exception while removing reference: " + e);
286.96 + e.printStackTrace();
286.97 + } finally {
286.98 + pollingQueue = false;
286.99 + }
286.100 + }
286.101 +
286.102 private static native void initIDs();
286.103
286.104 /*
287.1 --- a/src/share/classes/sun/java2d/SunGraphics2D.java Mon Nov 23 10:04:47 2009 +0000
287.2 +++ b/src/share/classes/sun/java2d/SunGraphics2D.java Wed Nov 25 11:08:25 2009 -0800
287.3 @@ -257,7 +257,6 @@
287.4 font = defaultFont;
287.5 }
287.6
287.7 - loops = sd.getRenderLoops(this);
287.8 setDevClip(sd.getBounds());
287.9 invalidatePipe();
287.10 }
287.11 @@ -367,6 +366,7 @@
287.12 shapepipe = invalidpipe;
287.13 textpipe = invalidpipe;
287.14 imagepipe = invalidpipe;
287.15 + loops = null;
287.16 }
287.17
287.18 public void validatePipe() {
288.1 --- a/src/share/classes/sun/java2d/SurfaceData.java Mon Nov 23 10:04:47 2009 +0000
288.2 +++ b/src/share/classes/sun/java2d/SurfaceData.java Wed Nov 25 11:08:25 2009 -0800
288.3 @@ -69,6 +69,7 @@
288.4 import sun.java2d.pipe.DrawImage;
288.5 import sun.awt.SunHints;
288.6 import sun.awt.image.SurfaceManager;
288.7 +import sun.java2d.pipe.LoopBasedPipe;
288.8
288.9 /**
288.10 * This class provides various pieces of information relevant to a
288.11 @@ -506,7 +507,6 @@
288.12 sg2d.textpipe = solidTextRenderer;
288.13 }
288.14 sg2d.shapepipe = colorPrimitives;
288.15 - sg2d.loops = getRenderLoops(sg2d);
288.16 // assert(sg2d.surfaceData == this);
288.17 }
288.18 } else if (sg2d.compositeState == sg2d.COMP_CUSTOM) {
288.19 @@ -603,8 +603,17 @@
288.20
288.21 sg2d.textpipe = getTextPipe(sg2d, false /* AA==OFF */);
288.22 sg2d.shapepipe = colorPrimitives;
288.23 + // assert(sg2d.surfaceData == this);
288.24 + }
288.25 +
288.26 + // check for loops
288.27 + if (sg2d.textpipe instanceof LoopBasedPipe ||
288.28 + sg2d.shapepipe instanceof LoopBasedPipe ||
288.29 + sg2d.fillpipe instanceof LoopBasedPipe ||
288.30 + sg2d.drawpipe instanceof LoopBasedPipe ||
288.31 + sg2d.imagepipe instanceof LoopBasedPipe)
288.32 + {
288.33 sg2d.loops = getRenderLoops(sg2d);
288.34 - // assert(sg2d.surfaceData == this);
288.35 }
288.36 }
288.37
289.1 --- a/src/share/classes/sun/java2d/pipe/AATextRenderer.java Mon Nov 23 10:04:47 2009 +0000
289.2 +++ b/src/share/classes/sun/java2d/pipe/AATextRenderer.java Wed Nov 25 11:08:25 2009 -0800
289.3 @@ -34,8 +34,9 @@
289.4 * a solid source colour to an opaque destination.
289.5 */
289.6
289.7 -public class AATextRenderer extends GlyphListLoopPipe {
289.8 -
289.9 +public class AATextRenderer extends GlyphListLoopPipe
289.10 + implements LoopBasedPipe
289.11 +{
289.12 protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) {
289.13 sg2d.loops.drawGlyphListAALoop.DrawGlyphListAA(sg2d, sg2d.surfaceData,
289.14 gl);
290.1 --- a/src/share/classes/sun/java2d/pipe/GlyphListLoopPipe.java Mon Nov 23 10:04:47 2009 +0000
290.2 +++ b/src/share/classes/sun/java2d/pipe/GlyphListLoopPipe.java Wed Nov 25 11:08:25 2009 -0800
290.3 @@ -36,8 +36,9 @@
290.4 * the installed loop may not match the glyphvector.
290.5 */
290.6
290.7 -public abstract class GlyphListLoopPipe extends GlyphListPipe {
290.8 -
290.9 +public abstract class GlyphListLoopPipe extends GlyphListPipe
290.10 + implements LoopBasedPipe
290.11 +{
290.12 protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl,
290.13 int aaHint) {
290.14 switch (aaHint) {
291.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
291.2 +++ b/src/share/classes/sun/java2d/pipe/LoopBasedPipe.java Wed Nov 25 11:08:25 2009 -0800
291.3 @@ -0,0 +1,37 @@
291.4 +/*
291.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
291.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
291.7 + *
291.8 + * This code is free software; you can redistribute it and/or modify it
291.9 + * under the terms of the GNU General Public License version 2 only, as
291.10 + * published by the Free Software Foundation. Sun designates this
291.11 + * particular file as subject to the "Classpath" exception as provided
291.12 + * by Sun in the LICENSE file that accompanied this code.
291.13 + *
291.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
291.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
291.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
291.17 + * version 2 for more details (a copy is included in the LICENSE file that
291.18 + * accompanied this code).
291.19 + *
291.20 + * You should have received a copy of the GNU General Public License version
291.21 + * 2 along with this work; if not, write to the Free Software Foundation,
291.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
291.23 + *
291.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
291.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
291.26 + * have any questions.
291.27 + */
291.28 +
291.29 +package sun.java2d.pipe;
291.30 +
291.31 +/**
291.32 + * This is a marker interface used by Pipes that need RenderLoops.
291.33 + * RenderLoops are validated in SurfaceData when a pipe is recognised to
291.34 + * implement this interface.
291.35 + *
291.36 + * @author Mario Torre <neugens@aicas.com>
291.37 + */
291.38 +public interface LoopBasedPipe {
291.39 +
291.40 +}
292.1 --- a/src/share/classes/sun/java2d/pipe/LoopPipe.java Mon Nov 23 10:04:47 2009 +0000
292.2 +++ b/src/share/classes/sun/java2d/pipe/LoopPipe.java Wed Nov 25 11:08:25 2009 -0800
292.3 @@ -46,7 +46,8 @@
292.4 public class LoopPipe
292.5 implements PixelDrawPipe,
292.6 PixelFillPipe,
292.7 - ShapeDrawPipe
292.8 + ShapeDrawPipe,
292.9 + LoopBasedPipe
292.10 {
292.11 final static RenderingEngine RenderEngine = RenderingEngine.getInstance();
292.12
293.1 --- a/src/share/classes/sun/java2d/pipe/SolidTextRenderer.java Mon Nov 23 10:04:47 2009 +0000
293.2 +++ b/src/share/classes/sun/java2d/pipe/SolidTextRenderer.java Wed Nov 25 11:08:25 2009 -0800
293.3 @@ -35,8 +35,9 @@
293.4 * a solid source colour to an opaque destination.
293.5 */
293.6
293.7 -public class SolidTextRenderer extends GlyphListLoopPipe {
293.8 -
293.9 +public class SolidTextRenderer extends GlyphListLoopPipe
293.10 + implements LoopBasedPipe
293.11 +{
293.12 protected void drawGlyphList(SunGraphics2D sg2d, GlyphList gl) {
293.13 sg2d.loops.drawGlyphListLoop.DrawGlyphList(sg2d, sg2d.surfaceData, gl);
293.14 }
294.1 --- a/src/share/classes/sun/java2d/pipe/SpanShapeRenderer.java Mon Nov 23 10:04:47 2009 +0000
294.2 +++ b/src/share/classes/sun/java2d/pipe/SpanShapeRenderer.java Wed Nov 25 11:08:25 2009 -0800
294.3 @@ -65,7 +65,9 @@
294.4 }
294.5 }
294.6
294.7 - public static class Simple extends SpanShapeRenderer {
294.8 + public static class Simple extends SpanShapeRenderer
294.9 + implements LoopBasedPipe
294.10 + {
294.11 public Object startSequence(SunGraphics2D sg, Shape s,
294.12 Rectangle devR, int[] bbox) {
294.13 return sg;
295.1 --- a/src/share/classes/sun/java2d/pisces/Renderer.java Mon Nov 23 10:04:47 2009 +0000
295.2 +++ b/src/share/classes/sun/java2d/pisces/Renderer.java Wed Nov 25 11:08:25 2009 -0800
295.3 @@ -775,10 +775,12 @@
295.4
295.5 // Free sorting arrays if larger than maximum size
295.6 private void crossingListFinished() {
295.7 - if (crossings.length > DEFAULT_CROSSINGS_SIZE) {
295.8 + if (crossings != null && crossings.length > DEFAULT_CROSSINGS_SIZE) {
295.9 crossings = new int[DEFAULT_CROSSINGS_SIZE];
295.10 }
295.11 - if (crossingIndices.length > DEFAULT_INDICES_SIZE) {
295.12 + if (crossingIndices != null &&
295.13 + crossingIndices.length > DEFAULT_INDICES_SIZE)
295.14 + {
295.15 crossingIndices = new int[DEFAULT_INDICES_SIZE];
295.16 }
295.17 }
296.1 --- a/src/share/classes/sun/management/AgentConfigurationError.java Mon Nov 23 10:04:47 2009 +0000
296.2 +++ b/src/share/classes/sun/management/AgentConfigurationError.java Wed Nov 25 11:08:25 2009 -0800
296.3 @@ -146,4 +146,6 @@
296.4 public String[] getParams() {
296.5 return params;
296.6 }
296.7 +
296.8 + private static final long serialVersionUID = 1211605593516195475L;
296.9 }
297.1 --- a/src/share/classes/sun/management/ClassLoadingImpl.java Mon Nov 23 10:04:47 2009 +0000
297.2 +++ b/src/share/classes/sun/management/ClassLoadingImpl.java Wed Nov 25 11:08:25 2009 -0800
297.3 @@ -71,6 +71,6 @@
297.4 native static void setVerboseClass(boolean value);
297.5
297.6 public ObjectName getObjectName() {
297.7 - return ObjectName.valueOf(ManagementFactory.CLASS_LOADING_MXBEAN_NAME);
297.8 + return Util.newObjectName(ManagementFactory.CLASS_LOADING_MXBEAN_NAME);
297.9 }
297.10 }
298.1 --- a/src/share/classes/sun/management/CompilationImpl.java Mon Nov 23 10:04:47 2009 +0000
298.2 +++ b/src/share/classes/sun/management/CompilationImpl.java Wed Nov 25 11:08:25 2009 -0800
298.3 @@ -70,7 +70,7 @@
298.4 }
298.5
298.6 public ObjectName getObjectName() {
298.7 - return ObjectName.valueOf(ManagementFactory.COMPILATION_MXBEAN_NAME);
298.8 + return Util.newObjectName(ManagementFactory.COMPILATION_MXBEAN_NAME);
298.9 }
298.10
298.11
299.1 --- a/src/share/classes/sun/management/Flag.java Mon Nov 23 10:04:47 2009 +0000
299.2 +++ b/src/share/classes/sun/management/Flag.java Wed Nov 25 11:08:25 2009 -0800
299.3 @@ -45,7 +45,7 @@
299.4 Flag(String name, Object value, boolean writeable,
299.5 boolean external, Origin origin) {
299.6 this.name = name;
299.7 - this.value = value;
299.8 + this.value = value == null ? "" : value ;
299.9 this.origin = origin;
299.10 this.writeable = writeable;
299.11 this.external = external;
299.12 @@ -64,8 +64,7 @@
299.13 }
299.14
299.15 VMOption getVMOption() {
299.16 - String val = value == null ? "" : value.toString();
299.17 - return new VMOption(name, val, writeable, origin);
299.18 + return new VMOption(name, value.toString(), writeable, origin);
299.19 }
299.20
299.21 static Flag getFlag(String name) {
300.1 --- a/src/share/classes/sun/management/GcInfoCompositeData.java Mon Nov 23 10:04:47 2009 +0000
300.2 +++ b/src/share/classes/sun/management/GcInfoCompositeData.java Wed Nov 25 11:08:25 2009 -0800
300.3 @@ -248,4 +248,5 @@
300.4 return baseGcInfoCompositeType;
300.5 }
300.6
300.7 + private static final long serialVersionUID = -5716428894085882742L;
300.8 }
301.1 --- a/src/share/classes/sun/management/HotSpotDiagnostic.java Mon Nov 23 10:04:47 2009 +0000
301.2 +++ b/src/share/classes/sun/management/HotSpotDiagnostic.java Wed Nov 25 11:08:25 2009 -0800
301.3 @@ -25,9 +25,9 @@
301.4
301.5 package sun.management;
301.6
301.7 -import java.util.*;
301.8 import java.io.IOException;
301.9 -import java.lang.reflect.Method;
301.10 +import java.util.ArrayList;
301.11 +import java.util.List;
301.12 import javax.management.ObjectName;
301.13
301.14 import com.sun.management.HotSpotDiagnosticMXBean;
301.15 @@ -117,6 +117,6 @@
301.16 }
301.17
301.18 public ObjectName getObjectName() {
301.19 - return ObjectName.valueOf("com.sun.management:type=HotSpotDiagnostic");
301.20 + return Util.newObjectName("com.sun.management:type=HotSpotDiagnostic");
301.21 }
301.22 }
302.1 --- a/src/share/classes/sun/management/HotspotInternal.java Mon Nov 23 10:04:47 2009 +0000
302.2 +++ b/src/share/classes/sun/management/HotspotInternal.java Wed Nov 25 11:08:25 2009 -0800
302.3 @@ -41,7 +41,7 @@
302.4
302.5 private final static String HOTSPOT_INTERNAL_MBEAN_NAME =
302.6 "sun.management:type=HotspotInternal";
302.7 - private static ObjectName objName = ObjectName.valueOf(HOTSPOT_INTERNAL_MBEAN_NAME);
302.8 + private static ObjectName objName = Util.newObjectName(HOTSPOT_INTERNAL_MBEAN_NAME);
302.9 private MBeanServer server = null;
302.10
302.11 /**
303.1 --- a/src/share/classes/sun/management/LazyCompositeData.java Mon Nov 23 10:04:47 2009 +0000
303.2 +++ b/src/share/classes/sun/management/LazyCompositeData.java Wed Nov 25 11:08:25 2009 -0800
303.3 @@ -192,4 +192,6 @@
303.4
303.5 return isTypeMatched(type1.getRowType(), type2.getRowType());
303.6 }
303.7 +
303.8 + private static final long serialVersionUID = -2190411934472666714L;
303.9 }
304.1 --- a/src/share/classes/sun/management/ManagementFactoryHelper.java Mon Nov 23 10:04:47 2009 +0000
304.2 +++ b/src/share/classes/sun/management/ManagementFactoryHelper.java Wed Nov 25 11:08:25 2009 -0800
304.3 @@ -40,7 +40,11 @@
304.4 import java.security.PrivilegedExceptionAction;
304.5 import sun.security.action.LoadLibraryAction;
304.6
304.7 +import java.util.logging.PlatformLoggingMXBean;
304.8 +import sun.util.logging.LoggingSupport;
304.9 +
304.10 import java.util.ArrayList;
304.11 +import java.util.Collections;
304.12 import java.util.List;
304.13 import com.sun.management.OSMBeanFactory;
304.14 import com.sun.management.HotSpotDiagnosticMXBean;
304.15 @@ -135,6 +139,54 @@
304.16 return result;
304.17 }
304.18
304.19 + public static List<PlatformLoggingMXBean> getLoggingMXBean() {
304.20 + if (LoggingSupport.isAvailable()) {
304.21 + return Collections.singletonList(createPlatformLoggingMXBean());
304.22 + } else {
304.23 + return Collections.emptyList();
304.24 + }
304.25 + }
304.26 +
304.27 + private final static String LOGGING_MXBEAN_NAME = "java.util.logging:type=Logging";
304.28 + private static PlatformLoggingMXBean createPlatformLoggingMXBean() {
304.29 + return new PlatformLoggingMXBean() {
304.30 + private volatile ObjectName objname; // created lazily
304.31 + @Override
304.32 + public ObjectName getObjectName() {
304.33 + ObjectName result = objname;
304.34 + if (result == null) {
304.35 + synchronized (this) {
304.36 + if (objname == null) {
304.37 + result = Util.newObjectName(LOGGING_MXBEAN_NAME);
304.38 + objname = result;
304.39 + }
304.40 + }
304.41 + }
304.42 + return result;
304.43 + }
304.44 +
304.45 + @Override
304.46 + public java.util.List<String> getLoggerNames() {
304.47 + return LoggingSupport.getLoggerNames();
304.48 + }
304.49 +
304.50 + @Override
304.51 + public String getLoggerLevel(String loggerName) {
304.52 + return LoggingSupport.getLoggerLevel(loggerName);
304.53 + }
304.54 +
304.55 + @Override
304.56 + public void setLoggerLevel(String loggerName, String levelName) {
304.57 + LoggingSupport.setLoggerLevel(loggerName, levelName);
304.58 + }
304.59 +
304.60 + @Override
304.61 + public String getParentLoggerName(String loggerName) {
304.62 + return LoggingSupport.getParentLoggerName(loggerName);
304.63 + }
304.64 + };
304.65 + }
304.66 +
304.67 public static List<BufferPoolMXBean> getBufferPoolMXBeans() {
304.68 List<BufferPoolMXBean> pools = new ArrayList<BufferPoolMXBean>(2);
304.69 pools.add(createBufferPoolMXBean(sun.misc.SharedSecrets.getJavaNioAccess()
304.70 @@ -160,7 +212,7 @@
304.71 if (result == null) {
304.72 synchronized (this) {
304.73 if (objname == null) {
304.74 - result = ObjectName.valueOf(BUFFER_POOL_MXBEAN_NAME +
304.75 + result = Util.newObjectName(BUFFER_POOL_MXBEAN_NAME +
304.76 ",name=" + pool.getName());
304.77 objname = result;
304.78 }
304.79 @@ -257,7 +309,7 @@
304.80 */
304.81 private static void addMBean(MBeanServer mbs, Object mbean, String mbeanName) {
304.82 try {
304.83 - final ObjectName objName = ObjectName.valueOf(mbeanName);
304.84 + final ObjectName objName = Util.newObjectName(mbeanName);
304.85
304.86 // inner class requires these fields to be final
304.87 final MBeanServer mbs0 = mbs;
304.88 @@ -317,7 +369,7 @@
304.89
304.90 private static void unregisterMBean(MBeanServer mbs, String mbeanName) {
304.91 try {
304.92 - final ObjectName objName = ObjectName.valueOf(mbeanName);
304.93 + final ObjectName objName = Util.newObjectName(mbeanName);
304.94
304.95 // inner class requires these fields to be final
304.96 final MBeanServer mbs0 = mbs;
305.1 --- a/src/share/classes/sun/management/MappedMXBeanType.java Mon Nov 23 10:04:47 2009 +0000
305.2 +++ b/src/share/classes/sun/management/MappedMXBeanType.java Wed Nov 25 11:08:25 2009 -0800
305.3 @@ -777,6 +777,7 @@
305.4 public boolean isValue(Object o) {
305.5 return false;
305.6 }
305.7 + private static final long serialVersionUID = -3413063475064374490L;
305.8 }
305.9 private static final OpenType inProgress;
305.10 static {
306.1 --- a/src/share/classes/sun/management/MemoryImpl.java Mon Nov 23 10:04:47 2009 +0000
306.2 +++ b/src/share/classes/sun/management/MemoryImpl.java Wed Nov 25 11:08:25 2009 -0800
306.3 @@ -34,15 +34,7 @@
306.4 import javax.management.ObjectName;
306.5 import javax.management.MBeanNotificationInfo;
306.6 import javax.management.Notification;
306.7 -import javax.management.NotificationEmitter;
306.8 -import javax.management.NotificationFilter;
306.9 -import javax.management.NotificationListener;
306.10 -import javax.management.ListenerNotFoundException;
306.11 import javax.management.openmbean.CompositeData;
306.12 -import java.util.List;
306.13 -import java.util.ArrayList;
306.14 -import java.util.ListIterator;
306.15 -import java.util.Collections;
306.16
306.17 /**
306.18 * Implementation class for the memory subsystem.
306.19 @@ -177,7 +169,7 @@
306.20 }
306.21
306.22 public ObjectName getObjectName() {
306.23 - return ObjectName.valueOf(ManagementFactory.MEMORY_MXBEAN_NAME);
306.24 + return Util.newObjectName(ManagementFactory.MEMORY_MXBEAN_NAME);
306.25 }
306.26
306.27 }
307.1 --- a/src/share/classes/sun/management/MemoryNotifInfoCompositeData.java Mon Nov 23 10:04:47 2009 +0000
307.2 +++ b/src/share/classes/sun/management/MemoryNotifInfoCompositeData.java Wed Nov 25 11:08:25 2009 -0800
307.3 @@ -127,4 +127,5 @@
307.4 }
307.5 }
307.6
307.7 + private static final long serialVersionUID = -1805123446483771291L;
307.8 }
308.1 --- a/src/share/classes/sun/management/MemoryUsageCompositeData.java Mon Nov 23 10:04:47 2009 +0000
308.2 +++ b/src/share/classes/sun/management/MemoryUsageCompositeData.java Wed Nov 25 11:08:25 2009 -0800
308.3 @@ -126,4 +126,6 @@
308.4 "Unexpected composite type for MemoryUsage");
308.5 }
308.6 }
308.7 +
308.8 + private static final long serialVersionUID = -8504291541083874143L;
308.9 }
309.1 --- a/src/share/classes/sun/management/MonitorInfoCompositeData.java Mon Nov 23 10:04:47 2009 +0000
309.2 +++ b/src/share/classes/sun/management/MonitorInfoCompositeData.java Wed Nov 25 11:08:25 2009 -0800
309.3 @@ -143,4 +143,6 @@
309.4 "Unexpected composite type for MonitorInfo");
309.5 }
309.6 }
309.7 +
309.8 + private static final long serialVersionUID = -5825215591822908529L;
309.9 }
310.1 --- a/src/share/classes/sun/management/OperatingSystemImpl.java Mon Nov 23 10:04:47 2009 +0000
310.2 +++ b/src/share/classes/sun/management/OperatingSystemImpl.java Wed Nov 25 11:08:25 2009 -0800
310.3 @@ -74,7 +74,7 @@
310.4 }
310.5 }
310.6 public ObjectName getObjectName() {
310.7 - return ObjectName.valueOf(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME);
310.8 + return Util.newObjectName(ManagementFactory.OPERATING_SYSTEM_MXBEAN_NAME);
310.9 }
310.10
310.11 }
311.1 --- a/src/share/classes/sun/management/RuntimeImpl.java Mon Nov 23 10:04:47 2009 +0000
311.2 +++ b/src/share/classes/sun/management/RuntimeImpl.java Wed Nov 25 11:08:25 2009 -0800
311.3 @@ -33,12 +33,6 @@
311.4 import java.util.Map;
311.5 import java.util.Set;
311.6 import java.util.Properties;
311.7 -import javax.management.openmbean.CompositeData;
311.8 -import javax.management.openmbean.CompositeDataSupport;
311.9 -import javax.management.openmbean.CompositeType;
311.10 -import javax.management.openmbean.OpenType;
311.11 -import javax.management.openmbean.SimpleType;
311.12 -import javax.management.openmbean.OpenDataException;
311.13 import javax.management.ObjectName;
311.14
311.15 /**
311.16 @@ -149,7 +143,7 @@
311.17 }
311.18
311.19 public ObjectName getObjectName() {
311.20 - return ObjectName.valueOf(ManagementFactory.RUNTIME_MXBEAN_NAME);
311.21 + return Util.newObjectName(ManagementFactory.RUNTIME_MXBEAN_NAME);
311.22 }
311.23
311.24 }
312.1 --- a/src/share/classes/sun/management/StackTraceElementCompositeData.java Mon Nov 23 10:04:47 2009 +0000
312.2 +++ b/src/share/classes/sun/management/StackTraceElementCompositeData.java Wed Nov 25 11:08:25 2009 -0800
312.3 @@ -120,4 +120,6 @@
312.4 "Unexpected composite type for StackTraceElement");
312.5 }
312.6 }
312.7 +
312.8 + private static final long serialVersionUID = -2704607706598396827L;
312.9 }
313.1 --- a/src/share/classes/sun/management/ThreadImpl.java Mon Nov 23 10:04:47 2009 +0000
313.2 +++ b/src/share/classes/sun/management/ThreadImpl.java Wed Nov 25 11:08:25 2009 -0800
313.3 @@ -29,10 +29,6 @@
313.4 import java.lang.management.ManagementFactory;
313.5
313.6 import java.lang.management.ThreadInfo;
313.7 -import java.lang.management.LockInfo;
313.8 -import java.lang.management.MonitorInfo;
313.9 -import java.util.Map;
313.10 -import java.util.HashMap;
313.11
313.12 import javax.management.ObjectName;
313.13
313.14 @@ -415,7 +411,7 @@
313.15 private static native void resetContentionTimes0(long tid);
313.16
313.17 public ObjectName getObjectName() {
313.18 - return ObjectName.valueOf(ManagementFactory.THREAD_MXBEAN_NAME);
313.19 + return Util.newObjectName(ManagementFactory.THREAD_MXBEAN_NAME);
313.20 }
313.21
313.22 }
314.1 --- a/src/share/classes/sun/management/ThreadInfoCompositeData.java Mon Nov 23 10:04:47 2009 +0000
314.2 +++ b/src/share/classes/sun/management/ThreadInfoCompositeData.java Wed Nov 25 11:08:25 2009 -0800
314.3 @@ -410,4 +410,6 @@
314.4
314.5 }
314.6 }
314.7 +
314.8 + private static final long serialVersionUID = 2464378539119753175L;
314.9 }
315.1 --- a/src/share/classes/sun/management/Util.java Mon Nov 23 10:04:47 2009 +0000
315.2 +++ b/src/share/classes/sun/management/Util.java Wed Nov 25 11:08:25 2009 -0800
315.3 @@ -25,26 +25,34 @@
315.4
315.5 package sun.management;
315.6
315.7 -import java.lang.management.*;
315.8 +import java.lang.management.ManagementPermission;
315.9 import java.util.List;
315.10 -import java.security.Permission;
315.11 import javax.management.ObjectName;
315.12 import javax.management.MalformedObjectNameException;
315.13
315.14 -import static java.lang.management.ManagementFactory.*;
315.15
315.16 -class Util {
315.17 +public class Util {
315.18 + private Util() {} // there are no instances of this class
315.19 +
315.20 static RuntimeException newException(Exception e) {
315.21 throw new RuntimeException(e);
315.22 }
315.23
315.24 private static final String[] EMPTY_STRING_ARRAY = new String[0];
315.25 static String[] toStringArray(List<String> list) {
315.26 - return (String[]) list.toArray(EMPTY_STRING_ARRAY);
315.27 + return list.toArray(EMPTY_STRING_ARRAY);
315.28 }
315.29
315.30 public static ObjectName newObjectName(String domainAndType, String name) {
315.31 - return ObjectName.valueOf(domainAndType + ",name=" + name);
315.32 + return newObjectName(domainAndType + ",name=" + name);
315.33 + }
315.34 +
315.35 + public static ObjectName newObjectName(String name) {
315.36 + try {
315.37 + return ObjectName.getInstance(name);
315.38 + } catch (MalformedObjectNameException e) {
315.39 + throw new IllegalArgumentException(e);
315.40 + }
315.41 }
315.42
315.43 private static ManagementPermission monitorPermission =
316.1 --- a/src/share/classes/sun/management/VMOptionCompositeData.java Mon Nov 23 10:04:47 2009 +0000
316.2 +++ b/src/share/classes/sun/management/VMOptionCompositeData.java Wed Nov 25 11:08:25 2009 -0800
316.3 @@ -128,4 +128,6 @@
316.4 "Unexpected composite type for VMOption");
316.5 }
316.6 }
316.7 +
316.8 + private static final long serialVersionUID = -2395573975093578470L;
316.9 }
317.1 --- a/src/share/classes/sun/management/counter/perf/ByteArrayCounterSnapshot.java Mon Nov 23 10:04:47 2009 +0000
317.2 +++ b/src/share/classes/sun/management/counter/perf/ByteArrayCounterSnapshot.java Wed Nov 25 11:08:25 2009 -0800
317.3 @@ -53,4 +53,6 @@
317.4 public byte byteAt(int index) {
317.5 return value[index];
317.6 }
317.7 +
317.8 + private static final long serialVersionUID = 1444793459838438979L;
317.9 }
318.1 --- a/src/share/classes/sun/management/counter/perf/InstrumentationException.java Mon Nov 23 10:04:47 2009 +0000
318.2 +++ b/src/share/classes/sun/management/counter/perf/InstrumentationException.java Wed Nov 25 11:08:25 2009 -0800
318.3 @@ -42,4 +42,6 @@
318.4 public InstrumentationException(String message) {
318.5 super(message);
318.6 }
318.7 +
318.8 + private static final long serialVersionUID = 8060117844393922797L;
318.9 }
319.1 --- a/src/share/classes/sun/management/counter/perf/LongArrayCounterSnapshot.java Mon Nov 23 10:04:47 2009 +0000
319.2 +++ b/src/share/classes/sun/management/counter/perf/LongArrayCounterSnapshot.java Wed Nov 25 11:08:25 2009 -0800
319.3 @@ -53,4 +53,6 @@
319.4 public long longAt(int index) {
319.5 return value[index];
319.6 }
319.7 +
319.8 + private static final long serialVersionUID = 3585870271405924292L;
319.9 }
320.1 --- a/src/share/classes/sun/management/counter/perf/LongCounterSnapshot.java Mon Nov 23 10:04:47 2009 +0000
320.2 +++ b/src/share/classes/sun/management/counter/perf/LongCounterSnapshot.java Wed Nov 25 11:08:25 2009 -0800
320.3 @@ -52,4 +52,6 @@
320.4 public long longValue() {
320.5 return value;
320.6 }
320.7 +
320.8 + private static final long serialVersionUID = 2054263861474565758L;
320.9 }
321.1 --- a/src/share/classes/sun/management/counter/perf/PerfByteArrayCounter.java Mon Nov 23 10:04:47 2009 +0000
321.2 +++ b/src/share/classes/sun/management/counter/perf/PerfByteArrayCounter.java Wed Nov 25 11:08:25 2009 -0800
321.3 @@ -88,4 +88,6 @@
321.4 getVectorLength(),
321.5 byteArrayValue());
321.6 }
321.7 +
321.8 + private static final long serialVersionUID = 2545474036937279921L;
321.9 }
322.1 --- a/src/share/classes/sun/management/counter/perf/PerfLongArrayCounter.java Mon Nov 23 10:04:47 2009 +0000
322.2 +++ b/src/share/classes/sun/management/counter/perf/PerfLongArrayCounter.java Wed Nov 25 11:08:25 2009 -0800
322.3 @@ -80,4 +80,6 @@
322.4 getVectorLength(),
322.5 longArrayValue());
322.6 }
322.7 +
322.8 + private static final long serialVersionUID = -2733617913045487126L;
322.9 }
323.1 --- a/src/share/classes/sun/management/counter/perf/PerfLongCounter.java Mon Nov 23 10:04:47 2009 +0000
323.2 +++ b/src/share/classes/sun/management/counter/perf/PerfLongCounter.java Wed Nov 25 11:08:25 2009 -0800
323.3 @@ -62,4 +62,6 @@
323.4 getFlags(),
323.5 longValue());
323.6 }
323.7 +
323.8 + private static final long serialVersionUID = 857711729279242948L;
323.9 }
324.1 --- a/src/share/classes/sun/management/counter/perf/PerfStringCounter.java Mon Nov 23 10:04:47 2009 +0000
324.2 +++ b/src/share/classes/sun/management/counter/perf/PerfStringCounter.java Wed Nov 25 11:08:25 2009 -0800
324.3 @@ -86,4 +86,5 @@
324.4 stringValue());
324.5 }
324.6
324.7 + private static final long serialVersionUID = 6802913433363692452L;
324.8 }
325.1 --- a/src/share/classes/sun/management/counter/perf/StringCounterSnapshot.java Mon Nov 23 10:04:47 2009 +0000
325.2 +++ b/src/share/classes/sun/management/counter/perf/StringCounterSnapshot.java Wed Nov 25 11:08:25 2009 -0800
325.3 @@ -49,4 +49,6 @@
325.4 public String stringValue() {
325.5 return value;
325.6 }
325.7 +
325.8 + private static final long serialVersionUID = 1132921539085572034L;
325.9 }
326.1 --- a/src/share/classes/sun/management/jmxremote/SingleEntryRegistry.java Mon Nov 23 10:04:47 2009 +0000
326.2 +++ b/src/share/classes/sun/management/jmxremote/SingleEntryRegistry.java Wed Nov 25 11:08:25 2009 -0800
326.3 @@ -86,4 +86,6 @@
326.4
326.5 private final String name;
326.6 private final Remote object;
326.7 +
326.8 + private static final long serialVersionUID = -4897238949499730950L;
326.9 }
327.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
327.2 +++ b/src/share/classes/sun/misc/IOUtils.java Wed Nov 25 11:08:25 2009 -0800
327.3 @@ -0,0 +1,80 @@
327.4 +/*
327.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
327.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
327.7 + *
327.8 + * This code is free software; you can redistribute it and/or modify it
327.9 + * under the terms of the GNU General Public License version 2 only, as
327.10 + * published by the Free Software Foundation. Sun designates this
327.11 + * particular file as subject to the "Classpath" exception as provided
327.12 + * by Sun in the LICENSE file that accompanied this code.
327.13 + *
327.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
327.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
327.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
327.17 + * version 2 for more details (a copy is included in the LICENSE file that
327.18 + * accompanied this code).
327.19 + *
327.20 + * You should have received a copy of the GNU General Public License version
327.21 + * 2 along with this work; if not, write to the Free Software Foundation,
327.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
327.23 + *
327.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
327.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
327.26 + * have any questions.
327.27 + */
327.28 +
327.29 +/**
327.30 + * IOUtils: A collection of IO-related public static methods.
327.31 + */
327.32 +
327.33 +package sun.misc;
327.34 +
327.35 +import java.io.EOFException;
327.36 +import java.io.IOException;
327.37 +import java.io.InputStream;
327.38 +import java.util.Arrays;
327.39 +
327.40 +public class IOUtils {
327.41 +
327.42 + /**
327.43 + * Read up to <code>length</code> of bytes from <code>in</code>
327.44 + * until EOF is detected.
327.45 + * @param in input stream, must not be null
327.46 + * @param length number of bytes to read, -1 or Integer.MAX_VALUE means
327.47 + * read as much as possible
327.48 + * @param readAll if true, an EOFException will be thrown if not enough
327.49 + * bytes are read. Ignored when length is -1 or Integer.MAX_VALUE
327.50 + * @return bytes read
327.51 + * @throws IOException Any IO error or a premature EOF is detected
327.52 + */
327.53 + public static byte[] readFully(InputStream is, int length, boolean readAll)
327.54 + throws IOException {
327.55 + byte[] output = {};
327.56 + if (length == -1) length = Integer.MAX_VALUE;
327.57 + int pos = 0;
327.58 + while (pos < length) {
327.59 + int bytesToRead;
327.60 + if (pos >= output.length) { // Only expand when there's no room
327.61 + bytesToRead = Math.min(length - pos, output.length + 1024);
327.62 + if (output.length < pos + bytesToRead) {
327.63 + output = Arrays.copyOf(output, pos + bytesToRead);
327.64 + }
327.65 + } else {
327.66 + bytesToRead = output.length - pos;
327.67 + }
327.68 + int cc = is.read(output, pos, bytesToRead);
327.69 + if (cc < 0) {
327.70 + if (readAll && length != Integer.MAX_VALUE) {
327.71 + throw new EOFException("Detect premature EOF");
327.72 + } else {
327.73 + if (output.length != pos) {
327.74 + output = Arrays.copyOf(output, pos);
327.75 + }
327.76 + break;
327.77 + }
327.78 + }
327.79 + pos += cc;
327.80 + }
327.81 + return output;
327.82 + }
327.83 +}
328.1 --- a/src/share/classes/sun/misc/Resource.java Mon Nov 23 10:04:47 2009 +0000
328.2 +++ b/src/share/classes/sun/misc/Resource.java Wed Nov 25 11:08:25 2009 -0800
328.3 @@ -1,5 +1,5 @@
328.4 /*
328.5 - * Copyright 1998-2006 Sun Microsystems, Inc. All Rights Reserved.
328.6 + * Copyright 1998-2009 Sun Microsystems, Inc. All Rights Reserved.
328.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
328.8 *
328.9 * This code is free software; you can redistribute it and/or modify it
328.10 @@ -25,14 +25,15 @@
328.11
328.12 package sun.misc;
328.13
328.14 +import java.io.EOFException;
328.15 import java.net.URL;
328.16 import java.io.IOException;
328.17 import java.io.InterruptedIOException;
328.18 import java.io.InputStream;
328.19 import java.security.CodeSigner;
328.20 import java.util.jar.Manifest;
328.21 -import java.util.jar.Attributes;
328.22 import java.nio.ByteBuffer;
328.23 +import java.util.Arrays;
328.24 import sun.nio.ByteBuffered;
328.25
328.26 /**
328.27 @@ -105,49 +106,37 @@
328.28 }
328.29
328.30 try {
328.31 - if (len != -1) {
328.32 - // Read exactly len bytes from the input stream
328.33 - b = new byte[len];
328.34 - while (len > 0) {
328.35 - int n = 0;
328.36 - try {
328.37 - n = in.read(b, b.length - len, len);
328.38 - } catch (InterruptedIOException iioe) {
328.39 - Thread.interrupted();
328.40 - isInterrupted = true;
328.41 + b = new byte[0];
328.42 + if (len == -1) len = Integer.MAX_VALUE;
328.43 + int pos = 0;
328.44 + while (pos < len) {
328.45 + int bytesToRead;
328.46 + if (pos >= b.length) { // Only expand when there's no room
328.47 + bytesToRead = Math.min(len - pos, b.length + 1024);
328.48 + if (b.length < pos + bytesToRead) {
328.49 + b = Arrays.copyOf(b, pos + bytesToRead);
328.50 }
328.51 - if (n == -1) {
328.52 - throw new IOException("unexpected EOF");
328.53 - }
328.54 - len -= n;
328.55 + } else {
328.56 + bytesToRead = b.length - pos;
328.57 }
328.58 - } else {
328.59 - // Read until end of stream is reached
328.60 - b = new byte[1024];
328.61 - int total = 0;
328.62 - for (;;) {
328.63 - len = 0;
328.64 - try {
328.65 - len = in.read(b, total, b.length - total);
328.66 - if (len == -1)
328.67 - break;
328.68 - } catch (InterruptedIOException iioe) {
328.69 - Thread.interrupted();
328.70 - isInterrupted = true;
328.71 - }
328.72 - total += len;
328.73 - if (total >= b.length) {
328.74 - byte[] tmp = new byte[total * 2];
328.75 - System.arraycopy(b, 0, tmp, 0, total);
328.76 - b = tmp;
328.77 + int cc = 0;
328.78 + try {
328.79 + cc = in.read(b, pos, bytesToRead);
328.80 + } catch (InterruptedIOException iioe) {
328.81 + Thread.interrupted();
328.82 + isInterrupted = true;
328.83 + }
328.84 + if (cc < 0) {
328.85 + if (len != Integer.MAX_VALUE) {
328.86 + throw new EOFException("Detect premature EOF");
328.87 + } else {
328.88 + if (b.length != pos) {
328.89 + b = Arrays.copyOf(b, pos);
328.90 + }
328.91 + break;
328.92 }
328.93 }
328.94 - // Trim array to correct size, if necessary
328.95 - if (total != b.length) {
328.96 - byte[] tmp = new byte[total];
328.97 - System.arraycopy(b, 0, tmp, 0, total);
328.98 - b = tmp;
328.99 - }
328.100 + pos += cc;
328.101 }
328.102 } finally {
328.103 try {
329.1 --- a/src/share/classes/sun/net/ftp/FtpClient.java Mon Nov 23 10:04:47 2009 +0000
329.2 +++ b/src/share/classes/sun/net/ftp/FtpClient.java Wed Nov 25 11:08:25 2009 -0800
329.3 @@ -1,5 +1,5 @@
329.4 /*
329.5 - * Copyright 1994-2008 Sun Microsystems, Inc. All Rights Reserved.
329.6 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
329.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
329.8 *
329.9 * This code is free software; you can redistribute it and/or modify it
329.10 @@ -22,794 +22,922 @@
329.11 * CA 95054 USA or visit www.sun.com if you need additional information or
329.12 * have any questions.
329.13 */
329.14 -
329.15 package sun.net.ftp;
329.16
329.17 -import java.util.StringTokenizer;
329.18 -import java.util.regex.*;
329.19 +import java.net.*;
329.20 import java.io.*;
329.21 -import java.net.*;
329.22 -import sun.net.TransferProtocolClient;
329.23 -import sun.net.TelnetInputStream;
329.24 -import sun.net.TelnetOutputStream;
329.25 -import sun.misc.RegexpPool;
329.26 -import java.security.AccessController;
329.27 -import java.security.PrivilegedAction;
329.28 +import java.util.Date;
329.29 +import java.util.List;
329.30 +import java.util.Iterator;
329.31
329.32 /**
329.33 - * This class implements the FTP client.
329.34 + * A class that implements the FTP protocol according to
329.35 + * RFCs <A href="http://www.ietf.org/rfc/rfc0959.txt">959</A>,
329.36 + * <A href="http://www.ietf.org/rfc/rfc2228.txt">2228</A>,
329.37 + * <A href="http://www.ietf.org/rfc/rfc2389.txt">2389</A>,
329.38 + * <A href="http://www.ietf.org/rfc/rfc2428.txt">2428</A>,
329.39 + * <A href="http://www.ietf.org/rfc/rfc3659.txt">3659</A>,
329.40 + * <A href="http://www.ietf.org/rfc/rfc4217.txt">4217</A>.
329.41 + * Which includes support for FTP over SSL/TLS (aka ftps).
329.42 *
329.43 - * @author Jonathan Payne
329.44 + * {@code FtpClient} provides all the functionalities of a typical FTP
329.45 + * client, like storing or retrieving files, listing or creating directories.
329.46 + * A typical usage would consist of connecting the client to the server,
329.47 + * log in, issue a few commands then logout.
329.48 + * Here is a code example:
329.49 + * <pre>
329.50 + * FtpClient cl = FtpClient.create();
329.51 + * cl.connect("ftp.gnu.org").login("anonymous", "john.doe@mydomain.com".toCharArray())).changeDirectory("pub/gnu");
329.52 + * Iterator<FtpDirEntry> dir = cl.listFiles();
329.53 + * while (dir.hasNext()) {
329.54 + * FtpDirEntry f = dir.next();
329.55 + * System.err.println(f.getName());
329.56 + * }
329.57 + * cl.close();
329.58 + * }
329.59 + * </pre>
329.60 + * <p><b>Error reporting:</b> There are, mostly, two families of errors that
329.61 + * can occur during an FTP session. The first kind are the network related issues
329.62 + * like a connection reset, and they are usually fatal to the session, meaning,
329.63 + * in all likelyhood the connection to the server has been lost and the session
329.64 + * should be restarted from scratch. These errors are reported by throwing an
329.65 + * {@link IOException}. The second kind are the errors reported by the FTP server,
329.66 + * like when trying to download a non-existing file for example. These errors
329.67 + * are usually non fatal to the session, meaning more commands can be sent to the
329.68 + * server. In these cases, a {@link FtpProtocolException} is thrown.</p>
329.69 + * <p>
329.70 + * It should be noted that this is not a thread-safe API, as it wouldn't make
329.71 + * too much sense, due to the very sequential nature of FTP, to provide a
329.72 + * client able to be manipulated from multiple threads.
329.73 + *
329.74 + * @since 1.7
329.75 */
329.76 +public abstract class FtpClient implements java.io.Closeable {
329.77
329.78 -public class FtpClient extends TransferProtocolClient {
329.79 - public static final int FTP_PORT = 21;
329.80 + private static final int FTP_PORT = 21;
329.81
329.82 - static int FTP_SUCCESS = 1;
329.83 - static int FTP_TRY_AGAIN = 2;
329.84 - static int FTP_ERROR = 3;
329.85 + public static enum TransferType {
329.86
329.87 - /** remember the ftp server name because we may need it */
329.88 - private String serverName = null;
329.89 + ASCII, BINARY, EBCDIC
329.90 + };
329.91
329.92 - /** socket for data transfer */
329.93 - private boolean replyPending = false;
329.94 - private boolean binaryMode = false;
329.95 - private boolean loggedIn = false;
329.96 -
329.97 - /** regexp pool of hosts for which we should connect directly, not Proxy
329.98 - * these are intialized from a property.
329.99 + /**
329.100 + * Returns the default FTP port number.
329.101 + *
329.102 + * @return the port number.
329.103 */
329.104 - private static RegexpPool nonProxyHostsPool = null;
329.105 -
329.106 - /** The string soucre of nonProxyHostsPool
329.107 - */
329.108 - private static String nonProxyHostsSource = null;
329.109 -
329.110 - /** last command issued */
329.111 - String command;
329.112 -
329.113 - /** The last reply code from the ftp daemon. */
329.114 - int lastReplyCode;
329.115 -
329.116 - /** Welcome message from the server, if any. */
329.117 - public String welcomeMsg;
329.118 -
329.119 -
329.120 - /* these methods are used to determine whether ftp urls are sent to */
329.121 - /* an http server instead of using a direct connection to the */
329.122 - /* host. They aren't used directly here. */
329.123 - /**
329.124 - * @return if the networking layer should send ftp connections through
329.125 - * a proxy
329.126 - */
329.127 - public static boolean getUseFtpProxy() {
329.128 - // if the ftp.proxyHost is set, use it!
329.129 - return (getFtpProxyHost() != null);
329.130 + public static final int defaultPort() {
329.131 + return FTP_PORT;
329.132 }
329.133
329.134 /**
329.135 - * @return the host to use, or null if none has been specified
329.136 + * Creates an instance of FtpClient. The client is not connected to any
329.137 + * server yet.
329.138 + *
329.139 */
329.140 - public static String getFtpProxyHost() {
329.141 - return java.security.AccessController.doPrivileged(
329.142 - new java.security.PrivilegedAction<String>() {
329.143 - public String run() {
329.144 - String result = System.getProperty("ftp.proxyHost");
329.145 - if (result == null) {
329.146 - result = System.getProperty("ftpProxyHost");
329.147 - }
329.148 - if (result == null) {
329.149 - // as a last resort we use the general one if ftp.useProxy
329.150 - // is true
329.151 - if (Boolean.getBoolean("ftp.useProxy")) {
329.152 - result = System.getProperty("proxyHost");
329.153 - }
329.154 - }
329.155 - return result;
329.156 - }
329.157 - });
329.158 + protected FtpClient() {
329.159 }
329.160
329.161 /**
329.162 - * @return the proxy port to use. Will default reasonably if not set.
329.163 + * Creates an instance of {@code FtpClient}. The client is not connected to any
329.164 + * server yet.
329.165 + *
329.166 + * @return the created {@code FtpClient}
329.167 */
329.168 - public static int getFtpProxyPort() {
329.169 - final int result[] = {80};
329.170 - java.security.AccessController.doPrivileged(
329.171 - new java.security.PrivilegedAction<Void>() {
329.172 - public Void run() {
329.173 -
329.174 - String tmp = System.getProperty("ftp.proxyPort");
329.175 - if (tmp == null) {
329.176 - // for compatibility with 1.0.2
329.177 - tmp = System.getProperty("ftpProxyPort");
329.178 - }
329.179 - if (tmp == null) {
329.180 - // as a last resort we use the general one if ftp.useProxy
329.181 - // is true
329.182 - if (Boolean.getBoolean("ftp.useProxy")) {
329.183 - tmp = System.getProperty("proxyPort");
329.184 - }
329.185 - }
329.186 - if (tmp != null) {
329.187 - result[0] = Integer.parseInt(tmp);
329.188 - }
329.189 - return null;
329.190 - }
329.191 - });
329.192 - return result[0];
329.193 - }
329.194 -
329.195 - public static boolean matchNonProxyHosts(String host) {
329.196 - synchronized (FtpClient.class) {
329.197 - String rawList = java.security.AccessController.doPrivileged(
329.198 - new sun.security.action.GetPropertyAction("ftp.nonProxyHosts"));
329.199 - if (rawList == null) {
329.200 - nonProxyHostsPool = null;
329.201 - } else {
329.202 - if (!rawList.equals(nonProxyHostsSource)) {
329.203 - RegexpPool pool = new RegexpPool();
329.204 - StringTokenizer st = new StringTokenizer(rawList, "|", false);
329.205 - try {
329.206 - while (st.hasMoreTokens()) {
329.207 - pool.add(st.nextToken().toLowerCase(), Boolean.TRUE);
329.208 - }
329.209 - } catch (sun.misc.REException ex) {
329.210 - System.err.println("Error in http.nonProxyHosts system property: " + ex);
329.211 - }
329.212 - nonProxyHostsPool = pool;
329.213 - }
329.214 - }
329.215 - nonProxyHostsSource = rawList;
329.216 - }
329.217 -
329.218 - if (nonProxyHostsPool == null) {
329.219 - return false;
329.220 - }
329.221 -
329.222 - if (nonProxyHostsPool.match(host) != null) {
329.223 - return true;
329.224 - } else {
329.225 - return false;
329.226 - }
329.227 + public static FtpClient create() {
329.228 + FtpClientProvider provider = FtpClientProvider.provider();
329.229 + return provider.createFtpClient();
329.230 }
329.231
329.232 /**
329.233 - * issue the QUIT command to the FTP server and close the connection.
329.234 + * Creates an instance of FtpClient and connects it to the specified
329.235 + * address.
329.236 *
329.237 - * @exception FtpProtocolException if an error occured
329.238 + * @param dest the {@code InetSocketAddress} to connect to.
329.239 + * @return The created {@code FtpClient}
329.240 + * @throws IOException if the connection fails
329.241 + * @see #connect(java.net.SocketAddress)
329.242 */
329.243 - public void closeServer() throws IOException {
329.244 - if (serverIsOpen()) {
329.245 - issueCommand("QUIT");
329.246 - super.closeServer();
329.247 + public static FtpClient create(InetSocketAddress dest) throws FtpProtocolException, IOException {
329.248 + FtpClient client = create();
329.249 + if (dest != null) {
329.250 + client.connect(dest);
329.251 }
329.252 + return client;
329.253 }
329.254
329.255 /**
329.256 - * Send a command to the FTP server.
329.257 + * Creates an instance of {@code FtpClient} and connects it to the
329.258 + * specified host on the default FTP port.
329.259 *
329.260 - * @param cmd String containing the command
329.261 - * @return reply code
329.262 - *
329.263 - * @exception FtpProtocolException if an error occured
329.264 + * @param dest the {@code String} containing the name of the host
329.265 + * to connect to.
329.266 + * @return The created {@code FtpClient}
329.267 + * @throws IOException if the connection fails.
329.268 + * @throws FtpProtocolException if the server rejected the connection
329.269 */
329.270 - protected int issueCommand(String cmd) throws IOException {
329.271 - command = cmd;
329.272 -
329.273 - int reply;
329.274 -
329.275 - while (replyPending) {
329.276 - replyPending = false;
329.277 - if (readReply() == FTP_ERROR)
329.278 - throw new FtpProtocolException("Error reading FTP pending reply\n");
329.279 - }
329.280 - do {
329.281 - sendServer(cmd + "\r\n");
329.282 - reply = readReply();
329.283 - } while (reply == FTP_TRY_AGAIN);
329.284 - return reply;
329.285 + public static FtpClient create(String dest) throws FtpProtocolException, IOException {
329.286 + return create(new InetSocketAddress(dest, FTP_PORT));
329.287 }
329.288
329.289 /**
329.290 - * Send a command to the FTP server and check for success.
329.291 + * Enables, or disables, the use of the <I>passive</I> mode. In that mode,
329.292 + * data connections are established by having the client connect to the server.
329.293 + * This is the recommended default mode as it will work best through
329.294 + * firewalls and NATs. If set to {@code false} the mode is said to be
329.295 + * <I>active</I> which means the server will connect back to the client
329.296 + * after a PORT command to establish a data connection.
329.297 *
329.298 - * @param cmd String containing the command
329.299 + * <p><b>Note:</b> Since the passive mode might not be supported by all
329.300 + * FTP servers, enabling it means the client will try to use it. If the
329.301 + * server rejects it, then the client will attempt to fall back to using
329.302 + * the <I>active</I> mode by issuing a {@code PORT} command instead.</p>
329.303 *
329.304 - * @exception FtpProtocolException if an error occured
329.305 + * @param passive {@code true} to force passive mode.
329.306 + * @return This FtpClient
329.307 + * @see #isPassiveModeEnabled()
329.308 */
329.309 - protected void issueCommandCheck(String cmd) throws IOException {
329.310 - if (issueCommand(cmd) != FTP_SUCCESS)
329.311 - throw new FtpProtocolException(cmd + ":" + getResponseString());
329.312 + public abstract FtpClient enablePassiveMode(boolean passive);
329.313 +
329.314 + /**
329.315 + * Tests whether passive mode is enabled.
329.316 + *
329.317 + * @return {@code true} if the passive mode has been enabled.
329.318 + * @see #enablePassiveMode(boolean)
329.319 + */
329.320 + public abstract boolean isPassiveModeEnabled();
329.321 +
329.322 + /**
329.323 + * Sets the default timeout value to use when connecting to the server,
329.324 + *
329.325 + * @param timeout the timeout value, in milliseconds, to use for the connect
329.326 + * operation. A value of zero or less, means use the default timeout.
329.327 + *
329.328 + * @return This FtpClient
329.329 + */
329.330 + public abstract FtpClient setConnectTimeout(int timeout);
329.331 +
329.332 + /**
329.333 + * Returns the current default connection timeout value.
329.334 + *
329.335 + * @return the value, in milliseconds, of the current connect timeout.
329.336 + * @see #setConnectTimeout(int)
329.337 + */
329.338 + public abstract int getConnectTimeout();
329.339 +
329.340 + /**
329.341 + * Sets the timeout value to use when reading from the server,
329.342 + *
329.343 + * @param timeout the timeout value, in milliseconds, to use for the read
329.344 + * operation. A value of zero or less, means use the default timeout.
329.345 + * @return This FtpClient
329.346 + */
329.347 + public abstract FtpClient setReadTimeout(int timeout);
329.348 +
329.349 + /**
329.350 + * Returns the current read timeout value.
329.351 + *
329.352 + * @return the value, in milliseconds, of the current read timeout.
329.353 + * @see #setReadTimeout(int)
329.354 + */
329.355 + public abstract int getReadTimeout();
329.356 +
329.357 + /**
329.358 + * Set the {@code Proxy} to be used for the next connection.
329.359 + * If the client is already connected, it doesn't affect the current
329.360 + * connection. However it is not recommended to change this during a session.
329.361 + *
329.362 + * @param p the {@code Proxy} to use, or {@code null} for no proxy.
329.363 + * @return This FtpClient
329.364 + */
329.365 + public abstract FtpClient setProxy(Proxy p);
329.366 +
329.367 + /**
329.368 + * Get the proxy of this FtpClient
329.369 + *
329.370 + * @return the {@code Proxy}, this client is using, or {@code null}
329.371 + * if none is used.
329.372 + * @see #setProxy(Proxy)
329.373 + */
329.374 + public abstract Proxy getProxy();
329.375 +
329.376 + /**
329.377 + * Tests whether this client is connected or not to a server.
329.378 + *
329.379 + * @return {@code true} if the client is connected.
329.380 + */
329.381 + public abstract boolean isConnected();
329.382 +
329.383 + /**
329.384 + * Connects the {@code FtpClient} to the specified destination server.
329.385 + *
329.386 + * @param dest the address of the destination server
329.387 + * @return this FtpClient
329.388 + * @throws IOException if connection failed.
329.389 + * @throws SecurityException if there is a SecurityManager installed and it
329.390 + * denied the authorization to connect to the destination.
329.391 + * @throws FtpProtocolException
329.392 + */
329.393 + public abstract FtpClient connect(SocketAddress dest) throws FtpProtocolException, IOException;
329.394 +
329.395 + /**
329.396 + * Connects the FtpClient to the specified destination server.
329.397 + *
329.398 + * @param dest the address of the destination server
329.399 + * @param timeout the value, in milliseconds, to use as a connection timeout
329.400 + * @return this FtpClient
329.401 + * @throws IOException if connection failed.
329.402 + * @throws SecurityException if there is a SecurityManager installed and it
329.403 + * denied the authorization to connect to the destination.
329.404 + * @throws FtpProtocolException
329.405 + */
329.406 + public abstract FtpClient connect(SocketAddress dest, int timeout) throws FtpProtocolException, IOException;
329.407 +
329.408 + /**
329.409 + * Retrieves the address of the FTP server this client is connected to.
329.410 + *
329.411 + * @return the {@link SocketAddress} of the server, or {@code null} if this
329.412 + * client is not connected yet.
329.413 + */
329.414 + public abstract SocketAddress getServerAddress();
329.415 +
329.416 + /**
329.417 + * Attempts to log on the server with the specified user name and password.
329.418 + *
329.419 + * @param user The user name
329.420 + * @param password The password for that user
329.421 + * @return this FtpClient
329.422 + * @throws IOException if an error occured during the transmission
329.423 + * @throws FtpProtocolException if the login was refused by the server
329.424 + */
329.425 + public abstract FtpClient login(String user, char[] password) throws FtpProtocolException, IOException;
329.426 +
329.427 + /**
329.428 + * Attempts to log on the server with the specified user name, password and
329.429 + * account name.
329.430 + *
329.431 + * @param user The user name
329.432 + * @param password The password for that user.
329.433 + * @param account The account name for that user.
329.434 + * @return this FtpClient
329.435 + * @throws IOException if an error occurs during the transmission.
329.436 + * @throws FtpProtocolException if the login was refused by the server
329.437 + */
329.438 + public abstract FtpClient login(String user, char[] password, String account) throws FtpProtocolException, IOException;
329.439 +
329.440 + /**
329.441 + * Closes the current connection. Logs out the current user, if any, by
329.442 + * issuing the QUIT command to the server.
329.443 + * This is in effect terminates the current
329.444 + * session and the connection to the server will be closed.
329.445 + * <p>After a close, the client can then be connected to another server
329.446 + * to start an entirely different session.</P>
329.447 + *
329.448 + * @throws IOException if an error occurs during transmission
329.449 + */
329.450 + public abstract void close() throws IOException;
329.451 +
329.452 + /**
329.453 + * Checks whether the client is logged in to the server or not.
329.454 + *
329.455 + * @return {@code true} if the client has already completed a login.
329.456 + */
329.457 + public abstract boolean isLoggedIn();
329.458 +
329.459 + /**
329.460 + * Changes to a specific directory on a remote FTP server
329.461 + *
329.462 + * @param remoteDirectory path of the directory to CD to.
329.463 + * @return this FtpClient
329.464 + * @throws IOException if an error occurs during the transmission.
329.465 + * @throws FtpProtocolException if the command was refused by the server
329.466 + */
329.467 + public abstract FtpClient changeDirectory(String remoteDirectory) throws FtpProtocolException, IOException;
329.468 +
329.469 + /**
329.470 + * Changes to the parent directory, sending the CDUP command to the server.
329.471 + *
329.472 + * @return this FtpClient
329.473 + * @throws IOException if an error occurs during the transmission.
329.474 + * @throws FtpProtocolException if the command was refused by the server
329.475 + */
329.476 + public abstract FtpClient changeToParentDirectory() throws FtpProtocolException, IOException;
329.477 +
329.478 + /**
329.479 + * Retrieve the server current working directory using the PWD command.
329.480 + *
329.481 + * @return a {@code String} containing the current working directory
329.482 + * @throws IOException if an error occurs during transmission
329.483 + * @throws FtpProtocolException if the command was refused by the server,
329.484 + */
329.485 + public abstract String getWorkingDirectory() throws FtpProtocolException, IOException;
329.486 +
329.487 + /**
329.488 + * Sets the restart offset to the specified value. That value will be
329.489 + * sent through a {@code REST} command to server before the next file
329.490 + * transfer and has the effect of resuming a file transfer from the
329.491 + * specified point. After the transfer the restart offset is set back to
329.492 + * zero.
329.493 + *
329.494 + * @param offset the offset in the remote file at which to start the next
329.495 + * transfer. This must be a value greater than or equal to zero.
329.496 + * @return this FtpClient
329.497 + * @throws IllegalArgumentException if the offset is negative.
329.498 + */
329.499 + public abstract FtpClient setRestartOffset(long offset);
329.500 +
329.501 + /**
329.502 + * Retrieves a file from the ftp server and writes its content to the specified
329.503 + * {@code OutputStream}.
329.504 + * <p>If the restart offset was set, then a {@code REST} command will be
329.505 + * sent before the {@code RETR} in order to restart the tranfer from the specified
329.506 + * offset.</p>
329.507 + * <p>The {@code OutputStream} is not closed by this method at the end
329.508 + * of the transfer. </p>
329.509 + * <p>This method will block until the transfer is complete or an exception
329.510 + * is thrown.</p>
329.511 + *
329.512 + * @param name a {@code String} containing the name of the file to
329.513 + * retreive from the server.
329.514 + * @param local the {@code OutputStream} the file should be written to.
329.515 + * @return this FtpClient
329.516 + * @throws IOException if the transfer fails.
329.517 + * @throws FtpProtocolException if the command was refused by the server
329.518 + * @see #setRestartOffset(long)
329.519 + */
329.520 + public abstract FtpClient getFile(String name, OutputStream local) throws FtpProtocolException, IOException;
329.521 +
329.522 + /**
329.523 + * Retrieves a file from the ftp server, using the {@code RETR} command, and
329.524 + * returns the InputStream from the established data connection.
329.525 + * {@link #completePending()} <b>has</b> to be called once the application
329.526 + * is done reading from the returned stream.
329.527 + * <p>If the restart offset was set, then a {@code REST} command will be
329.528 + * sent before the {@code RETR} in order to restart the tranfer from the specified
329.529 + * offset.</p>
329.530 + *
329.531 + * @param name the name of the remote file
329.532 + * @return the {@link java.io.InputStream} from the data connection
329.533 + * @throws IOException if an error occured during the transmission.
329.534 + * @throws FtpProtocolException if the command was refused by the server
329.535 + * @see #setRestartOffset(long)
329.536 + */
329.537 + public abstract InputStream getFileStream(String name) throws FtpProtocolException, IOException;
329.538 +
329.539 + /**
329.540 + * Transfers a file from the client to the server (aka a <I>put</I>)
329.541 + * by sending the STOR command, and returns the {@code OutputStream}
329.542 + * from the established data connection.
329.543 + *
329.544 + * A new file is created at the server site if the file specified does
329.545 + * not already exist.
329.546 + *
329.547 + * {@link #completePending()} <b>has</b> to be called once the application
329.548 + * is finished writing to the returned stream.
329.549 + *
329.550 + * @param name the name of the remote file to write.
329.551 + * @return the {@link java.io.OutputStream} from the data connection or
329.552 + * {@code null} if the command was unsuccessful.
329.553 + * @throws IOException if an error occured during the transmission.
329.554 + * @throws FtpProtocolException if the command was rejected by the server
329.555 + */
329.556 + public OutputStream putFileStream(String name) throws FtpProtocolException, IOException {
329.557 + return putFileStream(name, false);
329.558 }
329.559
329.560 /**
329.561 - * Read the reply from the FTP server.
329.562 + * Transfers a file from the client to the server (aka a <I>put</I>)
329.563 + * by sending the STOR or STOU command, depending on the
329.564 + * {@code unique} argument, and returns the {@code OutputStream}
329.565 + * from the established data connection.
329.566 + * {@link #completePending()} <b>has</b> to be called once the application
329.567 + * is finished writing to the stream.
329.568 *
329.569 - * @return FTP_SUCCESS or FTP_ERROR depending on success
329.570 - * @exception FtpProtocolException if an error occured
329.571 + * A new file is created at the server site if the file specified does
329.572 + * not already exist.
329.573 + *
329.574 + * If {@code unique} is set to {@code true}, the resultant file
329.575 + * is to be created under a name unique to that directory, meaning
329.576 + * it will not overwrite an existing file, instead the server will
329.577 + * generate a new, unique, file name.
329.578 + * The name of the remote file can be retrieved, after completion of the
329.579 + * transfer, by calling {@link #getLastFileName()}.
329.580 + *
329.581 + * @param name the name of the remote file to write.
329.582 + * @param unique {@code true} if the remote files should be unique,
329.583 + * in which case the STOU command will be used.
329.584 + * @return the {@link java.io.OutputStream} from the data connection.
329.585 + * @throws IOException if an error occured during the transmission.
329.586 + * @throws FtpProtocolException if the command was rejected by the server
329.587 */
329.588 - protected int readReply() throws IOException {
329.589 - lastReplyCode = readServerResponse();
329.590 + public abstract OutputStream putFileStream(String name, boolean unique) throws FtpProtocolException, IOException;
329.591
329.592 - switch (lastReplyCode / 100) {
329.593 - case 1:
329.594 - replyPending = true;
329.595 - /* falls into ... */
329.596 -
329.597 - case 2:
329.598 - case 3:
329.599 - return FTP_SUCCESS;
329.600 -
329.601 - case 5:
329.602 - if (lastReplyCode == 530) {
329.603 - if (!loggedIn) {
329.604 - throw new FtpLoginException("Not logged in");
329.605 - }
329.606 - return FTP_ERROR;
329.607 - }
329.608 - if (lastReplyCode == 550) {
329.609 - throw new FileNotFoundException(command + ": " + getResponseString());
329.610 - }
329.611 - }
329.612 -
329.613 - /* this statement is not reached */
329.614 - return FTP_ERROR;
329.615 + /**
329.616 + * Transfers a file from the client to the server (aka a <I>put</I>)
329.617 + * by sending the STOR or STOU command, depending on the
329.618 + * {@code unique} argument. The content of the {@code InputStream}
329.619 + * passed in argument is written into the remote file, overwriting any
329.620 + * existing data.
329.621 + *
329.622 + * A new file is created at the server site if the file specified does
329.623 + * not already exist.
329.624 + *
329.625 + * If {@code unique} is set to {@code true}, the resultant file
329.626 + * is to be created under a name unique to that directory, meaning
329.627 + * it will not overwrite an existing file, instead the server will
329.628 + * generate a new, unique, file name.
329.629 + * The name of the remote file can be retrieved, after completion of the
329.630 + * transfer, by calling {@link #getLastFileName()}.
329.631 + *
329.632 + * <p>This method will block until the transfer is complete or an exception
329.633 + * is thrown.</p>
329.634 + *
329.635 + * @param name the name of the remote file to write.
329.636 + * @param local the {@code InputStream} that points to the data to
329.637 + * transfer.
329.638 + * @return this FtpClient
329.639 + * @throws IOException if an error occured during the transmission.
329.640 + * @throws FtpProtocolException if the command was rejected by the server
329.641 + */
329.642 + public FtpClient putFile(String name, InputStream local) throws FtpProtocolException, IOException {
329.643 + return putFile(name, local, false);
329.644 }
329.645
329.646 /**
329.647 - * Tries to open a Data Connection in "PASSIVE" mode by issuing a EPSV or
329.648 - * PASV command then opening a Socket to the specified address & port
329.649 + * Transfers a file from the client to the server (aka a <I>put</I>)
329.650 + * by sending the STOR command. The content of the {@code InputStream}
329.651 + * passed in argument is written into the remote file, overwriting any
329.652 + * existing data.
329.653 *
329.654 - * @return the opened socket
329.655 - * @exception FtpProtocolException if an error occurs when issuing the
329.656 - * PASV command to the ftp server.
329.657 + * A new file is created at the server site if the file specified does
329.658 + * not already exist.
329.659 + *
329.660 + * <p>This method will block until the transfer is complete or an exception
329.661 + * is thrown.</p>
329.662 + *
329.663 + * @param name the name of the remote file to write.
329.664 + * @param local the {@code InputStream} that points to the data to
329.665 + * transfer.
329.666 + * @param unique {@code true} if the remote file should be unique
329.667 + * (i.e. not already existing), {@code false} otherwise.
329.668 + * @return this FtpClient
329.669 + * @throws IOException if an error occured during the transmission.
329.670 + * @throws FtpProtocolException if the command was rejected by the server
329.671 + * @see #getLastFileName()
329.672 */
329.673 - protected Socket openPassiveDataConnection() throws IOException {
329.674 - String serverAnswer;
329.675 - int port;
329.676 - InetSocketAddress dest = null;
329.677 + public abstract FtpClient putFile(String name, InputStream local, boolean unique) throws FtpProtocolException, IOException;
329.678
329.679 - /**
329.680 - * Here is the idea:
329.681 - *
329.682 - * - First we want to try the new (and IPv6 compatible) EPSV command
329.683 - * But since we want to be nice with NAT software, we'll issue the
329.684 - * EPSV ALL cmd first.
329.685 - * EPSV is documented in RFC2428
329.686 - * - If EPSV fails, then we fall back to the older, yet OK PASV command
329.687 - * - If PASV fails as well, then we throw an exception and the calling method
329.688 - * will have to try the EPRT or PORT command
329.689 - */
329.690 - if (issueCommand("EPSV ALL") == FTP_SUCCESS) {
329.691 - // We can safely use EPSV commands
329.692 - if (issueCommand("EPSV") == FTP_ERROR)
329.693 - throw new FtpProtocolException("EPSV Failed: " + getResponseString());
329.694 - serverAnswer = getResponseString();
329.695 + /**
329.696 + * Sends the APPE command to the server in order to transfer a data stream
329.697 + * passed in argument and append it to the content of the specified remote
329.698 + * file.
329.699 + *
329.700 + * <p>This method will block until the transfer is complete or an exception
329.701 + * is thrown.</p>
329.702 + *
329.703 + * @param name A {@code String} containing the name of the remote file
329.704 + * to append to.
329.705 + * @param local The {@code InputStream} providing access to the data
329.706 + * to be appended.
329.707 + * @return this FtpClient
329.708 + * @throws IOException if an error occured during the transmission.
329.709 + * @throws FtpProtocolException if the command was rejected by the server
329.710 + */
329.711 + public abstract FtpClient appendFile(String name, InputStream local) throws FtpProtocolException, IOException;
329.712
329.713 - // The response string from a EPSV command will contain the port number
329.714 - // the format will be :
329.715 - // 229 Entering Extended Passive Mode (|||58210|)
329.716 - //
329.717 - // So we'll use the regular expresions package to parse the output.
329.718 + /**
329.719 + * Renames a file on the server.
329.720 + *
329.721 + * @param from the name of the file being renamed
329.722 + * @param to the new name for the file
329.723 + * @return this FtpClient
329.724 + * @throws IOException if an error occured during the transmission.
329.725 + * @throws FtpProtocolException if the command was rejected by the server
329.726 + */
329.727 + public abstract FtpClient rename(String from, String to) throws FtpProtocolException, IOException;
329.728
329.729 - Pattern p = Pattern.compile("^229 .* \\(\\|\\|\\|(\\d+)\\|\\)");
329.730 - Matcher m = p.matcher(serverAnswer);
329.731 - if (! m.find())
329.732 - throw new FtpProtocolException("EPSV failed : " + serverAnswer);
329.733 - // Yay! Let's extract the port number
329.734 - String s = m.group(1);
329.735 - port = Integer.parseInt(s);
329.736 - InetAddress add = serverSocket.getInetAddress();
329.737 - if (add != null) {
329.738 - dest = new InetSocketAddress(add, port);
329.739 - } else {
329.740 - // This means we used an Unresolved address to connect in
329.741 - // the first place. Most likely because the proxy is doing
329.742 - // the name resolution for us, so let's keep using unresolved
329.743 - // address.
329.744 - dest = InetSocketAddress.createUnresolved(serverName, port);
329.745 - }
329.746 - } else {
329.747 - // EPSV ALL failed, so Let's try the regular PASV cmd
329.748 - if (issueCommand("PASV") == FTP_ERROR)
329.749 - throw new FtpProtocolException("PASV failed: " + getResponseString());
329.750 - serverAnswer = getResponseString();
329.751 + /**
329.752 + * Deletes a file on the server.
329.753 + *
329.754 + * @param name a {@code String} containing the name of the file
329.755 + * to delete.
329.756 + * @return this FtpClient
329.757 + * @throws IOException if an error occured during the exchange
329.758 + * @throws FtpProtocolException if the command was rejected by the server
329.759 + */
329.760 + public abstract FtpClient deleteFile(String name) throws FtpProtocolException, IOException;
329.761
329.762 - // Let's parse the response String to get the IP & port to connect to
329.763 - // the String should be in the following format :
329.764 - //
329.765 - // 227 Entering Passive Mode (A1,A2,A3,A4,p1,p2)
329.766 - //
329.767 - // Note that the two parenthesis are optional
329.768 - //
329.769 - // The IP address is A1.A2.A3.A4 and the port is p1 * 256 + p2
329.770 - //
329.771 - // The regular expression is a bit more complex this time, because the
329.772 - // parenthesis are optionals and we have to use 3 groups.
329.773 + /**
329.774 + * Creates a new directory on the server.
329.775 + *
329.776 + * @param name a {@code String} containing the name of the directory
329.777 + * to create.
329.778 + * @return this FtpClient
329.779 + * @throws IOException if an error occured during the exchange
329.780 + * @throws FtpProtocolException if the command was rejected by the server
329.781 + */
329.782 + public abstract FtpClient makeDirectory(String name) throws FtpProtocolException, IOException;
329.783
329.784 - Pattern p = Pattern.compile("227 .* \\(?(\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3}),(\\d{1,3}),(\\d{1,3})\\)?");
329.785 - Matcher m = p.matcher(serverAnswer);
329.786 - if (! m.find())
329.787 - throw new FtpProtocolException("PASV failed : " + serverAnswer);
329.788 - // Get port number out of group 2 & 3
329.789 - port = Integer.parseInt(m.group(3)) + (Integer.parseInt(m.group(2)) << 8);
329.790 - // IP address is simple
329.791 - String s = m.group(1).replace(',','.');
329.792 - dest = new InetSocketAddress(s, port);
329.793 - }
329.794 - // Got everything, let's open the socket!
329.795 - Socket s;
329.796 - if (proxy != null) {
329.797 - if (proxy.type() == Proxy.Type.SOCKS) {
329.798 - s = AccessController.doPrivileged(
329.799 - new PrivilegedAction<Socket>() {
329.800 - public Socket run() {
329.801 - return new Socket(proxy);
329.802 - }});
329.803 - } else
329.804 - s = new Socket(Proxy.NO_PROXY);
329.805 - } else
329.806 - s = new Socket();
329.807 - // Bind the socket to the same address as the control channel. This
329.808 - // is needed in case of multi-homed systems.
329.809 - s.bind(new InetSocketAddress(serverSocket.getLocalAddress(),0));
329.810 - if (connectTimeout >= 0) {
329.811 - s.connect(dest, connectTimeout);
329.812 - } else {
329.813 - if (defaultConnectTimeout > 0) {
329.814 - s.connect(dest, defaultConnectTimeout);
329.815 - } else {
329.816 - s.connect(dest);
329.817 - }
329.818 - }
329.819 - if (readTimeout >= 0)
329.820 - s.setSoTimeout(readTimeout);
329.821 - else
329.822 - if (defaultSoTimeout > 0) {
329.823 - s.setSoTimeout(defaultSoTimeout);
329.824 - }
329.825 - return s;
329.826 + /**
329.827 + * Removes a directory on the server.
329.828 + *
329.829 + * @param name a {@code String} containing the name of the directory
329.830 + * to remove.
329.831 + *
329.832 + * @return this FtpClient
329.833 + * @throws IOException if an error occured during the exchange.
329.834 + * @throws FtpProtocolException if the command was rejected by the server
329.835 + */
329.836 + public abstract FtpClient removeDirectory(String name) throws FtpProtocolException, IOException;
329.837 +
329.838 + /**
329.839 + * Sends a No-operation command. It's useful for testing the connection
329.840 + * status or as a <I>keep alive</I> mechanism.
329.841 + *
329.842 + * @return this FtpClient
329.843 + * @throws IOException if an error occured during the transmission.
329.844 + * @throws FtpProtocolException if the command was rejected by the server
329.845 + */
329.846 + public abstract FtpClient noop() throws FtpProtocolException, IOException;
329.847 +
329.848 + /**
329.849 + * Sends the {@code STAT} command to the server.
329.850 + * This can be used while a data connection is open to get a status
329.851 + * on the current transfer, in that case the parameter should be
329.852 + * {@code null}.
329.853 + * If used between file transfers, it may have a pathname as argument
329.854 + * in which case it will work as the LIST command except no data
329.855 + * connection will be created.
329.856 + *
329.857 + * @param name an optional {@code String} containing the pathname
329.858 + * the STAT command should apply to.
329.859 + * @return the response from the server
329.860 + * @throws IOException if an error occured during the transmission.
329.861 + * @throws FtpProtocolException if the command was rejected by the server
329.862 + */
329.863 + public abstract String getStatus(String name) throws FtpProtocolException, IOException;
329.864 +
329.865 + /**
329.866 + * Sends the {@code FEAT} command to the server and returns the list of supported
329.867 + * features in the form of strings.
329.868 + *
329.869 + * The features are the supported commands, like AUTH TLS, PROT or PASV.
329.870 + * See the RFCs for a complete list.
329.871 + *
329.872 + * Note that not all FTP servers support that command, in which case
329.873 + * a {@link FtpProtocolException} will be thrown.
329.874 + *
329.875 + * @return a {@code List} of {@code Strings} describing the
329.876 + * supported additional features
329.877 + * @throws IOException if an error occurs during the transmission.
329.878 + * @throws FtpProtocolException if the command is rejected by the server
329.879 + */
329.880 + public abstract List<String> getFeatures() throws FtpProtocolException, IOException;
329.881 +
329.882 + /**
329.883 + * Sends the {@code ABOR} command to the server.
329.884 + * <p>It tells the server to stop the previous command or transfer. No action
329.885 + * will be taken if the previous command has already been completed.</p>
329.886 + * <p>This doesn't abort the current session, more commands can be issued
329.887 + * after an abort.</p>
329.888 + *
329.889 + * @return this FtpClient
329.890 + * @throws IOException if an error occured during the transmission.
329.891 + * @throws FtpProtocolException if the command was rejected by the server
329.892 + */
329.893 + public abstract FtpClient abort() throws FtpProtocolException, IOException;
329.894 +
329.895 + /**
329.896 + * Some methods do not wait until completion before returning, so this
329.897 + * method can be called to wait until completion. This is typically the case
329.898 + * with commands that trigger a transfer like {@link #getFileStream(String)}.
329.899 + * So this method should be called before accessing information related to
329.900 + * such a command.
329.901 + * <p>This method will actually block reading on the command channel for a
329.902 + * notification from the server that the command is finished. Such a
329.903 + * notification often carries extra information concerning the completion
329.904 + * of the pending action (e.g. number of bytes transfered).</p>
329.905 + * <p>Note that this will return immediately if no command or action
329.906 + * is pending</p>
329.907 + * <p>It should be also noted that most methods issuing commands to the ftp
329.908 + * server will call this method if a previous command is pending.
329.909 + * <p>Example of use:
329.910 + * <pre>
329.911 + * InputStream in = cl.getFileStream("file");
329.912 + * ...
329.913 + * cl.completePending();
329.914 + * long size = cl.getLastTransferSize();
329.915 + * </pre>
329.916 + * On the other hand, it's not necessary in a case like:
329.917 + * <pre>
329.918 + * InputStream in = cl.getFileStream("file");
329.919 + * // read content
329.920 + * ...
329.921 + * cl.close();
329.922 + * </pre>
329.923 + * <p>Since {@link #close()} will call completePending() if necessary.</p>
329.924 + * @return this FtpClient
329.925 + * @throws IOException if an error occured during the transfer
329.926 + * @throws FtpProtocolException if the command didn't complete successfully
329.927 + */
329.928 + public abstract FtpClient completePending() throws FtpProtocolException, IOException;
329.929 +
329.930 + /**
329.931 + * Reinitializes the USER parameters on the FTP server
329.932 + *
329.933 + * @return this FtpClient
329.934 + * @throws IOException if an error occurs during transmission
329.935 + * @throws FtpProtocolException if the command fails
329.936 + */
329.937 + public abstract FtpClient reInit() throws FtpProtocolException, IOException;
329.938 +
329.939 + /**
329.940 + * Changes the transfer type (binary, ascii, ebcdic) and issue the
329.941 + * proper command (e.g. TYPE A) to the server.
329.942 + *
329.943 + * @param type the {@code TransferType} to use.
329.944 + * @return This FtpClient
329.945 + * @throws IOException if an error occurs during transmission.
329.946 + * @throws FtpProtocolException if the command was rejected by the server
329.947 + */
329.948 + public abstract FtpClient setType(TransferType type) throws FtpProtocolException, IOException;
329.949 +
329.950 + /**
329.951 + * Changes the current transfer type to binary.
329.952 + * This is a convenience method that is equivalent to
329.953 + * {@code setType(TransferType.BINARY)}
329.954 + *
329.955 + * @return This FtpClient
329.956 + * @throws IOException if an error occurs during the transmission.
329.957 + * @throws FtpProtocolException if the command was rejected by the server
329.958 + * @see #setType(TransferType)
329.959 + */
329.960 + public FtpClient setBinaryType() throws FtpProtocolException, IOException {
329.961 + setType(TransferType.BINARY);
329.962 + return this;
329.963 }
329.964
329.965 /**
329.966 - * Tries to open a Data Connection with the server. It will first try a passive
329.967 - * mode connection, then, if it fails, a more traditional PORT command
329.968 + * Changes the current transfer type to ascii.
329.969 + * This is a convenience method that is equivalent to
329.970 + * {@code setType(TransferType.ASCII)}
329.971 *
329.972 - * @param cmd the command to execute (RETR, STOR, etc...)
329.973 - * @return the opened socket
329.974 - *
329.975 - * @exception FtpProtocolException if an error occurs when issuing the
329.976 - * PORT command to the ftp server.
329.977 + * @return This FtpClient
329.978 + * @throws IOException if an error occurs during the transmission.
329.979 + * @throws FtpProtocolException if the command was rejected by the server
329.980 + * @see #setType(TransferType)
329.981 */
329.982 - protected Socket openDataConnection(String cmd) throws IOException {
329.983 - ServerSocket portSocket;
329.984 - Socket clientSocket = null;
329.985 - String portCmd;
329.986 - InetAddress myAddress;
329.987 - IOException e;
329.988 -
329.989 - // Let's try passive mode first
329.990 - try {
329.991 - clientSocket = openPassiveDataConnection();
329.992 - } catch (IOException ex) {
329.993 - clientSocket = null;
329.994 - }
329.995 - if (clientSocket != null) {
329.996 - // We did get a clientSocket, so the passive mode worked
329.997 - // Let's issue the command (GET, DIR, ...)
329.998 - try {
329.999 - if (issueCommand(cmd) == FTP_ERROR) {
329.1000 - clientSocket.close();
329.1001 - throw new FtpProtocolException(getResponseString());
329.1002 - } else
329.1003 - return clientSocket;
329.1004 - } catch (IOException ioe) {
329.1005 - clientSocket.close();
329.1006 - throw ioe;
329.1007 - }
329.1008 - }
329.1009 -
329.1010 - assert(clientSocket == null);
329.1011 -
329.1012 - // Passive mode failed, let's fall back to the good old "PORT"
329.1013 -
329.1014 - if (proxy != null && proxy.type() == Proxy.Type.SOCKS) {
329.1015 - // We're behind a firewall and the passive mode fail,
329.1016 - // since we can't accept a connection through SOCKS (yet)
329.1017 - // throw an exception
329.1018 - throw new FtpProtocolException("Passive mode failed");
329.1019 - }
329.1020 - // Bind the ServerSocket to the same address as the control channel
329.1021 - // This is needed for multi-homed systems
329.1022 - portSocket = new ServerSocket(0, 1, serverSocket.getLocalAddress());
329.1023 - try {
329.1024 - myAddress = portSocket.getInetAddress();
329.1025 - if (myAddress.isAnyLocalAddress())
329.1026 - myAddress = getLocalAddress();
329.1027 - // Let's try the new, IPv6 compatible EPRT command
329.1028 - // See RFC2428 for specifics
329.1029 - // Some FTP servers (like the one on Solaris) are bugged, they
329.1030 - // will accept the EPRT command but then, the subsequent command
329.1031 - // (e.g. RETR) will fail, so we have to check BOTH results (the
329.1032 - // EPRT cmd then the actual command) to decide wether we should
329.1033 - // fall back on the older PORT command.
329.1034 - portCmd = "EPRT |" +
329.1035 - ((myAddress instanceof Inet6Address) ? "2" : "1") + "|" +
329.1036 - myAddress.getHostAddress() +"|" +
329.1037 - portSocket.getLocalPort()+"|";
329.1038 - if (issueCommand(portCmd) == FTP_ERROR ||
329.1039 - issueCommand(cmd) == FTP_ERROR) {
329.1040 - // The EPRT command failed, let's fall back to good old PORT
329.1041 - portCmd = "PORT ";
329.1042 - byte[] addr = myAddress.getAddress();
329.1043 -
329.1044 - /* append host addr */
329.1045 - for (int i = 0; i < addr.length; i++) {
329.1046 - portCmd = portCmd + (addr[i] & 0xFF) + ",";
329.1047 - }
329.1048 -
329.1049 - /* append port number */
329.1050 - portCmd = portCmd + ((portSocket.getLocalPort() >>> 8) & 0xff) + ","
329.1051 - + (portSocket.getLocalPort() & 0xff);
329.1052 - if (issueCommand(portCmd) == FTP_ERROR) {
329.1053 - e = new FtpProtocolException("PORT :" + getResponseString());
329.1054 - throw e;
329.1055 - }
329.1056 - if (issueCommand(cmd) == FTP_ERROR) {
329.1057 - e = new FtpProtocolException(cmd + ":" + getResponseString());
329.1058 - throw e;
329.1059 - }
329.1060 - }
329.1061 - // Either the EPRT or the PORT command was successful
329.1062 - // Let's create the client socket
329.1063 - if (connectTimeout >= 0) {
329.1064 - portSocket.setSoTimeout(connectTimeout);
329.1065 - } else {
329.1066 - if (defaultConnectTimeout > 0)
329.1067 - portSocket.setSoTimeout(defaultConnectTimeout);
329.1068 - }
329.1069 - clientSocket = portSocket.accept();
329.1070 - if (readTimeout >= 0)
329.1071 - clientSocket.setSoTimeout(readTimeout);
329.1072 - else {
329.1073 - if (defaultSoTimeout > 0)
329.1074 - clientSocket.setSoTimeout(defaultSoTimeout);
329.1075 - }
329.1076 - } finally {
329.1077 - portSocket.close();
329.1078 - }
329.1079 -
329.1080 - return clientSocket;
329.1081 - }
329.1082 -
329.1083 - /* public methods */
329.1084 -
329.1085 - /**
329.1086 - * Open a FTP connection to host <i>host</i>.
329.1087 - *
329.1088 - * @param host The hostname of the ftp server
329.1089 - *
329.1090 - * @exception FtpProtocolException if connection fails
329.1091 - */
329.1092 - public void openServer(String host) throws IOException {
329.1093 - openServer(host, FTP_PORT);
329.1094 + public FtpClient setAsciiType() throws FtpProtocolException, IOException {
329.1095 + setType(TransferType.ASCII);
329.1096 + return this;
329.1097 }
329.1098
329.1099 /**
329.1100 - * Open a FTP connection to host <i>host</i> on port <i>port</i>.
329.1101 + * Issues a {@code LIST} command to the server to get the current directory
329.1102 + * listing, and returns the InputStream from the data connection.
329.1103 *
329.1104 - * @param host the hostname of the ftp server
329.1105 - * @param port the port to connect to (usually 21)
329.1106 + * <p>{@link #completePending()} <b>has</b> to be called once the application
329.1107 + * is finished reading from the stream.</p>
329.1108 *
329.1109 - * @exception FtpProtocolException if connection fails
329.1110 + * @param path the pathname of the directory to list, or {@code null}
329.1111 + * for the current working directory.
329.1112 + * @return the {@code InputStream} from the resulting data connection
329.1113 + * @throws IOException if an error occurs during the transmission.
329.1114 + * @throws FtpProtocolException if the command was rejected by the server
329.1115 + * @see #changeDirectory(String)
329.1116 + * @see #listFiles(String)
329.1117 */
329.1118 - public void openServer(String host, int port) throws IOException {
329.1119 - this.serverName = host;
329.1120 - super.openServer(host, port);
329.1121 - if (readReply() == FTP_ERROR)
329.1122 - throw new FtpProtocolException("Welcome message: " +
329.1123 - getResponseString());
329.1124 - }
329.1125 -
329.1126 + public abstract InputStream list(String path) throws FtpProtocolException, IOException;
329.1127
329.1128 /**
329.1129 - * login user to a host with username <i>user</i> and password
329.1130 - * <i>password</i>
329.1131 + * Issues a {@code NLST path} command to server to get the specified directory
329.1132 + * content. It differs from {@link #list(String)} method by the fact that
329.1133 + * it will only list the file names which would make the parsing of the
329.1134 + * somewhat easier.
329.1135 *
329.1136 - * @param user Username to use at login
329.1137 - * @param password Password to use at login or null of none is needed
329.1138 + * <p>{@link #completePending()} <b>has</b> to be called once the application
329.1139 + * is finished reading from the stream.</p>
329.1140 *
329.1141 - * @exception FtpLoginException if login is unsuccesful
329.1142 + * @param path a {@code String} containing the pathname of the
329.1143 + * directory to list or {@code null} for the current working directory.
329.1144 + * @return the {@code InputStream} from the resulting data connection
329.1145 + * @throws IOException if an error occurs during the transmission.
329.1146 + * @throws FtpProtocolException if the command was rejected by the server
329.1147 */
329.1148 - public void login(String user, String password) throws IOException {
329.1149 - if (!serverIsOpen())
329.1150 - throw new FtpLoginException("not connected to host");
329.1151 - if (user == null || user.length() == 0)
329.1152 - return;
329.1153 - if (issueCommand("USER " + user) == FTP_ERROR)
329.1154 - throw new FtpLoginException("user " + user + " : " + getResponseString());
329.1155 - /*
329.1156 - * Checks for "331 User name okay, need password." answer
329.1157 - */
329.1158 -
329.1159 - if (lastReplyCode == 331)
329.1160 - if ((password == null) || (password.length() == 0) ||
329.1161 - (issueCommand("PASS " + password) == FTP_ERROR))
329.1162 - throw new FtpLoginException("password: " + getResponseString());
329.1163 -
329.1164 - // keep the welcome message around so we can
329.1165 - // put it in the resulting HTML page.
329.1166 - String l;
329.1167 - StringBuffer sb = new StringBuffer();
329.1168 - for (int i = 0; i < serverResponse.size(); i++) {
329.1169 - l = (String)serverResponse.elementAt(i);
329.1170 - if (l != null) {
329.1171 - if (l.length() >= 4 && l.startsWith("230")) {
329.1172 - // get rid of the "230-" prefix
329.1173 - l = l.substring(4);
329.1174 - }
329.1175 - sb.append(l);
329.1176 - }
329.1177 - }
329.1178 - welcomeMsg = sb.toString();
329.1179 - loggedIn = true;
329.1180 - }
329.1181 + public abstract InputStream nameList(String path) throws FtpProtocolException, IOException;
329.1182
329.1183 /**
329.1184 - * GET a file from the FTP server
329.1185 + * Issues the {@code SIZE [path]} command to the server to get the size of a
329.1186 + * specific file on the server.
329.1187 + * Note that this command may not be supported by the server. In which
329.1188 + * case -1 will be returned.
329.1189 *
329.1190 - * @param filename name of the file to retrieve
329.1191 - * @return the <code>InputStream</code> to read the file from
329.1192 - *
329.1193 - * @exception FileNotFoundException if the file can't be opened
329.1194 + * @param path a {@code String} containing the pathname of the
329.1195 + * file.
329.1196 + * @return a {@code long} containing the size of the file or -1 if
329.1197 + * the server returned an error, which can be checked with
329.1198 + * {@link #getLastReplyCode()}.
329.1199 + * @throws IOException if an error occurs during the transmission.
329.1200 + * @throws FtpProtocolException if the command was rejected by the server
329.1201 */
329.1202 - public TelnetInputStream get(String filename) throws IOException {
329.1203 - Socket s;
329.1204 -
329.1205 - try {
329.1206 - s = openDataConnection("RETR " + filename);
329.1207 - } catch (FileNotFoundException fileException) {
329.1208 - /* Well, "/" might not be the file delimitor for this
329.1209 - particular ftp server, so let's try a series of
329.1210 - "cd" commands to get to the right place. */
329.1211 - /* But don't try this if there are no '/' in the path */
329.1212 - if (filename.indexOf('/') == -1)
329.1213 - throw fileException;
329.1214 -
329.1215 - StringTokenizer t = new StringTokenizer(filename, "/");
329.1216 - String pathElement = null;
329.1217 -
329.1218 - while (t.hasMoreElements()) {
329.1219 - pathElement = t.nextToken();
329.1220 -
329.1221 - if (!t.hasMoreElements()) {
329.1222 - /* This is the file component. Look it up now. */
329.1223 - break;
329.1224 - }
329.1225 - try {
329.1226 - cd(pathElement);
329.1227 - } catch (FtpProtocolException e) {
329.1228 - /* Giving up. */
329.1229 - throw fileException;
329.1230 - }
329.1231 - }
329.1232 - if (pathElement != null) {
329.1233 - s = openDataConnection("RETR " + pathElement);
329.1234 - } else {
329.1235 - throw fileException;
329.1236 - }
329.1237 - }
329.1238 -
329.1239 - return new TelnetInputStream(s.getInputStream(), binaryMode);
329.1240 - }
329.1241 + public abstract long getSize(String path) throws FtpProtocolException, IOException;
329.1242
329.1243 /**
329.1244 - * PUT a file to the FTP server
329.1245 + * Issues the {@code MDTM [path]} command to the server to get the modification
329.1246 + * time of a specific file on the server.
329.1247 + * Note that this command may not be supported by the server, in which
329.1248 + * case {@code null} will be returned.
329.1249 *
329.1250 - * @param filename name of the file to store
329.1251 - * @return the <code>OutputStream</code> to write the file to
329.1252 - *
329.1253 + * @param path a {@code String} containing the pathname of the file.
329.1254 + * @return a {@code Date} representing the last modification time
329.1255 + * or {@code null} if the server returned an error, which
329.1256 + * can be checked with {@link #getLastReplyCode()}.
329.1257 + * @throws IOException if an error occurs during the transmission.
329.1258 + * @throws FtpProtocolException if the command was rejected by the server
329.1259 */
329.1260 - public TelnetOutputStream put(String filename) throws IOException {
329.1261 - Socket s = openDataConnection("STOR " + filename);
329.1262 - TelnetOutputStream out = new TelnetOutputStream(s.getOutputStream(), binaryMode);
329.1263 - if (!binaryMode)
329.1264 - out.setStickyCRLF(true);
329.1265 - return out;
329.1266 - }
329.1267 + public abstract Date getLastModified(String path) throws FtpProtocolException, IOException;
329.1268
329.1269 /**
329.1270 - * Append to a file on the FTP server
329.1271 + * Sets the parser used to handle the directory output to the specified
329.1272 + * one. By default the parser is set to one that can handle most FTP
329.1273 + * servers output (Unix base mostly). However it may be necessary for
329.1274 + * and application to provide its own parser due to some uncommon
329.1275 + * output format.
329.1276 *
329.1277 - * @param filename name of the file to append to
329.1278 - * @return the <code>OutputStream</code> to write the file to
329.1279 - *
329.1280 + * @param p The {@code FtpDirParser} to use.
329.1281 + * @return this FtpClient
329.1282 + * @see #listFiles(String)
329.1283 */
329.1284 - public TelnetOutputStream append(String filename) throws IOException {
329.1285 - Socket s = openDataConnection("APPE " + filename);
329.1286 - TelnetOutputStream out = new TelnetOutputStream(s.getOutputStream(), binaryMode);
329.1287 - if (!binaryMode)
329.1288 - out.setStickyCRLF(true);
329.1289 -
329.1290 - return out;
329.1291 - }
329.1292 + public abstract FtpClient setDirParser(FtpDirParser p);
329.1293
329.1294 /**
329.1295 - * LIST files in the current directory on a remote FTP server
329.1296 + * Issues a {@code MLSD} command to the server to get the specified directory
329.1297 + * listing and applies the internal parser to create an Iterator of
329.1298 + * {@link java.net.FtpDirEntry}. Note that the Iterator returned is also a
329.1299 + * {@link java.io.Closeable}.
329.1300 + * <p>If the server doesn't support the MLSD command, the LIST command is used
329.1301 + * instead and the parser set by {@link #setDirParser(java.net.FtpDirParser) }
329.1302 + * is used instead.</p>
329.1303 *
329.1304 - * @return the <code>InputStream</code> to read the list from
329.1305 + * {@link #completePending()} <b>has</b> to be called once the application
329.1306 + * is finished iterating through the files.
329.1307 *
329.1308 + * @param path the pathname of the directory to list or {@code null}
329.1309 + * for the current working directoty.
329.1310 + * @return a {@code Iterator} of files or {@code null} if the
329.1311 + * command failed.
329.1312 + * @throws IOException if an error occured during the transmission
329.1313 + * @see #setDirParser(FtpDirParser)
329.1314 + * @see #changeDirectory(String)
329.1315 + * @throws FtpProtocolException if the command was rejected by the server
329.1316 */
329.1317 - public TelnetInputStream list() throws IOException {
329.1318 - Socket s = openDataConnection("LIST");
329.1319 -
329.1320 - return new TelnetInputStream(s.getInputStream(), binaryMode);
329.1321 - }
329.1322 + public abstract Iterator<FtpDirEntry> listFiles(String path) throws FtpProtocolException, IOException;
329.1323
329.1324 /**
329.1325 - * List (NLST) file names on a remote FTP server
329.1326 + * Attempts to use Kerberos GSSAPI as an authentication mechanism with the
329.1327 + * ftp server. This will issue an {@code AUTH GSSAPI} command, and if
329.1328 + * it is accepted by the server, will followup with {@code ADAT}
329.1329 + * command to exchange the various tokens until authentication is
329.1330 + * successful. This conforms to Appendix I of RFC 2228.
329.1331 *
329.1332 - * @param path pathname to the directory to list, null for current
329.1333 - * directory
329.1334 - * @return the <code>InputStream</code> to read the list from
329.1335 - * @exception <code>FtpProtocolException</code>
329.1336 + * @return this FtpClient
329.1337 + * @throws IOException if an error occurs during the transmission.
329.1338 + * @throws FtpProtocolException if the command was rejected by the server
329.1339 */
329.1340 - public TelnetInputStream nameList(String path) throws IOException {
329.1341 - Socket s;
329.1342 -
329.1343 - if (path != null)
329.1344 - s = openDataConnection("NLST " + path);
329.1345 - else
329.1346 - s = openDataConnection("NLST");
329.1347 - return new TelnetInputStream(s.getInputStream(), binaryMode);
329.1348 - }
329.1349 + public abstract FtpClient useKerberos() throws FtpProtocolException, IOException;
329.1350
329.1351 /**
329.1352 - * CD to a specific directory on a remote FTP server
329.1353 + * Returns the Welcome string the server sent during initial connection.
329.1354 *
329.1355 - * @param remoteDirectory path of the directory to CD to
329.1356 - *
329.1357 - * @exception <code>FtpProtocolException</code>
329.1358 + * @return a {@code String} containing the message the server
329.1359 + * returned during connection or {@code null}.
329.1360 */
329.1361 - public void cd(String remoteDirectory) throws IOException {
329.1362 - if (remoteDirectory == null ||
329.1363 - "".equals(remoteDirectory))
329.1364 - return;
329.1365 - issueCommandCheck("CWD " + remoteDirectory);
329.1366 - }
329.1367 + public abstract String getWelcomeMsg();
329.1368
329.1369 /**
329.1370 - * CD to the parent directory on a remote FTP server
329.1371 + * Returns the last reply code sent by the server.
329.1372 *
329.1373 + * @return the lastReplyCode or {@code null} if none were received yet.
329.1374 */
329.1375 - public void cdUp() throws IOException {
329.1376 - issueCommandCheck("CDUP");
329.1377 - }
329.1378 + public abstract FtpReplyCode getLastReplyCode();
329.1379
329.1380 /**
329.1381 - * Print working directory of remote FTP server
329.1382 + * Returns the last response string sent by the server.
329.1383 *
329.1384 - * @exception FtpProtocolException if the command fails
329.1385 + * @return the message string, which can be quite long, last returned
329.1386 + * by the server, or {@code null} if no response were received yet.
329.1387 */
329.1388 - public String pwd() throws IOException {
329.1389 - String answ;
329.1390 -
329.1391 - issueCommandCheck("PWD");
329.1392 - /*
329.1393 - * answer will be of the following format :
329.1394 - *
329.1395 - * 257 "/" is current directory.
329.1396 - */
329.1397 - answ = getResponseString();
329.1398 - if (!answ.startsWith("257"))
329.1399 - throw new FtpProtocolException("PWD failed. " + answ);
329.1400 - return answ.substring(5, answ.lastIndexOf('"'));
329.1401 - }
329.1402 + public abstract String getLastResponseString();
329.1403
329.1404 /**
329.1405 - * Set transfer type to 'I'
329.1406 + * Returns, when available, the size of the latest started transfer.
329.1407 + * This is retreived by parsing the response string received as an initial
329.1408 + * response to a {@code RETR} or similar request.
329.1409 *
329.1410 - * @exception FtpProtocolException if the command fails
329.1411 + * @return the size of the latest transfer or -1 if either there was no
329.1412 + * transfer or the information was unavailable.
329.1413 */
329.1414 - public void binary() throws IOException {
329.1415 - issueCommandCheck("TYPE I");
329.1416 - binaryMode = true;
329.1417 - }
329.1418 + public abstract long getLastTransferSize();
329.1419
329.1420 /**
329.1421 - * Set transfer type to 'A'
329.1422 + * Returns, when available, the remote name of the last transfered file.
329.1423 + * This is mainly useful for "put" operation when the unique flag was
329.1424 + * set since it allows to recover the unique file name created on the
329.1425 + * server which may be different from the one submitted with the command.
329.1426 *
329.1427 - * @exception FtpProtocolException if the command fails
329.1428 + * @return the name the latest transfered file remote name, or
329.1429 + * {@code null} if that information is unavailable.
329.1430 */
329.1431 - public void ascii() throws IOException {
329.1432 - issueCommandCheck("TYPE A");
329.1433 - binaryMode = false;
329.1434 - }
329.1435 + public abstract String getLastFileName();
329.1436
329.1437 /**
329.1438 - * Rename a file on the ftp server
329.1439 + * Attempts to switch to a secure, encrypted connection. This is done by
329.1440 + * sending the {@code AUTH TLS} command.
329.1441 + * <p>See <a href="http://www.ietf.org/rfc/rfc4217.txt">RFC 4217</a></p>
329.1442 + * If successful this will establish a secure command channel with the
329.1443 + * server, it will also make it so that all other transfers (e.g. a RETR
329.1444 + * command) will be done over an encrypted channel as well unless a
329.1445 + * {@link #reInit()} command or a {@link #endSecureSession()} command is issued.
329.1446 + * <p>This method should be called after a successful {@link #connect(java.net.InetSocketAddress) }
329.1447 + * but before calling {@link #login(java.lang.String, char[]) }.</p>
329.1448 *
329.1449 - * @exception FtpProtocolException if the command fails
329.1450 + * @return this FtpCLient
329.1451 + * @throws IOException if an error occured during the transmission.
329.1452 + * @throws FtpProtocolException if the command was rejected by the server
329.1453 + * @see #endSecureSession()
329.1454 */
329.1455 - public void rename(String from, String to) throws IOException {
329.1456 - issueCommandCheck("RNFR " + from);
329.1457 - issueCommandCheck("RNTO " + to);
329.1458 - }
329.1459 + public abstract FtpClient startSecureSession() throws FtpProtocolException, IOException;
329.1460
329.1461 /**
329.1462 - * Get the "System string" from the FTP server
329.1463 + * Sends a {@code CCC} command followed by a {@code PROT C}
329.1464 + * command to the server terminating an encrypted session and reverting
329.1465 + * back to a non encrypted transmission.
329.1466 *
329.1467 - * @exception FtpProtocolException if it fails
329.1468 + * @return this FtpClient
329.1469 + * @throws IOException if an error occured during transmission.
329.1470 + * @throws FtpProtocolException if the command was rejected by the server
329.1471 + * @see #startSecureSession()
329.1472 */
329.1473 - public String system() throws IOException {
329.1474 - String answ;
329.1475 - issueCommandCheck("SYST");
329.1476 - answ = getResponseString();
329.1477 - if (!answ.startsWith("215"))
329.1478 - throw new FtpProtocolException("SYST failed." + answ);
329.1479 - return answ.substring(4); // Skip "215 "
329.1480 - }
329.1481 + public abstract FtpClient endSecureSession() throws FtpProtocolException, IOException;
329.1482
329.1483 /**
329.1484 - * Send a No-operation command. It's usefull for testing the connection status
329.1485 + * Sends the "Allocate" ({@code ALLO}) command to the server telling it to
329.1486 + * pre-allocate the specified number of bytes for the next transfer.
329.1487 *
329.1488 - * @exception FtpProtocolException if the command fails
329.1489 + * @param size The number of bytes to allocate.
329.1490 + * @return this FtpClient
329.1491 + * @throws IOException if an error occured during the transmission.
329.1492 + * @throws FtpProtocolException if the command was rejected by the server
329.1493 */
329.1494 - public void noop() throws IOException {
329.1495 - issueCommandCheck("NOOP");
329.1496 - }
329.1497 + public abstract FtpClient allocate(long size) throws FtpProtocolException, IOException;
329.1498
329.1499 /**
329.1500 - * Reinitialize the USER parameters on the FTp server
329.1501 + * Sends the "Structure Mount" ({@code SMNT}) command to the server. This let the
329.1502 + * user mount a different file system data structure without altering his
329.1503 + * login or accounting information.
329.1504 *
329.1505 - * @exception FtpProtocolException if the command fails
329.1506 + * @param struct a {@code String} containing the name of the
329.1507 + * structure to mount.
329.1508 + * @return this FtpClient
329.1509 + * @throws IOException if an error occured during the transmission.
329.1510 + * @throws FtpProtocolException if the command was rejected by the server
329.1511 */
329.1512 - public void reInit() throws IOException {
329.1513 - issueCommandCheck("REIN");
329.1514 - loggedIn = false;
329.1515 - }
329.1516 + public abstract FtpClient structureMount(String struct) throws FtpProtocolException, IOException;
329.1517
329.1518 /**
329.1519 - * New FTP client connected to host <i>host</i>.
329.1520 + * Sends a System ({@code SYST}) command to the server and returns the String
329.1521 + * sent back by the server describing the operating system at the
329.1522 + * server.
329.1523 *
329.1524 - * @param host Hostname of the FTP server
329.1525 - *
329.1526 - * @exception FtpProtocolException if the connection fails
329.1527 + * @return a {@code String} describing the OS, or {@code null}
329.1528 + * if the operation was not successful.
329.1529 + * @throws IOException if an error occured during the transmission.
329.1530 + * @throws FtpProtocolException if the command was rejected by the server
329.1531 */
329.1532 - public FtpClient(String host) throws IOException {
329.1533 - super();
329.1534 - openServer(host, FTP_PORT);
329.1535 - }
329.1536 + public abstract String getSystem() throws FtpProtocolException, IOException;
329.1537
329.1538 /**
329.1539 - * New FTP client connected to host <i>host</i>, port <i>port</i>.
329.1540 + * Sends the {@code HELP} command to the server, with an optional command, like
329.1541 + * SITE, and returns the text sent back by the server.
329.1542 *
329.1543 - * @param host Hostname of the FTP server
329.1544 - * @param port port number to connect to (usually 21)
329.1545 + * @param cmd the command for which the help is requested or
329.1546 + * {@code null} for the general help
329.1547 + * @return a {@code String} containing the text sent back by the
329.1548 + * server, or {@code null} if the command failed.
329.1549 + * @throws IOException if an error occured during transmission
329.1550 + * @throws FtpProtocolException if the command was rejected by the server
329.1551 + */
329.1552 + public abstract String getHelp(String cmd) throws FtpProtocolException, IOException;
329.1553 +
329.1554 + /**
329.1555 + * Sends the {@code SITE} command to the server. This is used by the server
329.1556 + * to provide services specific to his system that are essential
329.1557 + * to file transfer.
329.1558 *
329.1559 - * @exception FtpProtocolException if the connection fails
329.1560 + * @param cmd the command to be sent.
329.1561 + * @return this FtpClient
329.1562 + * @throws IOException if an error occured during transmission
329.1563 + * @throws FtpProtocolException if the command was rejected by the server
329.1564 */
329.1565 - public FtpClient(String host, int port) throws IOException {
329.1566 - super();
329.1567 - openServer(host, port);
329.1568 - }
329.1569 -
329.1570 - /** Create an uninitialized FTP client. */
329.1571 - public FtpClient() {}
329.1572 -
329.1573 - public FtpClient(Proxy p) {
329.1574 - proxy = p;
329.1575 - }
329.1576 -
329.1577 - protected void finalize() throws IOException {
329.1578 - /**
329.1579 - * Do not call the "normal" closeServer() as we want finalization
329.1580 - * to be as efficient as possible
329.1581 - */
329.1582 - if (serverIsOpen())
329.1583 - super.closeServer();
329.1584 - }
329.1585 -
329.1586 + public abstract FtpClient siteCmd(String cmd) throws FtpProtocolException, IOException;
329.1587 }
330.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
330.2 +++ b/src/share/classes/sun/net/ftp/FtpClientProvider.java Wed Nov 25 11:08:25 2009 -0800
330.3 @@ -0,0 +1,158 @@
330.4 +/*
330.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
330.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
330.7 + *
330.8 + * This code is free software; you can redistribute it and/or modify it
330.9 + * under the terms of the GNU General Public License version 2 only, as
330.10 + * published by the Free Software Foundation. Sun designates this
330.11 + * particular file as subject to the "Classpath" exception as provided
330.12 + * by Sun in the LICENSE file that accompanied this code.
330.13 + *
330.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
330.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
330.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
330.17 + * version 2 for more details (a copy is included in the LICENSE file that
330.18 + * accompanied this code).
330.19 + *
330.20 + * You should have received a copy of the GNU General Public License version
330.21 + * 2 along with this work; if not, write to the Free Software Foundation,
330.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
330.23 + *
330.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
330.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
330.26 + * have any questions.
330.27 + */
330.28 +package sun.net.ftp;
330.29 +
330.30 +import java.security.AccessController;
330.31 +import java.security.PrivilegedAction;
330.32 +import java.util.ServiceConfigurationError;
330.33 +//import sun.misc.Service;
330.34 +
330.35 +/**
330.36 + * Service provider class for FtpClient.
330.37 + * Sub-classes of FtpClientProvider provide an implementation of {@link FtpClient}
330.38 + * and associated classes. Applications do not normally use this class directly.
330.39 + * See {@link #provider() } for how providers are found and loaded.
330.40 + *
330.41 + * @since 1.7
330.42 + */
330.43 +public abstract class FtpClientProvider {
330.44 +
330.45 + /**
330.46 + * Creates a FtpClient from this provider.
330.47 + *
330.48 + * @return The created {@link FtpClient}.
330.49 + */
330.50 + public abstract FtpClient createFtpClient();
330.51 + private static final Object lock = new Object();
330.52 + private static FtpClientProvider provider = null;
330.53 +
330.54 + /**
330.55 + * Initializes a new instance of this class.
330.56 + *
330.57 + * @throws SecurityException if a security manager is installed and it denies
330.58 + * {@link RuntimePermission}<tt>("ftpClientProvider")</tt>
330.59 + */
330.60 + protected FtpClientProvider() {
330.61 + SecurityManager sm = System.getSecurityManager();
330.62 + if (sm != null) {
330.63 + sm.checkPermission(new RuntimePermission("ftpClientProvider"));
330.64 + }
330.65 + }
330.66 +
330.67 + private static boolean loadProviderFromProperty() {
330.68 + String cm = System.getProperty("sun.net.ftpClientProvider");
330.69 + if (cm == null) {
330.70 + return false;
330.71 + }
330.72 + try {
330.73 + Class c = Class.forName(cm, true, null);
330.74 + provider = (FtpClientProvider) c.newInstance();
330.75 + return true;
330.76 + } catch (ClassNotFoundException x) {
330.77 + throw new ServiceConfigurationError(x.toString());
330.78 + } catch (IllegalAccessException x) {
330.79 + throw new ServiceConfigurationError(x.toString());
330.80 + } catch (InstantiationException x) {
330.81 + throw new ServiceConfigurationError(x.toString());
330.82 + } catch (SecurityException x) {
330.83 + throw new ServiceConfigurationError(x.toString());
330.84 + }
330.85 + }
330.86 +
330.87 + private static boolean loadProviderAsService() {
330.88 + // Iterator i = Service.providers(FtpClientProvider.class,
330.89 + // ClassLoader.getSystemClassLoader());
330.90 + // while (i.hasNext()) {
330.91 + // try {
330.92 + // provider = (FtpClientProvider) i.next();
330.93 + // return true;
330.94 + // } catch (ServiceConfigurationError sce) {
330.95 + // if (sce.getCause() instanceof SecurityException) {
330.96 + // // Ignore, try next provider, if any
330.97 + // continue;
330.98 + // }
330.99 + // throw sce;
330.100 + // }
330.101 + // }
330.102 + return false;
330.103 + }
330.104 +
330.105 + /**
330.106 + * Returns the system wide default FtpClientProvider for this invocation of
330.107 + * the Java virtual machine.
330.108 + *
330.109 + * <p> The first invocation of this method locates the default provider
330.110 + * object as follows: </p>
330.111 + *
330.112 + * <ol>
330.113 + *
330.114 + * <li><p> If the system property
330.115 + * <tt>java.net.FtpClientProvider</tt> is defined then it is
330.116 + * taken to be the fully-qualified name of a concrete provider class.
330.117 + * The class is loaded and instantiated; if this process fails then an
330.118 + * unspecified unchecked error or exception is thrown. </p></li>
330.119 + *
330.120 + * <li><p> If a provider class has been installed in a jar file that is
330.121 + * visible to the system class loader, and that jar file contains a
330.122 + * provider-configuration file named
330.123 + * <tt>java.net.FtpClientProvider</tt> in the resource
330.124 + * directory <tt>META-INF/services</tt>, then the first class name
330.125 + * specified in that file is taken. The class is loaded and
330.126 + * instantiated; if this process fails then an unspecified unchecked error or exception is
330.127 + * thrown. </p></li>
330.128 + *
330.129 + * <li><p> Finally, if no provider has been specified by any of the above
330.130 + * means then the system-default provider class is instantiated and the
330.131 + * result is returned. </p></li>
330.132 + *
330.133 + * </ol>
330.134 + *
330.135 + * <p> Subsequent invocations of this method return the provider that was
330.136 + * returned by the first invocation. </p>
330.137 + *
330.138 + * @return The system-wide default FtpClientProvider
330.139 + */
330.140 + public static FtpClientProvider provider() {
330.141 + synchronized (lock) {
330.142 + if (provider != null) {
330.143 + return provider;
330.144 + }
330.145 + return (FtpClientProvider) AccessController.doPrivileged(
330.146 + new PrivilegedAction<Object>() {
330.147 +
330.148 + public Object run() {
330.149 + if (loadProviderFromProperty()) {
330.150 + return provider;
330.151 + }
330.152 + if (loadProviderAsService()) {
330.153 + return provider;
330.154 + }
330.155 + provider = new sun.net.ftp.impl.DefaultFtpClientProvider();
330.156 + return provider;
330.157 + }
330.158 + });
330.159 + }
330.160 + }
330.161 +}
331.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
331.2 +++ b/src/share/classes/sun/net/ftp/FtpDirEntry.java Wed Nov 25 11:08:25 2009 -0800
331.3 @@ -0,0 +1,331 @@
331.4 +/*
331.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
331.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
331.7 + *
331.8 + * This code is free software; you can redistribute it and/or modify it
331.9 + * under the terms of the GNU General Public License version 2 only, as
331.10 + * published by the Free Software Foundation. Sun designates this
331.11 + * particular file as subject to the "Classpath" exception as provided
331.12 + * by Sun in the LICENSE file that accompanied this code.
331.13 + *
331.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
331.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
331.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
331.17 + * version 2 for more details (a copy is included in the LICENSE file that
331.18 + * accompanied this code).
331.19 + *
331.20 + * You should have received a copy of the GNU General Public License version
331.21 + * 2 along with this work; if not, write to the Free Software Foundation,
331.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
331.23 + *
331.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
331.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
331.26 + * have any questions.
331.27 + */
331.28 +package sun.net.ftp;
331.29 +
331.30 +import java.util.Date;
331.31 +import java.util.HashMap;
331.32 +
331.33 +/**
331.34 + * A {@code FtpDirEntry} is a class agregating all the information that the FTP client
331.35 + * can gather from the server by doing a {@code LST} (or {@code NLST}) command and
331.36 + * parsing the output. It will typically contain the name, type, size, last modification
331.37 + * time, owner and group of the file, although some of these could be unavailable
331.38 + * due to specific FTP server limitations.
331.39 + *
331.40 + * @see sun.net.ftp.FtpDirParser
331.41 + * @since 1.7
331.42 + */
331.43 +public class FtpDirEntry {
331.44 +
331.45 + public enum Type {
331.46 +
331.47 + FILE, DIR, PDIR, CDIR, LINK
331.48 + };
331.49 +
331.50 + public enum Permission {
331.51 +
331.52 + USER(0), GROUP(1), OTHERS(2);
331.53 + int value;
331.54 +
331.55 + Permission(int v) {
331.56 + value = v;
331.57 + }
331.58 + };
331.59 + private final String name;
331.60 + private String user = null;
331.61 + private String group = null;
331.62 + private long size = -1;
331.63 + private java.util.Date created = null;
331.64 + private java.util.Date lastModified = null;
331.65 + private Type type = Type.FILE;
331.66 + private boolean[][] permissions = null;
331.67 + private HashMap<String, String> facts = new HashMap<String, String>();
331.68 +
331.69 + private FtpDirEntry() {
331.70 + name = null;
331.71 + }
331.72 +
331.73 + /**
331.74 + * Creates an FtpDirEntry instance with only the name being set.
331.75 + *
331.76 + * @param name The name of the file
331.77 + */
331.78 + public FtpDirEntry(String name) {
331.79 + this.name = name;
331.80 + }
331.81 +
331.82 + /**
331.83 + * Returns the name of the remote file.
331.84 + *
331.85 + * @return a {@code String} containing the name of the remote file.
331.86 + */
331.87 + public String getName() {
331.88 + return name;
331.89 + }
331.90 +
331.91 + /**
331.92 + * Returns the user name of the owner of the file as returned by the FTP
331.93 + * server, if provided. This could be a name or a user id (number).
331.94 + *
331.95 + * @return a {@code String} containing the user name or
331.96 + * {@code null} if that information is not available.
331.97 + */
331.98 + public String getUser() {
331.99 + return user;
331.100 + }
331.101 +
331.102 + /**
331.103 + * Sets the user name of the owner of the file. Intended mostly to be
331.104 + * used from inside a {@link java.net.FtpDirParser} implementation.
331.105 + *
331.106 + * @param user The user name of the owner of the file, or {@code null}
331.107 + * if that information is not available.
331.108 + * @return this FtpDirEntry
331.109 + */
331.110 + public FtpDirEntry setUser(String user) {
331.111 + this.user = user;
331.112 + return this;
331.113 + }
331.114 +
331.115 + /**
331.116 + * Returns the group name of the file as returned by the FTP
331.117 + * server, if provided. This could be a name or a group id (number).
331.118 + *
331.119 + * @return a {@code String} containing the group name or
331.120 + * {@code null} if that information is not available.
331.121 + */
331.122 + public String getGroup() {
331.123 + return group;
331.124 + }
331.125 +
331.126 + /**
331.127 + * Sets the name of the group to which the file belong. Intended mostly to be
331.128 + * used from inside a {@link java.net.FtpDirParser} implementation.
331.129 + *
331.130 + * @param group The name of the group to which the file belong, or {@code null}
331.131 + * if that information is not available.
331.132 + * @return this FtpDirEntry
331.133 + */
331.134 + public FtpDirEntry setGroup(String group) {
331.135 + this.group = group;
331.136 + return this;
331.137 + }
331.138 +
331.139 + /**
331.140 + * Returns the size of the remote file as it was returned by the FTP
331.141 + * server, if provided.
331.142 + *
331.143 + * @return the size of the file or -1 if that information is not available.
331.144 + */
331.145 + public long getSize() {
331.146 + return size;
331.147 + }
331.148 +
331.149 + /**
331.150 + * Sets the size of that file. Intended mostly to be used from inside an
331.151 + * {@link java.net.FtpDirParser} implementation.
331.152 + *
331.153 + * @param size The size, in bytes, of that file. or -1 if unknown.
331.154 + * @return this FtpDirEntry
331.155 + */
331.156 + public FtpDirEntry setSize(long size) {
331.157 + this.size = size;
331.158 + return this;
331.159 + }
331.160 +
331.161 + /**
331.162 + * Returns the type of the remote file as it was returned by the FTP
331.163 + * server, if provided.
331.164 + * It returns a FtpDirEntry.Type enum and the values can be:
331.165 + * - FtpDirEntry.Type.FILE for a normal file
331.166 + * - FtpDirEntry.Type.DIR for a directory
331.167 + * - FtpDirEntry.Type.LINK for a symbolic link
331.168 + *
331.169 + * @return a {@code FtpDirEntry.Type} describing the type of the file
331.170 + * or {@code null} if that information is not available.
331.171 + */
331.172 + public Type getType() {
331.173 + return type;
331.174 + }
331.175 +
331.176 + /**
331.177 + * Sets the type of the file. Intended mostly to be used from inside an
331.178 + * {@link java.net.FtpDirParser} implementation.
331.179 + *
331.180 + * @param type the type of this file or {@code null} if that information
331.181 + * is not available.
331.182 + * @return this FtpDirEntry
331.183 + */
331.184 + public FtpDirEntry setType(Type type) {
331.185 + this.type = type;
331.186 + return this;
331.187 + }
331.188 +
331.189 + /**
331.190 + * Returns the last modification time of the remote file as it was returned
331.191 + * by the FTP server, if provided, {@code null} otherwise.
331.192 + *
331.193 + * @return a <code>Date</code> representing the last time the file was
331.194 + * modified on the server, or {@code null} if that
331.195 + * information is not available.
331.196 + */
331.197 + public java.util.Date getLastModified() {
331.198 + return this.lastModified;
331.199 + }
331.200 +
331.201 + /**
331.202 + * Sets the last modification time of the file. Intended mostly to be used
331.203 + * from inside an {@link java.net.FtpDirParser} implementation.
331.204 + *
331.205 + * @param lastModified The Date representing the last modification time, or
331.206 + * {@code null} if that information is not available.
331.207 + * @return this FtpDirEntry
331.208 + */
331.209 + public FtpDirEntry setLastModified(Date lastModified) {
331.210 + this.lastModified = lastModified;
331.211 + return this;
331.212 + }
331.213 +
331.214 + /**
331.215 + * Returns whether read access is granted for a specific permission.
331.216 + *
331.217 + * @param p the Permission (user, group, others) to check.
331.218 + * @return {@code true} if read access is granted.
331.219 + */
331.220 + public boolean canRead(Permission p) {
331.221 + if (permissions != null) {
331.222 + return permissions[p.value][0];
331.223 + }
331.224 + return false;
331.225 + }
331.226 +
331.227 + /**
331.228 + * Returns whether write access is granted for a specific permission.
331.229 + *
331.230 + * @param p the Permission (user, group, others) to check.
331.231 + * @return {@code true} if write access is granted.
331.232 + */
331.233 + public boolean canWrite(Permission p) {
331.234 + if (permissions != null) {
331.235 + return permissions[p.value][1];
331.236 + }
331.237 + return false;
331.238 + }
331.239 +
331.240 + /**
331.241 + * Returns whether execute access is granted for a specific permission.
331.242 + *
331.243 + * @param p the Permission (user, group, others) to check.
331.244 + * @return {@code true} if execute access is granted.
331.245 + */
331.246 + public boolean canExexcute(Permission p) {
331.247 + if (permissions != null) {
331.248 + return permissions[p.value][2];
331.249 + }
331.250 + return false;
331.251 + }
331.252 +
331.253 + /**
331.254 + * Sets the permissions for that file. Intended mostly to be used
331.255 + * from inside an {@link java.net.FtpDirParser} implementation.
331.256 + * The permissions array is a 3x3 {@code boolean} array, the first index being
331.257 + * the User, group or owner (0, 1 and 2 respectively) while the second
331.258 + * index is read, write or execute (0, 1 and 2 respectively again).
331.259 + * <p>E.G.: {@code permissions[1][2]} is the group/execute permission.</p>
331.260 + *
331.261 + * @param permissions a 3x3 {@code boolean} array
331.262 + * @return this {@code FtpDirEntry}
331.263 + */
331.264 + public FtpDirEntry setPermissions(boolean[][] permissions) {
331.265 + this.permissions = permissions;
331.266 + return this;
331.267 + }
331.268 +
331.269 + /**
331.270 + * Adds a 'fact', as defined in RFC 3659, to the list of facts of this file.
331.271 + * Intended mostly to be used from inside a {@link java.net.FtpDirParser}
331.272 + * implementation.
331.273 + *
331.274 + * @param fact the name of the fact (e.g. "Media-Type"). It is not case-sensitive.
331.275 + * @param value the value associated with this fact.
331.276 + * @return this {@code FtpDirEntry}
331.277 + */
331.278 + public FtpDirEntry addFact(String fact, String value) {
331.279 + facts.put(fact.toLowerCase(), value);
331.280 + return this;
331.281 + }
331.282 +
331.283 + /**
331.284 + * Returns the requested 'fact', as defined in RFC 3659, if available.
331.285 + *
331.286 + * @param fact The name of the fact *e.g. "Media-Type"). It is not case sensitive.
331.287 + * @return The value of the fact or, {@code null} if that fact wasn't
331.288 + * provided by the server.
331.289 + */
331.290 + public String getFact(String fact) {
331.291 + return facts.get(fact.toLowerCase());
331.292 + }
331.293 +
331.294 + /**
331.295 + * Returns the creation time of the file, when provided by the server.
331.296 + *
331.297 + * @return The Date representing the creation time, or {@code null}
331.298 + * if the server didn't provide that information.
331.299 + */
331.300 + public Date getCreated() {
331.301 + return created;
331.302 + }
331.303 +
331.304 + /**
331.305 + * Sets the creation time for that file. Intended mostly to be used from
331.306 + * inside a {@link java.net.FtpDirParser} implementation.
331.307 + *
331.308 + * @param created the Date representing the creation time for that file, or
331.309 + * {@code null} if that information is not available.
331.310 + * @return this FtpDirEntry
331.311 + */
331.312 + public FtpDirEntry setCreated(Date created) {
331.313 + this.created = created;
331.314 + return this;
331.315 + }
331.316 +
331.317 + /**
331.318 + * Returns a string representation of the object.
331.319 + * The {@code toString} method for class {@code FtpDirEntry}
331.320 + * returns a string consisting of the name of the file, followed by its
331.321 + * type between brackets, followed by the user and group between
331.322 + * parenthesis, then size between '{', and, finally, the lastModified of last
331.323 + * modification if it's available.
331.324 + *
331.325 + * @return a string representation of the object.
331.326 + */
331.327 + @Override
331.328 + public String toString() {
331.329 + if (lastModified == null) {
331.330 + return name + " [" + type + "] (" + user + " / " + group + ") " + size;
331.331 + }
331.332 + return name + " [" + type + "] (" + user + " / " + group + ") {" + size + "} " + java.text.DateFormat.getDateInstance().format(lastModified);
331.333 + }
331.334 +}
332.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
332.2 +++ b/src/share/classes/sun/net/ftp/FtpDirParser.java Wed Nov 25 11:08:25 2009 -0800
332.3 @@ -0,0 +1,49 @@
332.4 +/*
332.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
332.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
332.7 + *
332.8 + * This code is free software; you can redistribute it and/or modify it
332.9 + * under the terms of the GNU General Public License version 2 only, as
332.10 + * published by the Free Software Foundation. Sun designates this
332.11 + * particular file as subject to the "Classpath" exception as provided
332.12 + * by Sun in the LICENSE file that accompanied this code.
332.13 + *
332.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
332.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
332.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
332.17 + * version 2 for more details (a copy is included in the LICENSE file that
332.18 + * accompanied this code).
332.19 + *
332.20 + * You should have received a copy of the GNU General Public License version
332.21 + * 2 along with this work; if not, write to the Free Software Foundation,
332.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
332.23 + *
332.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
332.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
332.26 + * have any questions.
332.27 + */
332.28 +
332.29 +package sun.net.ftp;
332.30 +
332.31 +/**
332.32 + * This interface describes a parser for the FtpClient class. Such a parser is
332.33 + * used when listing a remote directory to transform text lines like:
332.34 + * drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog
332.35 + * into FtpDirEntry instances.
332.36 + *
332.37 + * @see java.net.FtpClient#setFileParser(FtpDirParser)
332.38 + * @since 1.7
332.39 + */
332.40 +public interface FtpDirParser {
332.41 +
332.42 + /**
332.43 + * Takes one line from a directory listing and returns an FtpDirEntry instance
332.44 + * based on the information contained.
332.45 + *
332.46 + * @param line a <code>String</code>, a line sent by the FTP server as a
332.47 + * result of the LST command.
332.48 + * @return an <code>FtpDirEntry</code> instance.
332.49 + * @see java.net.FtpDirEntry
332.50 + */
332.51 + public FtpDirEntry parseLine(String line);
332.52 +}
333.1 --- a/src/share/classes/sun/net/ftp/FtpLoginException.java Mon Nov 23 10:04:47 2009 +0000
333.2 +++ b/src/share/classes/sun/net/ftp/FtpLoginException.java Wed Nov 25 11:08:25 2009 -0800
333.3 @@ -1,5 +1,5 @@
333.4 /*
333.5 - * Copyright 1994-2008 Sun Microsystems, Inc. All Rights Reserved.
333.6 + * Copyright 1994-2009 Sun Microsystems, Inc. All Rights Reserved.
333.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
333.8 *
333.9 * This code is free software; you can redistribute it and/or modify it
333.10 @@ -25,7 +25,7 @@
333.11
333.12 package sun.net.ftp;
333.13
333.14 -import java.io.*;
333.15 +import java.io.IOException;
333.16
333.17 /**
333.18 * This exception is thrown when an error is encountered during an
333.19 @@ -33,10 +33,10 @@
333.20 *
333.21 * @author Jonathan Payne
333.22 */
333.23 -public class FtpLoginException extends FtpProtocolException {
333.24 +public class FtpLoginException extends IOException {
333.25 private static final long serialVersionUID = 2218162403237941536L;
333.26
333.27 - FtpLoginException(String s) {
333.28 + public FtpLoginException(String s) {
333.29 super(s);
333.30 }
333.31 }
334.1 --- a/src/share/classes/sun/net/ftp/FtpProtocolException.java Mon Nov 23 10:04:47 2009 +0000
334.2 +++ b/src/share/classes/sun/net/ftp/FtpProtocolException.java Wed Nov 25 11:08:25 2009 -0800
334.3 @@ -1,5 +1,5 @@
334.4 /*
334.5 - * Copyright 1994-2008 Sun Microsystems, Inc. All Rights Reserved.
334.6 + * Copyright 1994-2009 Sun Microsystems, Inc. All Rights Reserved.
334.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
334.8 *
334.9 * This code is free software; you can redistribute it and/or modify it
334.10 @@ -22,21 +22,49 @@
334.11 * CA 95054 USA or visit www.sun.com if you need additional information or
334.12 * have any questions.
334.13 */
334.14 -
334.15 package sun.net.ftp;
334.16
334.17 -import java.io.*;
334.18 -
334.19 /**
334.20 - * This exeception is thrown when unexpected results are returned during
334.21 - * an FTP session.
334.22 - *
334.23 + * Thrown to indicate that the FTP server reported an error.
334.24 + * For instance that the requested file doesn't exist or
334.25 + * that a command isn't supported.
334.26 + * <p>The specific error code can be retreived with {@link #getReplyCode() }.</p>
334.27 * @author Jonathan Payne
334.28 */
334.29 -public class FtpProtocolException extends IOException {
334.30 +public class FtpProtocolException extends Exception {
334.31 private static final long serialVersionUID = 5978077070276545054L;
334.32 + private final FtpReplyCode code;
334.33
334.34 - FtpProtocolException(String s) {
334.35 - super(s);
334.36 + /**
334.37 + * Constructs a new {@code FtpProtocolException} from the
334.38 + * specified detail message. The reply code is set to unknow error.
334.39 + *
334.40 + * @param detail the detail message.
334.41 + */
334.42 + public FtpProtocolException(String detail) {
334.43 + super(detail);
334.44 + code = FtpReplyCode.UNKNOWN_ERROR;
334.45 + }
334.46 +
334.47 + /**
334.48 + * Constructs a new {@code FtpProtocolException} from the
334.49 + * specified response code and exception detail message
334.50 + *
334.51 + * @param detail the detail message.
334.52 + * @param code The {@code FtpRelyCode} received from server.
334.53 + */
334.54 + public FtpProtocolException(String detail, FtpReplyCode code) {
334.55 + super(detail);
334.56 + this.code = code;
334.57 + }
334.58 +
334.59 + /**
334.60 + * Gets the reply code sent by the server that led to this exception
334.61 + * being thrown.
334.62 + *
334.63 + * @return The {@link FtpReplyCode} associated with that exception.
334.64 + */
334.65 + public FtpReplyCode getReplyCode() {
334.66 + return code;
334.67 }
334.68 }
335.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
335.2 +++ b/src/share/classes/sun/net/ftp/FtpReplyCode.java Wed Nov 25 11:08:25 2009 -0800
335.3 @@ -0,0 +1,248 @@
335.4 +/*
335.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
335.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
335.7 + *
335.8 + * This code is free software; you can redistribute it and/or modify it
335.9 + * under the terms of the GNU General Public License version 2 only, as
335.10 + * published by the Free Software Foundation. Sun designates this
335.11 + * particular file as subject to the "Classpath" exception as provided
335.12 + * by Sun in the LICENSE file that accompanied this code.
335.13 + *
335.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
335.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
335.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
335.17 + * version 2 for more details (a copy is included in the LICENSE file that
335.18 + * accompanied this code).
335.19 + *
335.20 + * You should have received a copy of the GNU General Public License version
335.21 + * 2 along with this work; if not, write to the Free Software Foundation,
335.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
335.23 + *
335.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
335.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
335.26 + * have any questions.
335.27 + */
335.28 +package sun.net.ftp;
335.29 +
335.30 +/**
335.31 + * This class describes a FTP protocol reply code and associates a meaning
335.32 + * to the numerical value according to the various RFCs (RFC 959 in
335.33 + * particular).
335.34 + *
335.35 + */
335.36 +public enum FtpReplyCode {
335.37 +
335.38 + RESTART_MARKER(110),
335.39 + SERVICE_READY_IN(120),
335.40 + DATA_CONNECTION_ALREADY_OPEN(125),
335.41 + FILE_STATUS_OK(150),
335.42 + COMMAND_OK(200),
335.43 + NOT_IMPLEMENTED(202),
335.44 + SYSTEM_STATUS(211),
335.45 + DIRECTORY_STATUS(212),
335.46 + FILE_STATUS(213),
335.47 + HELP_MESSAGE(214),
335.48 + NAME_SYSTEM_TYPE(215),
335.49 + SERVICE_READY(220),
335.50 + SERVICE_CLOSING(221),
335.51 + DATA_CONNECTION_OPEN(225),
335.52 + CLOSING_DATA_CONNECTION(226),
335.53 + ENTERING_PASSIVE_MODE(227),
335.54 + ENTERING_EXT_PASSIVE_MODE(229),
335.55 + LOGGED_IN(230),
335.56 + SECURELY_LOGGED_IN(232),
335.57 + SECURITY_EXCHANGE_OK(234),
335.58 + SECURITY_EXCHANGE_COMPLETE(235),
335.59 + FILE_ACTION_OK(250),
335.60 + PATHNAME_CREATED(257),
335.61 + NEED_PASSWORD(331),
335.62 + NEED_ACCOUNT(332),
335.63 + NEED_ADAT(334),
335.64 + NEED_MORE_ADAT(335),
335.65 + FILE_ACTION_PENDING(350),
335.66 + SERVICE_NOT_AVAILABLE(421),
335.67 + CANT_OPEN_DATA_CONNECTION(425),
335.68 + CONNECTION_CLOSED(426),
335.69 + NEED_SECURITY_RESOURCE(431),
335.70 + FILE_ACTION_NOT_TAKEN(450),
335.71 + ACTION_ABORTED(451),
335.72 + INSUFFICIENT_STORAGE(452),
335.73 + COMMAND_UNRECOGNIZED(500),
335.74 + INVALID_PARAMETER(501),
335.75 + BAD_SEQUENCE(503),
335.76 + NOT_IMPLEMENTED_FOR_PARAMETER(504),
335.77 + NOT_LOGGED_IN(530),
335.78 + NEED_ACCOUNT_FOR_STORING(532),
335.79 + PROT_LEVEL_DENIED(533),
335.80 + REQUEST_DENIED(534),
335.81 + FAILED_SECURITY_CHECK(535),
335.82 + UNSUPPORTED_PROT_LEVEL(536),
335.83 + PROT_LEVEL_NOT_SUPPORTED_BY_SECURITY(537),
335.84 + FILE_UNAVAILABLE(550),
335.85 + PAGE_TYPE_UNKNOWN(551),
335.86 + EXCEEDED_STORAGE(552),
335.87 + FILE_NAME_NOT_ALLOWED(553),
335.88 + PROTECTED_REPLY(631),
335.89 + UNKNOWN_ERROR(999);
335.90 + private final int value;
335.91 +
335.92 + FtpReplyCode(int val) {
335.93 + this.value = val;
335.94 + }
335.95 +
335.96 + /**
335.97 + * Returns the numerical value of the code.
335.98 + *
335.99 + * @return the numerical value.
335.100 + */
335.101 + public int getValue() {
335.102 + return value;
335.103 + }
335.104 +
335.105 + /**
335.106 + * Determines if the code is a Positive Preliminary response.
335.107 + * This means beginning with a 1 (which means a value between 100 and 199)
335.108 + *
335.109 + * @return <code>true</code> if the reply code is a positive preliminary
335.110 + * response.
335.111 + */
335.112 + public boolean isPositivePreliminary() {
335.113 + return value >= 100 && value < 200;
335.114 + }
335.115 +
335.116 + /**
335.117 + * Determines if the code is a Positive Completion response.
335.118 + * This means beginning with a 2 (which means a value between 200 and 299)
335.119 + *
335.120 + * @return <code>true</code> if the reply code is a positive completion
335.121 + * response.
335.122 + */
335.123 + public boolean isPositiveCompletion() {
335.124 + return value >= 200 && value < 300;
335.125 + }
335.126 +
335.127 + /**
335.128 + * Determines if the code is a positive internediate response.
335.129 + * This means beginning with a 3 (which means a value between 300 and 399)
335.130 + *
335.131 + * @return <code>true</code> if the reply code is a positive intermediate
335.132 + * response.
335.133 + */
335.134 + public boolean isPositiveIntermediate() {
335.135 + return value >= 300 && value < 400;
335.136 + }
335.137 +
335.138 + /**
335.139 + * Determines if the code is a transient negative response.
335.140 + * This means beginning with a 4 (which means a value between 400 and 499)
335.141 + *
335.142 + * @return <code>true</code> if the reply code is a transient negative
335.143 + * response.
335.144 + */
335.145 + public boolean isTransientNegative() {
335.146 + return value >= 400 && value < 500;
335.147 + }
335.148 +
335.149 + /**
335.150 + * Determines if the code is a permanent negative response.
335.151 + * This means beginning with a 5 (which means a value between 500 and 599)
335.152 + *
335.153 + * @return <code>true</code> if the reply code is a permanent negative
335.154 + * response.
335.155 + */
335.156 + public boolean isPermanentNegative() {
335.157 + return value >= 500 && value < 600;
335.158 + }
335.159 +
335.160 + /**
335.161 + * Determines if the code is a protected reply response.
335.162 + * This means beginning with a 6 (which means a value between 600 and 699)
335.163 + *
335.164 + * @return <code>true</code> if the reply code is a protected reply
335.165 + * response.
335.166 + */
335.167 + public boolean isProtectedReply() {
335.168 + return value >= 600 && value < 700;
335.169 + }
335.170 +
335.171 + /**
335.172 + * Determines if the code is a syntax related response.
335.173 + * This means the second digit is a 0.
335.174 + *
335.175 + * @return <code>true</code> if the reply code is a syntax related
335.176 + * response.
335.177 + */
335.178 + public boolean isSyntax() {
335.179 + return ((value / 10) - ((value / 100) * 10)) == 0;
335.180 + }
335.181 +
335.182 + /**
335.183 + * Determines if the code is an information related response.
335.184 + * This means the second digit is a 1.
335.185 + *
335.186 + * @return <code>true</code> if the reply code is an information related
335.187 + * response.
335.188 + */
335.189 + public boolean isInformation() {
335.190 + return ((value / 10) - ((value / 100) * 10)) == 1;
335.191 + }
335.192 +
335.193 + /**
335.194 + * Determines if the code is a connection related response.
335.195 + * This means the second digit is a 2.
335.196 + *
335.197 + * @return <code>true</code> if the reply code is a connection related
335.198 + * response.
335.199 + */
335.200 + public boolean isConnection() {
335.201 + return ((value / 10) - ((value / 100) * 10)) == 2;
335.202 + }
335.203 +
335.204 + /**
335.205 + * Determines if the code is an authentication related response.
335.206 + * This means the second digit is a 3.
335.207 + *
335.208 + * @return <code>true</code> if the reply code is an authentication related
335.209 + * response.
335.210 + */
335.211 + public boolean isAuthentication() {
335.212 + return ((value / 10) - ((value / 100) * 10)) == 3;
335.213 + }
335.214 +
335.215 + /**
335.216 + * Determines if the code is an unspecified type of response.
335.217 + * This means the second digit is a 4.
335.218 + *
335.219 + * @return <code>true</code> if the reply code is an unspecified type of
335.220 + * response.
335.221 + */
335.222 + public boolean isUnspecified() {
335.223 + return ((value / 10) - ((value / 100) * 10)) == 4;
335.224 + }
335.225 +
335.226 + /**
335.227 + * Determines if the code is a file system related response.
335.228 + * This means the second digit is a 5.
335.229 + *
335.230 + * @return <code>true</code> if the reply code is a file system related
335.231 + * response.
335.232 + */
335.233 + public boolean isFileSystem() {
335.234 + return ((value / 10) - ((value / 100) * 10)) == 5;
335.235 + }
335.236 +
335.237 + /**
335.238 + * Static utility method to convert a value into a FtpReplyCode.
335.239 + *
335.240 + * @param v the value to convert
335.241 + * @return the <code>FtpReplyCode</code> associated with the value.
335.242 + */
335.243 + public static FtpReplyCode find(int v) {
335.244 + for (FtpReplyCode code : FtpReplyCode.values()) {
335.245 + if (code.getValue() == v) {
335.246 + return code;
335.247 + }
335.248 + }
335.249 + return UNKNOWN_ERROR;
335.250 + }
335.251 +}
336.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
336.2 +++ b/src/share/classes/sun/net/ftp/impl/DefaultFtpClientProvider.java Wed Nov 25 11:08:25 2009 -0800
336.3 @@ -0,0 +1,38 @@
336.4 +/*
336.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
336.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
336.7 + *
336.8 + * This code is free software; you can redistribute it and/or modify it
336.9 + * under the terms of the GNU General Public License version 2 only, as
336.10 + * published by the Free Software Foundation. Sun designates this
336.11 + * particular file as subject to the "Classpath" exception as provided
336.12 + * by Sun in the LICENSE file that accompanied this code.
336.13 + *
336.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
336.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
336.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
336.17 + * version 2 for more details (a copy is included in the LICENSE file that
336.18 + * accompanied this code).
336.19 + *
336.20 + * You should have received a copy of the GNU General Public License version
336.21 + * 2 along with this work; if not, write to the Free Software Foundation,
336.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
336.23 + *
336.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
336.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
336.26 + * have any questions.
336.27 + */
336.28 +package sun.net.ftp.impl;
336.29 +
336.30 +/**
336.31 + * Default FtpClientProvider.
336.32 + * Uses sun.net.ftp.FtpCLient.
336.33 + */
336.34 +public class DefaultFtpClientProvider extends sun.net.ftp.FtpClientProvider {
336.35 +
336.36 + @Override
336.37 + public sun.net.ftp.FtpClient createFtpClient() {
336.38 + return sun.net.ftp.impl.FtpClient.create();
336.39 + }
336.40 +
336.41 +}
337.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
337.2 +++ b/src/share/classes/sun/net/ftp/impl/FtpClient.java Wed Nov 25 11:08:25 2009 -0800
337.3 @@ -0,0 +1,2191 @@
337.4 +/*
337.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
337.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
337.7 + *
337.8 + * This code is free software; you can redistribute it and/or modify it
337.9 + * under the terms of the GNU General Public License version 2 only, as
337.10 + * published by the Free Software Foundation. Sun designates this
337.11 + * particular file as subject to the "Classpath" exception as provided
337.12 + * by Sun in the LICENSE file that accompanied this code.
337.13 + *
337.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
337.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
337.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
337.17 + * version 2 for more details (a copy is included in the LICENSE file that
337.18 + * accompanied this code).
337.19 + *
337.20 + * You should have received a copy of the GNU General Public License version
337.21 + * 2 along with this work; if not, write to the Free Software Foundation,
337.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
337.23 + *
337.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
337.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
337.26 + * have any questions.
337.27 + */
337.28 +package sun.net.ftp.impl;
337.29 +
337.30 +import java.net.*;
337.31 +import java.io.*;
337.32 +import java.security.AccessController;
337.33 +import java.security.PrivilegedAction;
337.34 +import java.text.DateFormat;
337.35 +import java.text.ParseException;
337.36 +import java.text.SimpleDateFormat;
337.37 +import java.util.ArrayList;
337.38 +import java.util.Calendar;
337.39 +import java.util.Date;
337.40 +import java.util.Iterator;
337.41 +import java.util.List;
337.42 +import java.util.TimeZone;
337.43 +import java.util.Vector;
337.44 +import java.util.regex.Matcher;
337.45 +import java.util.regex.Pattern;
337.46 +import javax.net.ssl.SSLSocket;
337.47 +import javax.net.ssl.SSLSocketFactory;
337.48 +import sun.misc.BASE64Decoder;
337.49 +import sun.misc.BASE64Encoder;
337.50 +import sun.net.ftp.*;
337.51 +import sun.util.logging.PlatformLogger;
337.52 +
337.53 +
337.54 +public class FtpClient extends sun.net.ftp.FtpClient {
337.55 +
337.56 + private static int defaultSoTimeout;
337.57 + private static int defaultConnectTimeout;
337.58 + private static final PlatformLogger logger =
337.59 + PlatformLogger.getLogger("sun.net.ftp.FtpClient");
337.60 + private Proxy proxy;
337.61 + private Socket server;
337.62 + private PrintStream out;
337.63 + private InputStream in;
337.64 + private int readTimeout = -1;
337.65 + private int connectTimeout = -1;
337.66 +
337.67 + /* Name of encoding to use for output */
337.68 + private static String encoding = "ISO8859_1";
337.69 + /** remember the ftp server name because we may need it */
337.70 + private InetSocketAddress serverAddr;
337.71 + private boolean replyPending = false;
337.72 + private boolean loggedIn = false;
337.73 + private boolean useCrypto = false;
337.74 + private SSLSocketFactory sslFact;
337.75 + private Socket oldSocket;
337.76 + /** Array of strings (usually 1 entry) for the last reply from the server. */
337.77 + private Vector<String> serverResponse = new Vector<String>(1);
337.78 + /** The last reply code from the ftp daemon. */
337.79 + private FtpReplyCode lastReplyCode = null;
337.80 + /** Welcome message from the server, if any. */
337.81 + private String welcomeMsg;
337.82 + private boolean passiveMode = true;
337.83 + private TransferType type = TransferType.BINARY;
337.84 + private long restartOffset = 0;
337.85 + private long lastTransSize = -1; // -1 means 'unknown size'
337.86 + private String lastFileName;
337.87 + /**
337.88 + * Static members used by the parser
337.89 + */
337.90 + private static String[] patStrings = {
337.91 + // drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog
337.92 + "([\\-ld](?:[r\\-][w\\-][x\\-]){3})\\s*\\d+ (\\w+)\\s*(\\w+)\\s*(\\d+)\\s*([A-Z][a-z][a-z]\\s*\\d+)\\s*(\\d\\d:\\d\\d)\\s*(\\p{Print}*)",
337.93 + // drwxr-xr-x 1 user01 ftp 512 Jan 29 1997 prog
337.94 + "([\\-ld](?:[r\\-][w\\-][x\\-]){3})\\s*\\d+ (\\w+)\\s*(\\w+)\\s*(\\d+)\\s*([A-Z][a-z][a-z]\\s*\\d+)\\s*(\\d{4})\\s*(\\p{Print}*)",
337.95 + // 04/28/2006 09:12a 3,563 genBuffer.sh
337.96 + "(\\d{2}/\\d{2}/\\d{4})\\s*(\\d{2}:\\d{2}[ap])\\s*((?:[0-9,]+)|(?:<DIR>))\\s*(\\p{Graph}*)",
337.97 + // 01-29-97 11:32PM <DIR> prog
337.98 + "(\\d{2}-\\d{2}-\\d{2})\\s*(\\d{2}:\\d{2}[AP]M)\\s*((?:[0-9,]+)|(?:<DIR>))\\s*(\\p{Graph}*)"
337.99 + };
337.100 + private static int[][] patternGroups = {
337.101 + // 0 - file, 1 - size, 2 - date, 3 - time, 4 - year, 5 - permissions,
337.102 + // 6 - user, 7 - group
337.103 + {7, 4, 5, 6, 0, 1, 2, 3},
337.104 + {7, 4, 5, 0, 6, 1, 2, 3},
337.105 + {4, 3, 1, 2, 0, 0, 0, 0},
337.106 + {4, 3, 1, 2, 0, 0, 0, 0}};
337.107 + private static Pattern[] patterns;
337.108 + private static Pattern linkp = Pattern.compile("(\\p{Print}+) \\-\\> (\\p{Print}+)$");
337.109 + private DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM, java.util.Locale.US);
337.110 +
337.111 + static {
337.112 + final int vals[] = {0, 0};
337.113 + final String encs[] = {null};
337.114 +
337.115 + AccessController.doPrivileged(
337.116 + new PrivilegedAction<Object>() {
337.117 +
337.118 + public Object run() {
337.119 + vals[0] = Integer.getInteger("sun.net.client.defaultReadTimeout", 0).intValue();
337.120 + vals[1] = Integer.getInteger("sun.net.client.defaultConnectTimeout", 0).intValue();
337.121 + encs[0] = System.getProperty("file.encoding", "ISO8859_1");
337.122 + return null;
337.123 + }
337.124 + });
337.125 + if (vals[0] == 0) {
337.126 + defaultSoTimeout = -1;
337.127 + } else {
337.128 + defaultSoTimeout = vals[0];
337.129 + }
337.130 +
337.131 + if (vals[1] == 0) {
337.132 + defaultConnectTimeout = -1;
337.133 + } else {
337.134 + defaultConnectTimeout = vals[1];
337.135 + }
337.136 +
337.137 + encoding = encs[0];
337.138 + try {
337.139 + if (!isASCIISuperset(encoding)) {
337.140 + encoding = "ISO8859_1";
337.141 + }
337.142 + } catch (Exception e) {
337.143 + encoding = "ISO8859_1";
337.144 + }
337.145 +
337.146 + patterns = new Pattern[patStrings.length];
337.147 + for (int i = 0; i < patStrings.length; i++) {
337.148 + patterns[i] = Pattern.compile(patStrings[i]);
337.149 + }
337.150 + }
337.151 +
337.152 + /**
337.153 + * Test the named character encoding to verify that it converts ASCII
337.154 + * characters correctly. We have to use an ASCII based encoding, or else
337.155 + * the NetworkClients will not work correctly in EBCDIC based systems.
337.156 + * However, we cannot just use ASCII or ISO8859_1 universally, because in
337.157 + * Asian locales, non-ASCII characters may be embedded in otherwise
337.158 + * ASCII based protocols (eg. HTTP). The specifications (RFC2616, 2398)
337.159 + * are a little ambiguous in this matter. For instance, RFC2398 [part 2.1]
337.160 + * says that the HTTP request URI should be escaped using a defined
337.161 + * mechanism, but there is no way to specify in the escaped string what
337.162 + * the original character set is. It is not correct to assume that
337.163 + * UTF-8 is always used (as in URLs in HTML 4.0). For this reason,
337.164 + * until the specifications are updated to deal with this issue more
337.165 + * comprehensively, and more importantly, HTTP servers are known to
337.166 + * support these mechanisms, we will maintain the current behavior
337.167 + * where it is possible to send non-ASCII characters in their original
337.168 + * unescaped form.
337.169 + */
337.170 + private static boolean isASCIISuperset(String encoding) throws Exception {
337.171 + String chkS = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
337.172 + "abcdefghijklmnopqrstuvwxyz-_.!~*'();/?:@&=+$,";
337.173 +
337.174 + // Expected byte sequence for string above
337.175 + byte[] chkB = {48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 65, 66, 67, 68, 69, 70, 71, 72,
337.176 + 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 97, 98, 99,
337.177 + 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114,
337.178 + 115, 116, 117, 118, 119, 120, 121, 122, 45, 95, 46, 33, 126, 42, 39, 40, 41, 59,
337.179 + 47, 63, 58, 64, 38, 61, 43, 36, 44};
337.180 +
337.181 + byte[] b = chkS.getBytes(encoding);
337.182 + return java.util.Arrays.equals(b, chkB);
337.183 + }
337.184 +
337.185 + private class DefaultParser implements FtpDirParser {
337.186 +
337.187 + /**
337.188 + * Possible patterns:
337.189 + *
337.190 + * drwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog
337.191 + * drwxr-xr-x 1 user01 ftp 512 Jan 29 1997 prog
337.192 + * drwxr-xr-x 1 1 1 512 Jan 29 23:32 prog
337.193 + * lrwxr-xr-x 1 user01 ftp 512 Jan 29 23:32 prog -> prog2000
337.194 + * drwxr-xr-x 1 username ftp 512 Jan 29 23:32 prog
337.195 + * -rw-r--r-- 1 jcc staff 105009 Feb 3 15:05 test.1
337.196 + *
337.197 + * 01-29-97 11:32PM <DIR> prog
337.198 + * 04/28/2006 09:12a 3,563 genBuffer.sh
337.199 + *
337.200 + * drwxr-xr-x folder 0 Jan 29 23:32 prog
337.201 + *
337.202 + * 0 DIR 01-29-97 23:32 PROG
337.203 + */
337.204 + private DefaultParser() {
337.205 + }
337.206 +
337.207 + public FtpDirEntry parseLine(String line) {
337.208 + String fdate = null;
337.209 + String fsize = null;
337.210 + String time = null;
337.211 + String filename = null;
337.212 + String permstring = null;
337.213 + String username = null;
337.214 + String groupname = null;
337.215 + boolean dir = false;
337.216 + Calendar now = Calendar.getInstance();
337.217 + int year = now.get(Calendar.YEAR);
337.218 +
337.219 + Matcher m = null;
337.220 + for (int j = 0; j < patterns.length; j++) {
337.221 + m = patterns[j].matcher(line);
337.222 + if (m.find()) {
337.223 + // 0 - file, 1 - size, 2 - date, 3 - time, 4 - year,
337.224 + // 5 - permissions, 6 - user, 7 - group
337.225 + filename = m.group(patternGroups[j][0]);
337.226 + fsize = m.group(patternGroups[j][1]);
337.227 + fdate = m.group(patternGroups[j][2]);
337.228 + if (patternGroups[j][4] > 0) {
337.229 + fdate += (", " + m.group(patternGroups[j][4]));
337.230 + } else if (patternGroups[j][3] > 0) {
337.231 + fdate += (", " + String.valueOf(year));
337.232 + }
337.233 + if (patternGroups[j][3] > 0) {
337.234 + time = m.group(patternGroups[j][3]);
337.235 + }
337.236 + if (patternGroups[j][5] > 0) {
337.237 + permstring = m.group(patternGroups[j][5]);
337.238 + dir = permstring.startsWith("d");
337.239 + }
337.240 + if (patternGroups[j][6] > 0) {
337.241 + username = m.group(patternGroups[j][6]);
337.242 + }
337.243 + if (patternGroups[j][7] > 0) {
337.244 + groupname = m.group(patternGroups[j][7]);
337.245 + }
337.246 + // Old DOS format
337.247 + if ("<DIR>".equals(fsize)) {
337.248 + dir = true;
337.249 + fsize = null;
337.250 + }
337.251 + }
337.252 + }
337.253 +
337.254 + if (filename != null) {
337.255 + Date d;
337.256 + try {
337.257 + d = df.parse(fdate);
337.258 + } catch (Exception e) {
337.259 + d = null;
337.260 + }
337.261 + if (d != null && time != null) {
337.262 + int c = time.indexOf(":");
337.263 + now.setTime(d);
337.264 + now.set(Calendar.HOUR, Integer.parseInt(time.substring(0, c)));
337.265 + now.set(Calendar.MINUTE, Integer.parseInt(time.substring(c + 1)));
337.266 + d = now.getTime();
337.267 + }
337.268 + // see if it's a symbolic link, i.e. the name if followed
337.269 + // by a -> and a path
337.270 + Matcher m2 = linkp.matcher(filename);
337.271 + if (m2.find()) {
337.272 + // Keep only the name then
337.273 + filename = m2.group(1);
337.274 + }
337.275 + boolean[][] perms = new boolean[3][3];
337.276 + for (int i = 0; i < 3; i++) {
337.277 + for (int j = 0; j < 3; j++) {
337.278 + perms[i][j] = (permstring.charAt((i * 3) + j) != '-');
337.279 + }
337.280 + }
337.281 + FtpDirEntry file = new FtpDirEntry(filename);
337.282 + file.setUser(username).setGroup(groupname);
337.283 + file.setSize(Long.parseLong(fsize)).setLastModified(d);
337.284 + file.setPermissions(perms);
337.285 + file.setType(dir ? FtpDirEntry.Type.DIR : (line.charAt(0) == 'l' ? FtpDirEntry.Type.LINK : FtpDirEntry.Type.FILE));
337.286 + return file;
337.287 + }
337.288 + return null;
337.289 + }
337.290 + }
337.291 +
337.292 + private class MLSxParser implements FtpDirParser {
337.293 +
337.294 + private SimpleDateFormat df = new SimpleDateFormat("yyyyMMddhhmmss");
337.295 +
337.296 + public FtpDirEntry parseLine(String line) {
337.297 + String name = null;
337.298 + int i = line.lastIndexOf(";");
337.299 + if (i > 0) {
337.300 + name = line.substring(i + 1).trim();
337.301 + line = line.substring(0, i);
337.302 + } else {
337.303 + name = line.trim();
337.304 + line = "";
337.305 + }
337.306 + FtpDirEntry file = new FtpDirEntry(name);
337.307 + while (!line.isEmpty()) {
337.308 + String s;
337.309 + i = line.indexOf(";");
337.310 + if (i > 0) {
337.311 + s = line.substring(0, i);
337.312 + line = line.substring(i + 1);
337.313 + } else {
337.314 + s = line;
337.315 + line = "";
337.316 + }
337.317 + i = s.indexOf("=");
337.318 + if (i > 0) {
337.319 + String fact = s.substring(0, i);
337.320 + String value = s.substring(i + 1);
337.321 + file.addFact(fact, value);
337.322 + }
337.323 + }
337.324 + String s = file.getFact("Size");
337.325 + if (s != null) {
337.326 + file.setSize(Long.parseLong(s));
337.327 + }
337.328 + s = file.getFact("Modify");
337.329 + if (s != null) {
337.330 + Date d = null;
337.331 + try {
337.332 + d = df.parse(s);
337.333 + } catch (ParseException ex) {
337.334 + }
337.335 + if (d != null) {
337.336 + file.setLastModified(d);
337.337 + }
337.338 + }
337.339 + s = file.getFact("Create");
337.340 + if (s != null) {
337.341 + Date d = null;
337.342 + try {
337.343 + d = df.parse(s);
337.344 + } catch (ParseException ex) {
337.345 + }
337.346 + if (d != null) {
337.347 + file.setCreated(d);
337.348 + }
337.349 + }
337.350 + s = file.getFact("Type");
337.351 + if (s != null) {
337.352 + if (s.equalsIgnoreCase("file")) {
337.353 + file.setType(FtpDirEntry.Type.FILE);
337.354 + }
337.355 + if (s.equalsIgnoreCase("dir")) {
337.356 + file.setType(FtpDirEntry.Type.DIR);
337.357 + }
337.358 + if (s.equalsIgnoreCase("cdir")) {
337.359 + file.setType(FtpDirEntry.Type.CDIR);
337.360 + }
337.361 + if (s.equalsIgnoreCase("pdir")) {
337.362 + file.setType(FtpDirEntry.Type.PDIR);
337.363 + }
337.364 + }
337.365 + return file;
337.366 + }
337.367 + };
337.368 + private FtpDirParser parser = new DefaultParser();
337.369 + private FtpDirParser mlsxParser = new MLSxParser();
337.370 + private static Pattern transPat = null;
337.371 +
337.372 + private void getTransferSize() {
337.373 + lastTransSize = -1;
337.374 + /**
337.375 + * If it's a start of data transfer response, let's try to extract
337.376 + * the size from the response string. Usually it looks like that:
337.377 + *
337.378 + * 150 Opening BINARY mode data connection for foo (6701 bytes).
337.379 + */
337.380 + String response = getLastResponseString();
337.381 + if (transPat == null) {
337.382 + transPat = Pattern.compile("150 Opening .*\\((\\d+) bytes\\).");
337.383 + }
337.384 + Matcher m = transPat.matcher(response);
337.385 + if (m.find()) {
337.386 + String s = m.group(1);
337.387 + lastTransSize = Long.parseLong(s);
337.388 + }
337.389 + }
337.390 +
337.391 + /**
337.392 + * extract the created file name from the response string:
337.393 + * 226 Transfer complete (unique file name:toto.txt.1).
337.394 + * Usually happens when a STOU (store unique) command had been issued.
337.395 + */
337.396 + private void getTransferName() {
337.397 + lastFileName = null;
337.398 + String response = getLastResponseString();
337.399 + int i = response.indexOf("unique file name:");
337.400 + int e = response.lastIndexOf(')');
337.401 + if (i >= 0) {
337.402 + i += 17; // Length of "unique file name:"
337.403 + lastFileName = response.substring(i, e);
337.404 + }
337.405 + }
337.406 +
337.407 + /**
337.408 + * Pulls the response from the server and returns the code as a
337.409 + * number. Returns -1 on failure.
337.410 + */
337.411 + private int readServerResponse() throws IOException {
337.412 + StringBuffer replyBuf = new StringBuffer(32);
337.413 + int c;
337.414 + int continuingCode = -1;
337.415 + int code;
337.416 + String response;
337.417 +
337.418 + serverResponse.setSize(0);
337.419 + while (true) {
337.420 + while ((c = in.read()) != -1) {
337.421 + if (c == '\r') {
337.422 + if ((c = in.read()) != '\n') {
337.423 + replyBuf.append('\r');
337.424 + }
337.425 + }
337.426 + replyBuf.append((char) c);
337.427 + if (c == '\n') {
337.428 + break;
337.429 + }
337.430 + }
337.431 + response = replyBuf.toString();
337.432 + replyBuf.setLength(0);
337.433 + if (logger.isLoggable(PlatformLogger.FINEST)) {
337.434 + logger.finest("Server [" + serverAddr + "] --> " + response);
337.435 + }
337.436 +
337.437 + if (response.length() == 0) {
337.438 + code = -1;
337.439 + } else {
337.440 + try {
337.441 + code = Integer.parseInt(response.substring(0, 3));
337.442 + } catch (NumberFormatException e) {
337.443 + code = -1;
337.444 + } catch (StringIndexOutOfBoundsException e) {
337.445 + /* this line doesn't contain a response code, so
337.446 + we just completely ignore it */
337.447 + continue;
337.448 + }
337.449 + }
337.450 + serverResponse.addElement(response);
337.451 + if (continuingCode != -1) {
337.452 + /* we've seen a ###- sequence */
337.453 + if (code != continuingCode ||
337.454 + (response.length() >= 4 && response.charAt(3) == '-')) {
337.455 + continue;
337.456 + } else {
337.457 + /* seen the end of code sequence */
337.458 + continuingCode = -1;
337.459 + break;
337.460 + }
337.461 + } else if (response.length() >= 4 && response.charAt(3) == '-') {
337.462 + continuingCode = code;
337.463 + continue;
337.464 + } else {
337.465 + break;
337.466 + }
337.467 + }
337.468 +
337.469 + return code;
337.470 + }
337.471 +
337.472 + /** Sends command <i>cmd</i> to the server. */
337.473 + private void sendServer(String cmd) {
337.474 + out.print(cmd);
337.475 + if (logger.isLoggable(PlatformLogger.FINEST)) {
337.476 + logger.finest("Server [" + serverAddr + "] <-- " + cmd);
337.477 + }
337.478 + }
337.479 +
337.480 + /** converts the server response into a string. */
337.481 + private String getResponseString() {
337.482 + return serverResponse.elementAt(0);
337.483 + }
337.484 +
337.485 + /** Returns all server response strings. */
337.486 + private Vector<String> getResponseStrings() {
337.487 + return serverResponse;
337.488 + }
337.489 +
337.490 + /**
337.491 + * Read the reply from the FTP server.
337.492 + *
337.493 + * @return <code>true</code> if the command was successful
337.494 + * @throws IOException if an error occured
337.495 + */
337.496 + private boolean readReply() throws IOException {
337.497 + lastReplyCode = FtpReplyCode.find(readServerResponse());
337.498 +
337.499 + if (lastReplyCode.isPositivePreliminary()) {
337.500 + replyPending = true;
337.501 + return true;
337.502 + }
337.503 + if (lastReplyCode.isPositiveCompletion() || lastReplyCode.isPositiveIntermediate()) {
337.504 + if (lastReplyCode == FtpReplyCode.CLOSING_DATA_CONNECTION) {
337.505 + getTransferName();
337.506 + }
337.507 + return true;
337.508 + }
337.509 + return false;
337.510 + }
337.511 +
337.512 + /**
337.513 + * Sends a command to the FTP server and returns the error code
337.514 + * (which can be a "success") sent by the server.
337.515 + *
337.516 + * @param cmd
337.517 + * @return <code>true</code> if the command was successful
337.518 + * @throws IOException
337.519 + */
337.520 + private boolean issueCommand(String cmd) throws IOException {
337.521 + if (!isConnected()) {
337.522 + throw new IllegalStateException("Not connected");
337.523 + }
337.524 + if (replyPending) {
337.525 + try {
337.526 + completePending();
337.527 + } catch (sun.net.ftp.FtpProtocolException e) {
337.528 + // ignore...
337.529 + }
337.530 + }
337.531 + sendServer(cmd + "\r\n");
337.532 + return readReply();
337.533 + }
337.534 +
337.535 + /**
337.536 + * Send a command to the FTP server and check for success.
337.537 + *
337.538 + * @param cmd String containing the command
337.539 + *
337.540 + * @throws FtpProtocolException if an error occured
337.541 + */
337.542 + private void issueCommandCheck(String cmd) throws sun.net.ftp.FtpProtocolException, IOException {
337.543 + if (!issueCommand(cmd)) {
337.544 + throw new sun.net.ftp.FtpProtocolException(cmd + ":" + getResponseString(), getLastReplyCode());
337.545 + }
337.546 + }
337.547 + private static Pattern epsvPat = null;
337.548 + private static Pattern pasvPat = null;
337.549 +
337.550 + /**
337.551 + * Opens a "PASSIVE" connection with the server and returns the connected
337.552 + * <code>Socket</code>.
337.553 + *
337.554 + * @return the connected <code>Socket</code>
337.555 + * @throws IOException if the connection was unsuccessful.
337.556 + */
337.557 + private Socket openPassiveDataConnection(String cmd) throws sun.net.ftp.FtpProtocolException, IOException {
337.558 + String serverAnswer;
337.559 + int port;
337.560 + InetSocketAddress dest = null;
337.561 +
337.562 + /**
337.563 + * Here is the idea:
337.564 + *
337.565 + * - First we want to try the new (and IPv6 compatible) EPSV command
337.566 + * But since we want to be nice with NAT software, we'll issue the
337.567 + * EPSV ALL command first.
337.568 + * EPSV is documented in RFC2428
337.569 + * - If EPSV fails, then we fall back to the older, yet ok, PASV
337.570 + * - If PASV fails as well, then we throw an exception and the calling
337.571 + * method will have to try the EPRT or PORT command
337.572 + */
337.573 + if (issueCommand("EPSV ALL")) {
337.574 + // We can safely use EPSV commands
337.575 + issueCommandCheck("EPSV");
337.576 + serverAnswer = getResponseString();
337.577 +
337.578 + // The response string from a EPSV command will contain the port number
337.579 + // the format will be :
337.580 + // 229 Entering Extended PASSIVE Mode (|||58210|)
337.581 + //
337.582 + // So we'll use the regular expresions package to parse the output.
337.583 +
337.584 + if (epsvPat == null) {
337.585 + epsvPat = Pattern.compile("^229 .* \\(\\|\\|\\|(\\d+)\\|\\)");
337.586 + }
337.587 + Matcher m = epsvPat.matcher(serverAnswer);
337.588 + if (!m.find()) {
337.589 + throw new sun.net.ftp.FtpProtocolException("EPSV failed : " + serverAnswer);
337.590 + }
337.591 + // Yay! Let's extract the port number
337.592 + String s = m.group(1);
337.593 + port = Integer.parseInt(s);
337.594 + InetAddress add = server.getInetAddress();
337.595 + if (add != null) {
337.596 + dest = new InetSocketAddress(add, port);
337.597 + } else {
337.598 + // This means we used an Unresolved address to connect in
337.599 + // the first place. Most likely because the proxy is doing
337.600 + // the name resolution for us, so let's keep using unresolved
337.601 + // address.
337.602 + dest = InetSocketAddress.createUnresolved(serverAddr.getHostName(), port);
337.603 + }
337.604 + } else {
337.605 + // EPSV ALL failed, so Let's try the regular PASV cmd
337.606 + issueCommandCheck("PASV");
337.607 + serverAnswer = getResponseString();
337.608 +
337.609 + // Let's parse the response String to get the IP & port to connect
337.610 + // to. The String should be in the following format :
337.611 + //
337.612 + // 227 Entering PASSIVE Mode (A1,A2,A3,A4,p1,p2)
337.613 + //
337.614 + // Note that the two parenthesis are optional
337.615 + //
337.616 + // The IP address is A1.A2.A3.A4 and the port is p1 * 256 + p2
337.617 + //
337.618 + // The regular expression is a bit more complex this time, because
337.619 + // the parenthesis are optionals and we have to use 3 groups.
337.620 +
337.621 + if (pasvPat == null) {
337.622 + pasvPat = Pattern.compile("227 .* \\(?(\\d{1,3},\\d{1,3},\\d{1,3},\\d{1,3}),(\\d{1,3}),(\\d{1,3})\\)?");
337.623 + }
337.624 + Matcher m = pasvPat.matcher(serverAnswer);
337.625 + if (!m.find()) {
337.626 + throw new sun.net.ftp.FtpProtocolException("PASV failed : " + serverAnswer);
337.627 + }
337.628 + // Get port number out of group 2 & 3
337.629 + port = Integer.parseInt(m.group(3)) + (Integer.parseInt(m.group(2)) << 8);
337.630 + // IP address is simple
337.631 + String s = m.group(1).replace(',', '.');
337.632 + dest = new InetSocketAddress(s, port);
337.633 + }
337.634 + // Got everything, let's open the socket!
337.635 + Socket s;
337.636 + if (proxy != null) {
337.637 + if (proxy.type() == Proxy.Type.SOCKS) {
337.638 + s = AccessController.doPrivileged(
337.639 + new PrivilegedAction<Socket>() {
337.640 +
337.641 + public Socket run() {
337.642 + return new Socket(proxy);
337.643 + }
337.644 + });
337.645 + } else {
337.646 + s = new Socket(Proxy.NO_PROXY);
337.647 + }
337.648 + } else {
337.649 + s = new Socket();
337.650 + }
337.651 + // Bind the socket to the same address as the control channel. This
337.652 + // is needed in case of multi-homed systems.
337.653 + s.bind(new InetSocketAddress(server.getLocalAddress(), 0));
337.654 + if (connectTimeout >= 0) {
337.655 + s.connect(dest, connectTimeout);
337.656 + } else {
337.657 + if (defaultConnectTimeout > 0) {
337.658 + s.connect(dest, defaultConnectTimeout);
337.659 + } else {
337.660 + s.connect(dest);
337.661 + }
337.662 + }
337.663 + if (readTimeout >= 0) {
337.664 + s.setSoTimeout(readTimeout);
337.665 + } else if (defaultSoTimeout > 0) {
337.666 + s.setSoTimeout(defaultSoTimeout);
337.667 + }
337.668 + if (useCrypto) {
337.669 + try {
337.670 + s = sslFact.createSocket(s, dest.getHostName(), dest.getPort(), true);
337.671 + } catch (Exception e) {
337.672 + throw new sun.net.ftp.FtpProtocolException("Can't open secure data channel: " + e);
337.673 + }
337.674 + }
337.675 + if (!issueCommand(cmd)) {
337.676 + s.close();
337.677 + throw new sun.net.ftp.FtpProtocolException(cmd + ":" + getResponseString(), getLastReplyCode());
337.678 + }
337.679 + return s;
337.680 + }
337.681 +
337.682 + /**
337.683 + * Opens a data connection with the server according to the set mode
337.684 + * (ACTIVE or PASSIVE) then send the command passed as an argument.
337.685 + *
337.686 + * @param cmd the <code>String</code> containing the command to execute
337.687 + * @return the connected <code>Socket</code>
337.688 + * @throws IOException if the connection or command failed
337.689 + */
337.690 + private Socket openDataConnection(String cmd) throws sun.net.ftp.FtpProtocolException, IOException {
337.691 + Socket clientSocket;
337.692 +
337.693 + if (passiveMode) {
337.694 + return openPassiveDataConnection(cmd);
337.695 + }
337.696 + ServerSocket portSocket;
337.697 + InetAddress myAddress;
337.698 + String portCmd;
337.699 +
337.700 + if (proxy != null && proxy.type() == Proxy.Type.SOCKS) {
337.701 + // We're behind a firewall and the passive mode fail,
337.702 + // since we can't accept a connection through SOCKS (yet)
337.703 + // throw an exception
337.704 + throw new sun.net.ftp.FtpProtocolException("Passive mode failed");
337.705 + }
337.706 + // Bind the ServerSocket to the same address as the control channel
337.707 + // This is needed for multi-homed systems
337.708 + portSocket = new ServerSocket(0, 1, server.getLocalAddress());
337.709 + try {
337.710 + myAddress = portSocket.getInetAddress();
337.711 + if (myAddress.isAnyLocalAddress()) {
337.712 + myAddress = server.getLocalAddress();
337.713 + }
337.714 + // Let's try the new, IPv6 compatible EPRT command
337.715 + // See RFC2428 for specifics
337.716 + // Some FTP servers (like the one on Solaris) are bugged, they
337.717 + // will accept the EPRT command but then, the subsequent command
337.718 + // (e.g. RETR) will fail, so we have to check BOTH results (the
337.719 + // EPRT cmd then the actual command) to decide wether we should
337.720 + // fall back on the older PORT command.
337.721 + portCmd = "EPRT |" + ((myAddress instanceof Inet6Address) ? "2" : "1") + "|" +
337.722 + myAddress.getHostAddress() + "|" + portSocket.getLocalPort() + "|";
337.723 + if (!issueCommand(portCmd) || !issueCommand(cmd)) {
337.724 + // The EPRT command failed, let's fall back to good old PORT
337.725 + portCmd = "PORT ";
337.726 + byte[] addr = myAddress.getAddress();
337.727 +
337.728 + /* append host addr */
337.729 + for (int i = 0; i < addr.length; i++) {
337.730 + portCmd = portCmd + (addr[i] & 0xFF) + ",";
337.731 + }
337.732 +
337.733 + /* append port number */
337.734 + portCmd = portCmd + ((portSocket.getLocalPort() >>> 8) & 0xff) + "," + (portSocket.getLocalPort() & 0xff);
337.735 + issueCommandCheck(portCmd);
337.736 + issueCommandCheck(cmd);
337.737 + }
337.738 + // Either the EPRT or the PORT command was successful
337.739 + // Let's create the client socket
337.740 + if (connectTimeout >= 0) {
337.741 + portSocket.setSoTimeout(connectTimeout);
337.742 + } else {
337.743 + if (defaultConnectTimeout > 0) {
337.744 + portSocket.setSoTimeout(defaultConnectTimeout);
337.745 + }
337.746 + }
337.747 + clientSocket = portSocket.accept();
337.748 + if (readTimeout >= 0) {
337.749 + clientSocket.setSoTimeout(readTimeout);
337.750 + } else {
337.751 + if (defaultSoTimeout > 0) {
337.752 + clientSocket.setSoTimeout(defaultSoTimeout);
337.753 + }
337.754 + }
337.755 + } finally {
337.756 + portSocket.close();
337.757 + }
337.758 + if (useCrypto) {
337.759 + try {
337.760 + clientSocket = sslFact.createSocket(clientSocket, serverAddr.getHostName(), serverAddr.getPort(), true);
337.761 + } catch (Exception ex) {
337.762 + throw new IOException(ex.getLocalizedMessage());
337.763 + }
337.764 + }
337.765 + return clientSocket;
337.766 + }
337.767 +
337.768 + private InputStream createInputStream(InputStream in) {
337.769 + if (type == TransferType.ASCII) {
337.770 + return new sun.net.TelnetInputStream(in, false);
337.771 + }
337.772 + return in;
337.773 + }
337.774 +
337.775 + private OutputStream createOutputStream(OutputStream out) {
337.776 + if (type == TransferType.ASCII) {
337.777 + return new sun.net.TelnetOutputStream(out, false);
337.778 + }
337.779 + return out;
337.780 + }
337.781 +
337.782 + /**
337.783 + * Creates an instance of FtpClient. The client is not connected to any
337.784 + * server yet.
337.785 + *
337.786 + */
337.787 + protected FtpClient() {
337.788 + }
337.789 +
337.790 + /**
337.791 + * Creates an instance of FtpClient. The client is not connected to any
337.792 + * server yet.
337.793 + *
337.794 + */
337.795 + public static sun.net.ftp.FtpClient create() {
337.796 + return new FtpClient();
337.797 + }
337.798 +
337.799 + /**
337.800 + * Set the transfer mode to <I>passive</I>. In that mode, data connections
337.801 + * are established by having the client connect to the server.
337.802 + * This is the recommended default mode as it will work best through
337.803 + * firewalls and NATs.
337.804 + *
337.805 + * @return This FtpClient
337.806 + * @see #setActiveMode()
337.807 + */
337.808 + public sun.net.ftp.FtpClient enablePassiveMode(boolean passive) {
337.809 + passiveMode = passive;
337.810 + return this;
337.811 + }
337.812 +
337.813 + /**
337.814 + * Gets the current transfer mode.
337.815 + *
337.816 + * @return the current <code>FtpTransferMode</code>
337.817 + */
337.818 + public boolean isPassiveModeEnabled() {
337.819 + return passiveMode;
337.820 + }
337.821 +
337.822 + /**
337.823 + * Sets the timeout value to use when connecting to the server,
337.824 + *
337.825 + * @param timeout the timeout value, in milliseconds, to use for the connect
337.826 + * operation. A value of zero or less, means use the default timeout.
337.827 + *
337.828 + * @return This FtpClient
337.829 + */
337.830 + public sun.net.ftp.FtpClient setConnectTimeout(int timeout) {
337.831 + connectTimeout = timeout;
337.832 + return this;
337.833 + }
337.834 +
337.835 + /**
337.836 + * Returns the current connection timeout value.
337.837 + *
337.838 + * @return the value, in milliseconds, of the current connect timeout.
337.839 + * @see #setConnectTimeout(int)
337.840 + */
337.841 + public int getConnectTimeout() {
337.842 + return connectTimeout;
337.843 + }
337.844 +
337.845 + /**
337.846 + * Sets the timeout value to use when reading from the server,
337.847 + *
337.848 + * @param timeout the timeout value, in milliseconds, to use for the read
337.849 + * operation. A value of zero or less, means use the default timeout.
337.850 + * @return This FtpClient
337.851 + */
337.852 + public sun.net.ftp.FtpClient setReadTimeout(int timeout) {
337.853 + readTimeout = timeout;
337.854 + return this;
337.855 + }
337.856 +
337.857 + /**
337.858 + * Returns the current read timeout value.
337.859 + *
337.860 + * @return the value, in milliseconds, of the current read timeout.
337.861 + * @see #setReadTimeout(int)
337.862 + */
337.863 + public int getReadTimeout() {
337.864 + return readTimeout;
337.865 + }
337.866 +
337.867 + public sun.net.ftp.FtpClient setProxy(Proxy p) {
337.868 + proxy = p;
337.869 + return this;
337.870 + }
337.871 +
337.872 + /**
337.873 + * Get the proxy of this FtpClient
337.874 + *
337.875 + * @return the <code>Proxy</code>, this client is using, or <code>null</code>
337.876 + * if none is used.
337.877 + * @see #setProxy(Proxy)
337.878 + */
337.879 + public Proxy getProxy() {
337.880 + return proxy;
337.881 + }
337.882 +
337.883 + /**
337.884 + * Connects to the specified destination.
337.885 + *
337.886 + * @param dest the <code>InetSocketAddress</code> to connect to.
337.887 + * @throws IOException if the connection fails.
337.888 + */
337.889 + private void tryConnect(InetSocketAddress dest, int timeout) throws IOException {
337.890 + if (isConnected()) {
337.891 + disconnect();
337.892 + }
337.893 + server = doConnect(dest, timeout);
337.894 + try {
337.895 + out = new PrintStream(new BufferedOutputStream(server.getOutputStream()),
337.896 + true, encoding);
337.897 + } catch (UnsupportedEncodingException e) {
337.898 + throw new InternalError(encoding + "encoding not found");
337.899 + }
337.900 + in = new BufferedInputStream(server.getInputStream());
337.901 + }
337.902 +
337.903 + private Socket doConnect(InetSocketAddress dest, int timeout) throws IOException {
337.904 + Socket s;
337.905 + if (proxy != null) {
337.906 + if (proxy.type() == Proxy.Type.SOCKS) {
337.907 + s = AccessController.doPrivileged(
337.908 + new PrivilegedAction<Socket>() {
337.909 +
337.910 + public Socket run() {
337.911 + return new Socket(proxy);
337.912 + }
337.913 + });
337.914 + } else {
337.915 + s = new Socket(Proxy.NO_PROXY);
337.916 + }
337.917 + } else {
337.918 + s = new Socket();
337.919 + }
337.920 + // Instance specific timeouts do have priority, that means
337.921 + // connectTimeout & readTimeout (-1 means not set)
337.922 + // Then global default timeouts
337.923 + // Then no timeout.
337.924 + if (timeout >= 0) {
337.925 + s.connect(dest, timeout);
337.926 + } else {
337.927 + if (connectTimeout >= 0) {
337.928 + s.connect(dest, connectTimeout);
337.929 + } else {
337.930 + if (defaultConnectTimeout > 0) {
337.931 + s.connect(dest, defaultConnectTimeout);
337.932 + } else {
337.933 + s.connect(dest);
337.934 + }
337.935 + }
337.936 + }
337.937 + if (readTimeout >= 0) {
337.938 + s.setSoTimeout(readTimeout);
337.939 + } else if (defaultSoTimeout > 0) {
337.940 + s.setSoTimeout(defaultSoTimeout);
337.941 + }
337.942 + return s;
337.943 + }
337.944 +
337.945 + private void disconnect() throws IOException {
337.946 + if (isConnected()) {
337.947 + server.close();
337.948 + }
337.949 + server = null;
337.950 + in = null;
337.951 + out = null;
337.952 + lastTransSize = -1;
337.953 + lastFileName = null;
337.954 + restartOffset = 0;
337.955 + welcomeMsg = null;
337.956 + lastReplyCode = null;
337.957 + serverResponse.setSize(0);
337.958 + }
337.959 +
337.960 + /**
337.961 + * Tests whether this client is connected or not to a server.
337.962 + *
337.963 + * @return <code>true</code> if the client is connected.
337.964 + */
337.965 + public boolean isConnected() {
337.966 + return server != null;
337.967 + }
337.968 +
337.969 + public SocketAddress getServerAddress() {
337.970 + return server == null ? null : server.getRemoteSocketAddress();
337.971 + }
337.972 +
337.973 + public sun.net.ftp.FtpClient connect(SocketAddress dest) throws sun.net.ftp.FtpProtocolException, IOException {
337.974 + return connect(dest, -1);
337.975 + }
337.976 +
337.977 + /**
337.978 + * Connects the FtpClient to the specified destination.
337.979 + *
337.980 + * @param dest the address of the destination server
337.981 + * @throws IOException if connection failed.
337.982 + */
337.983 + public sun.net.ftp.FtpClient connect(SocketAddress dest, int timeout) throws sun.net.ftp.FtpProtocolException, IOException {
337.984 + if (!(dest instanceof InetSocketAddress)) {
337.985 + throw new IllegalArgumentException("Wrong address type");
337.986 + }
337.987 + serverAddr = (InetSocketAddress) dest;
337.988 + tryConnect(serverAddr, timeout);
337.989 + if (!readReply()) {
337.990 + throw new sun.net.ftp.FtpProtocolException("Welcome message: " +
337.991 + getResponseString(), lastReplyCode);
337.992 + }
337.993 + welcomeMsg = getResponseString().substring(4);
337.994 + return this;
337.995 + }
337.996 +
337.997 + private void tryLogin(String user, char[] password) throws sun.net.ftp.FtpProtocolException, IOException {
337.998 + issueCommandCheck("USER " + user);
337.999 +
337.1000 + /*
337.1001 + * Checks for "331 User name okay, need password." answer
337.1002 + */
337.1003 + if (lastReplyCode == FtpReplyCode.NEED_PASSWORD) {
337.1004 + if ((password != null) && (password.length > 0)) {
337.1005 + issueCommandCheck("PASS " + String.valueOf(password));
337.1006 + }
337.1007 + }
337.1008 + }
337.1009 +
337.1010 + /**
337.1011 + * Attempts to log on the server with the specified user name and password.
337.1012 + *
337.1013 + * @param user The user name
337.1014 + * @param password The password for that user
337.1015 + * @return <code>true</code> if the login was successful.
337.1016 + * @throws IOException if an error occured during the transmission
337.1017 + */
337.1018 + public sun.net.ftp.FtpClient login(String user, char[] password) throws sun.net.ftp.FtpProtocolException, IOException {
337.1019 + if (!isConnected()) {
337.1020 + throw new sun.net.ftp.FtpProtocolException("Not connected yet", FtpReplyCode.BAD_SEQUENCE);
337.1021 + }
337.1022 + if (user == null || user.length() == 0) {
337.1023 + throw new IllegalArgumentException("User name can't be null or empty");
337.1024 + }
337.1025 + tryLogin(user, password);
337.1026 +
337.1027 + // keep the welcome message around so we can
337.1028 + // put it in the resulting HTML page.
337.1029 + String l;
337.1030 + StringBuffer sb = new StringBuffer();
337.1031 + for (int i = 0; i < serverResponse.size(); i++) {
337.1032 + l = serverResponse.elementAt(i);
337.1033 + if (l != null) {
337.1034 + if (l.length() >= 4 && l.startsWith("230")) {
337.1035 + // get rid of the "230-" prefix
337.1036 + l = l.substring(4);
337.1037 + }
337.1038 + sb.append(l);
337.1039 + }
337.1040 + }
337.1041 + welcomeMsg = sb.toString();
337.1042 + loggedIn = true;
337.1043 + return this;
337.1044 + }
337.1045 +
337.1046 + /**
337.1047 + * Attempts to log on the server with the specified user name, password and
337.1048 + * account name.
337.1049 + *
337.1050 + * @param user The user name
337.1051 + * @param password The password for that user.
337.1052 + * @param account The account name for that user.
337.1053 + * @return <code>true</code> if the login was successful.
337.1054 + * @throws IOException if an error occurs during the transmission.
337.1055 + */
337.1056 + public sun.net.ftp.FtpClient login(String user, char[] password, String account) throws sun.net.ftp.FtpProtocolException, IOException {
337.1057 +
337.1058 + if (!isConnected()) {
337.1059 + throw new sun.net.ftp.FtpProtocolException("Not connected yet", FtpReplyCode.BAD_SEQUENCE);
337.1060 + }
337.1061 + if (user == null || user.length() == 0) {
337.1062 + throw new IllegalArgumentException("User name can't be null or empty");
337.1063 + }
337.1064 + tryLogin(user, password);
337.1065 +
337.1066 + /*
337.1067 + * Checks for "332 Need account for login." answer
337.1068 + */
337.1069 + if (lastReplyCode == FtpReplyCode.NEED_ACCOUNT) {
337.1070 + issueCommandCheck("ACCT " + account);
337.1071 + }
337.1072 +
337.1073 + // keep the welcome message around so we can
337.1074 + // put it in the resulting HTML page.
337.1075 + StringBuffer sb = new StringBuffer();
337.1076 + if (serverResponse != null) {
337.1077 + for (String l : serverResponse) {
337.1078 + if (l != null) {
337.1079 + if (l.length() >= 4 && l.startsWith("230")) {
337.1080 + // get rid of the "230-" prefix
337.1081 + l = l.substring(4);
337.1082 + }
337.1083 + sb.append(l);
337.1084 + }
337.1085 + }
337.1086 + }
337.1087 + welcomeMsg = sb.toString();
337.1088 + loggedIn = true;
337.1089 + return this;
337.1090 + }
337.1091 +
337.1092 + /**
337.1093 + * Logs out the current user. This is in effect terminates the current
337.1094 + * session and the connection to the server will be closed.
337.1095 + *
337.1096 + */
337.1097 + public void close() throws IOException {
337.1098 + if (isConnected()) {
337.1099 + issueCommand("QUIT");
337.1100 + loggedIn = false;
337.1101 + }
337.1102 + disconnect();
337.1103 + }
337.1104 +
337.1105 + /**
337.1106 + * Checks whether the client is logged in to the server or not.
337.1107 + *
337.1108 + * @return <code>true</code> if the client has already completed a login.
337.1109 + */
337.1110 + public boolean isLoggedIn() {
337.1111 + return loggedIn;
337.1112 + }
337.1113 +
337.1114 + /**
337.1115 + * Changes to a specific directory on a remote FTP server
337.1116 + *
337.1117 + * @param remoteDirectory path of the directory to CD to.
337.1118 + * @return <code>true</code> if the operation was successful.
337.1119 + * @exception <code>FtpProtocolException</code>
337.1120 + */
337.1121 + public sun.net.ftp.FtpClient changeDirectory(String remoteDirectory) throws sun.net.ftp.FtpProtocolException, IOException {
337.1122 + if (remoteDirectory == null || "".equals(remoteDirectory)) {
337.1123 + throw new IllegalArgumentException("directory can't be null or empty");
337.1124 + }
337.1125 +
337.1126 + issueCommandCheck("CWD " + remoteDirectory);
337.1127 + return this;
337.1128 + }
337.1129 +
337.1130 + /**
337.1131 + * Changes to the parent directory, sending the CDUP command to the server.
337.1132 + *
337.1133 + * @return <code>true</code> if the command was successful.
337.1134 + * @throws IOException
337.1135 + */
337.1136 + public sun.net.ftp.FtpClient changeToParentDirectory() throws sun.net.ftp.FtpProtocolException, IOException {
337.1137 + issueCommandCheck("CDUP");
337.1138 + return this;
337.1139 + }
337.1140 +
337.1141 + /**
337.1142 + * Returns the server current working directory, or <code>null</code> if
337.1143 + * the PWD command failed.
337.1144 + *
337.1145 + * @return a <code>String</code> containing the current working directory,
337.1146 + * or <code>null</code>
337.1147 + * @throws IOException
337.1148 + */
337.1149 + public String getWorkingDirectory() throws sun.net.ftp.FtpProtocolException, IOException {
337.1150 + issueCommandCheck("PWD");
337.1151 + /*
337.1152 + * answer will be of the following format :
337.1153 + *
337.1154 + * 257 "/" is current directory.
337.1155 + */
337.1156 + String answ = getResponseString();
337.1157 + if (!answ.startsWith("257")) {
337.1158 + return null;
337.1159 + }
337.1160 + return answ.substring(5, answ.lastIndexOf('"'));
337.1161 + }
337.1162 +
337.1163 + /**
337.1164 + * Sets the restart offset to the specified value. That value will be
337.1165 + * sent through a <code>REST</code> command to server before a file
337.1166 + * transfer and has the effect of resuming a file transfer from the
337.1167 + * specified point. After a transfer the restart offset is set back to
337.1168 + * zero.
337.1169 + *
337.1170 + * @param offset the offset in the remote file at which to start the next
337.1171 + * transfer. This must be a value greater than or equal to zero.
337.1172 + * @throws IllegalArgumentException if the offset is negative.
337.1173 + */
337.1174 + public sun.net.ftp.FtpClient setRestartOffset(long offset) {
337.1175 + if (offset < 0) {
337.1176 + throw new IllegalArgumentException("offset can't be negative");
337.1177 + }
337.1178 + restartOffset = offset;
337.1179 + return this;
337.1180 + }
337.1181 +
337.1182 + /**
337.1183 + * Retrieves a file from the ftp server and writes it to the specified
337.1184 + * <code>OutputStream</code>.
337.1185 + * If the restart offset was set, then a <code>REST</code> command will be
337.1186 + * sent before the RETR in order to restart the tranfer from the specified
337.1187 + * offset.
337.1188 + * The <code>OutputStream</code> is not closed by this method at the end
337.1189 + * of the transfer.
337.1190 + *
337.1191 + * @param name a <code>String<code> containing the name of the file to
337.1192 + * retreive from the server.
337.1193 + * @param local the <code>OutputStream</code> the file should be written to.
337.1194 + * @throws IOException if the transfer fails.
337.1195 + */
337.1196 + public sun.net.ftp.FtpClient getFile(String name, OutputStream local) throws sun.net.ftp.FtpProtocolException, IOException {
337.1197 + int mtu = 1500;
337.1198 + if (restartOffset > 0) {
337.1199 + Socket s;
337.1200 + try {
337.1201 + s = openDataConnection("REST " + restartOffset);
337.1202 + } finally {
337.1203 + restartOffset = 0;
337.1204 + }
337.1205 + issueCommandCheck("RETR " + name);
337.1206 + getTransferSize();
337.1207 + InputStream remote = createInputStream(s.getInputStream());
337.1208 + byte[] buf = new byte[mtu * 10];
337.1209 + int l;
337.1210 + while ((l = remote.read(buf)) >= 0) {
337.1211 + if (l > 0) {
337.1212 + local.write(buf, 0, l);
337.1213 + }
337.1214 + }
337.1215 + remote.close();
337.1216 + } else {
337.1217 + Socket s = openDataConnection("RETR " + name);
337.1218 + getTransferSize();
337.1219 + InputStream remote = createInputStream(s.getInputStream());
337.1220 + byte[] buf = new byte[mtu * 10];
337.1221 + int l;
337.1222 + while ((l = remote.read(buf)) >= 0) {
337.1223 + if (l > 0) {
337.1224 + local.write(buf, 0, l);
337.1225 + }
337.1226 + }
337.1227 + remote.close();
337.1228 + }
337.1229 + return completePending();
337.1230 + }
337.1231 +
337.1232 + /**
337.1233 + * Retrieves a file from the ftp server, using the RETR command, and
337.1234 + * returns the InputStream from* the established data connection.
337.1235 + * {@link #completePending()} <b>has</b> to be called once the application
337.1236 + * is done reading from the returned stream.
337.1237 + *
337.1238 + * @param name the name of the remote file
337.1239 + * @return the {@link java.io.InputStream} from the data connection, or
337.1240 + * <code>null</code> if the command was unsuccessful.
337.1241 + * @throws IOException if an error occured during the transmission.
337.1242 + */
337.1243 + public InputStream getFileStream(String name) throws sun.net.ftp.FtpProtocolException, IOException {
337.1244 + Socket s;
337.1245 + if (restartOffset > 0) {
337.1246 + try {
337.1247 + s = openDataConnection("REST " + restartOffset);
337.1248 + } finally {
337.1249 + restartOffset = 0;
337.1250 + }
337.1251 + if (s == null) {
337.1252 + return null;
337.1253 + }
337.1254 + issueCommandCheck("RETR " + name);
337.1255 + getTransferSize();
337.1256 + return createInputStream(s.getInputStream());
337.1257 + }
337.1258 +
337.1259 + s = openDataConnection("RETR " + name);
337.1260 + if (s == null) {
337.1261 + return null;
337.1262 + }
337.1263 + getTransferSize();
337.1264 + return createInputStream(s.getInputStream());
337.1265 + }
337.1266 +
337.1267 + /**
337.1268 + * Transfers a file from the client to the server (aka a <I>put</I>)
337.1269 + * by sending the STOR or STOU command, depending on the
337.1270 + * <code>unique</code> argument, and returns the <code>OutputStream</code>
337.1271 + * from the established data connection.
337.1272 + * {@link #completePending()} <b>has</b> to be called once the application
337.1273 + * is finished writing to the stream.
337.1274 + *
337.1275 + * A new file is created at the server site if the file specified does
337.1276 + * not already exist.
337.1277 + *
337.1278 + * If <code>unique</code> is set to <code>true</code>, the resultant file
337.1279 + * is to be created under a name unique to that directory, meaning
337.1280 + * it will not overwrite an existing file, instead the server will
337.1281 + * generate a new, unique, file name.
337.1282 + * The name of the remote file can be retrieved, after completion of the
337.1283 + * transfer, by calling {@link #getLastFileName()}.
337.1284 + *
337.1285 + * @param name the name of the remote file to write.
337.1286 + * @param unique <code>true</code> if the remote files should be unique,
337.1287 + * in which case the STOU command will be used.
337.1288 + * @return the {@link java.io.OutputStream} from the data connection or
337.1289 + * <code>null</code> if the command was unsuccessful.
337.1290 + * @throws IOException if an error occured during the transmission.
337.1291 + */
337.1292 + public OutputStream putFileStream(String name, boolean unique) throws sun.net.ftp.FtpProtocolException, IOException {
337.1293 + String cmd = unique ? "STOU " : "STOR ";
337.1294 + Socket s = openDataConnection(cmd + name);
337.1295 + if (s == null) {
337.1296 + return null;
337.1297 + }
337.1298 + if (type == TransferType.BINARY) {
337.1299 + return s.getOutputStream();
337.1300 + }
337.1301 + return new sun.net.TelnetOutputStream(s.getOutputStream(), false);
337.1302 + }
337.1303 +
337.1304 + /**
337.1305 + * Transfers a file from the client to the server (aka a <I>put</I>)
337.1306 + * by sending the STOR command. The content of the <code>InputStream</code>
337.1307 + * passed in argument is written into the remote file, overwriting any
337.1308 + * existing data.
337.1309 + *
337.1310 + * A new file is created at the server site if the file specified does
337.1311 + * not already exist.
337.1312 + *
337.1313 + * @param name the name of the remote file to write.
337.1314 + * @param local the <code>InputStream</code> that points to the data to
337.1315 + * transfer.
337.1316 + * @param unique <code>true</code> if the remote file should be unique
337.1317 + * (i.e. not already existing), <code>false</code> otherwise.
337.1318 + * @return <code>true</code> if the transfer was successful.
337.1319 + * @throws IOException if an error occured during the transmission.
337.1320 + * @see #getLastFileName()
337.1321 + */
337.1322 + public sun.net.ftp.FtpClient putFile(String name, InputStream local, boolean unique) throws sun.net.ftp.FtpProtocolException, IOException {
337.1323 + String cmd = unique ? "STOU " : "STOR ";
337.1324 + int mtu = 1500;
337.1325 + if (type == TransferType.BINARY) {
337.1326 + Socket s = openDataConnection(cmd + name);
337.1327 + OutputStream remote = createOutputStream(s.getOutputStream());
337.1328 + byte[] buf = new byte[mtu * 10];
337.1329 + int l;
337.1330 + while ((l = local.read(buf)) >= 0) {
337.1331 + if (l > 0) {
337.1332 + remote.write(buf, 0, l);
337.1333 + }
337.1334 + }
337.1335 + remote.close();
337.1336 + }
337.1337 + return completePending();
337.1338 + }
337.1339 +
337.1340 + /**
337.1341 + * Sends the APPE command to the server in order to transfer a data stream
337.1342 + * passed in argument and append it to the content of the specified remote
337.1343 + * file.
337.1344 + *
337.1345 + * @param name A <code>String</code> containing the name of the remote file
337.1346 + * to append to.
337.1347 + * @param local The <code>InputStream</code> providing access to the data
337.1348 + * to be appended.
337.1349 + * @return <code>true</code> if the transfer was successful.
337.1350 + * @throws IOException if an error occured during the transmission.
337.1351 + */
337.1352 + public sun.net.ftp.FtpClient appendFile(String name, InputStream local) throws sun.net.ftp.FtpProtocolException, IOException {
337.1353 + int mtu = 1500;
337.1354 + Socket s = openDataConnection("APPE " + name);
337.1355 + OutputStream remote = createOutputStream(s.getOutputStream());
337.1356 + byte[] buf = new byte[mtu * 10];
337.1357 + int l;
337.1358 + while ((l = local.read(buf)) >= 0) {
337.1359 + if (l > 0) {
337.1360 + remote.write(buf, 0, l);
337.1361 + }
337.1362 + }
337.1363 + remote.close();
337.1364 + return completePending();
337.1365 + }
337.1366 +
337.1367 + /**
337.1368 + * Renames a file on the server.
337.1369 + *
337.1370 + * @param from the name of the file being renamed
337.1371 + * @param to the new name for the file
337.1372 + * @throws IOException if the command fails
337.1373 + */
337.1374 + public sun.net.ftp.FtpClient rename(String from, String to) throws sun.net.ftp.FtpProtocolException, IOException {
337.1375 + issueCommandCheck("RNFR " + from);
337.1376 + issueCommandCheck("RNTO " + to);
337.1377 + return this;
337.1378 + }
337.1379 +
337.1380 + /**
337.1381 + * Deletes a file on the server.
337.1382 + *
337.1383 + * @param name a <code>String</code> containing the name of the file
337.1384 + * to delete.
337.1385 + * @return <code>true</code> if the command was successful
337.1386 + * @throws IOException if an error occured during the exchange
337.1387 + */
337.1388 + public sun.net.ftp.FtpClient deleteFile(String name) throws sun.net.ftp.FtpProtocolException, IOException {
337.1389 + issueCommandCheck("DELE " + name);
337.1390 + return this;
337.1391 + }
337.1392 +
337.1393 + /**
337.1394 + * Creates a new directory on the server.
337.1395 + *
337.1396 + * @param name a <code>String</code> containing the name of the directory
337.1397 + * to create.
337.1398 + * @return <code>true</code> if the operation was successful.
337.1399 + * @throws IOException if an error occured during the exchange
337.1400 + */
337.1401 + public sun.net.ftp.FtpClient makeDirectory(String name) throws sun.net.ftp.FtpProtocolException, IOException {
337.1402 + issueCommandCheck("MKD " + name);
337.1403 + return this;
337.1404 + }
337.1405 +
337.1406 + /**
337.1407 + * Removes a directory on the server.
337.1408 + *
337.1409 + * @param name a <code>String</code> containing the name of the directory
337.1410 + * to remove.
337.1411 + *
337.1412 + * @return <code>true</code> if the operation was successful.
337.1413 + * @throws IOException if an error occured during the exchange.
337.1414 + */
337.1415 + public sun.net.ftp.FtpClient removeDirectory(String name) throws sun.net.ftp.FtpProtocolException, IOException {
337.1416 + issueCommandCheck("RMD " + name);
337.1417 + return this;
337.1418 + }
337.1419 +
337.1420 + /**
337.1421 + * Sends a No-operation command. It's useful for testing the connection
337.1422 + * status or as a <I>keep alive</I> mechanism.
337.1423 + *
337.1424 + * @throws FtpProtocolException if the command fails
337.1425 + */
337.1426 + public sun.net.ftp.FtpClient noop() throws sun.net.ftp.FtpProtocolException, IOException {
337.1427 + issueCommandCheck("NOOP");
337.1428 + return this;
337.1429 + }
337.1430 +
337.1431 + /**
337.1432 + * Sends the STAT command to the server.
337.1433 + * This can be used while a data connection is open to get a status
337.1434 + * on the current transfer, in that case the parameter should be
337.1435 + * <code>null</code>.
337.1436 + * If used between file transfers, it may have a pathname as argument
337.1437 + * in which case it will work as the LIST command except no data
337.1438 + * connection will be created.
337.1439 + *
337.1440 + * @param name an optional <code>String</code> containing the pathname
337.1441 + * the STAT command should apply to.
337.1442 + * @return the response from the server or <code>null</code> if the
337.1443 + * command failed.
337.1444 + * @throws IOException if an error occured during the transmission.
337.1445 + */
337.1446 + public String getStatus(String name) throws sun.net.ftp.FtpProtocolException, IOException {
337.1447 + issueCommandCheck((name == null ? "STAT" : "STAT " + name));
337.1448 + /*
337.1449 + * A typical response will be:
337.1450 + * 213-status of t32.gif:
337.1451 + * -rw-r--r-- 1 jcc staff 247445 Feb 17 1998 t32.gif
337.1452 + * 213 End of Status
337.1453 + *
337.1454 + * or
337.1455 + *
337.1456 + * 211-jsn FTP server status:
337.1457 + * Version wu-2.6.2+Sun
337.1458 + * Connected to localhost (::1)
337.1459 + * Logged in as jccollet
337.1460 + * TYPE: ASCII, FORM: Nonprint; STRUcture: File; transfer MODE: Stream
337.1461 + * No data connection
337.1462 + * 0 data bytes received in 0 files
337.1463 + * 0 data bytes transmitted in 0 files
337.1464 + * 0 data bytes total in 0 files
337.1465 + * 53 traffic bytes received in 0 transfers
337.1466 + * 485 traffic bytes transmitted in 0 transfers
337.1467 + * 587 traffic bytes total in 0 transfers
337.1468 + * 211 End of status
337.1469 + *
337.1470 + * So we need to remove the 1st and last line
337.1471 + */
337.1472 + Vector<String> resp = getResponseStrings();
337.1473 + StringBuffer sb = new StringBuffer();
337.1474 + for (int i = 1; i < resp.size() - 1; i++) {
337.1475 + sb.append(resp.get(i));
337.1476 + }
337.1477 + return sb.toString();
337.1478 + }
337.1479 +
337.1480 + /**
337.1481 + * Sends the FEAT command to the server and returns the list of supported
337.1482 + * features in the form of strings.
337.1483 + *
337.1484 + * The features are the supported commands, like AUTH TLS, PROT or PASV.
337.1485 + * See the RFCs for a complete list.
337.1486 + *
337.1487 + * Note that not all FTP servers support that command, in which case
337.1488 + * the method will return <code>null</code>
337.1489 + *
337.1490 + * @return a <code>List</code> of <code>Strings</code> describing the
337.1491 + * supported additional features, or <code>null</code>
337.1492 + * if the command is not supported.
337.1493 + * @throws IOException if an error occurs during the transmission.
337.1494 + */
337.1495 + public List<String> getFeatures() throws sun.net.ftp.FtpProtocolException, IOException {
337.1496 + /*
337.1497 + * The FEAT command, when implemented will return something like:
337.1498 + *
337.1499 + * 211-Features:
337.1500 + * AUTH TLS
337.1501 + * PBSZ
337.1502 + * PROT
337.1503 + * EPSV
337.1504 + * EPRT
337.1505 + * PASV
337.1506 + * REST STREAM
337.1507 + * 211 END
337.1508 + */
337.1509 + ArrayList<String> features = new ArrayList<String>();
337.1510 + issueCommandCheck("FEAT");
337.1511 + Vector<String> resp = getResponseStrings();
337.1512 + // Note that we start at index 1 to skip the 1st line (211-...)
337.1513 + // and we stop before the last line.
337.1514 + for (int i = 1; i < resp.size() - 1; i++) {
337.1515 + String s = resp.get(i);
337.1516 + // Get rid of leading space and trailing newline
337.1517 + features.add(s.substring(1, s.length() - 1));
337.1518 + }
337.1519 + return features;
337.1520 + }
337.1521 +
337.1522 + /**
337.1523 + * sends the ABOR command to the server.
337.1524 + * It tells the server to stop the previous command or transfer.
337.1525 + *
337.1526 + * @return <code>true</code> if the command was successful.
337.1527 + * @throws IOException if an error occured during the transmission.
337.1528 + */
337.1529 + public sun.net.ftp.FtpClient abort() throws sun.net.ftp.FtpProtocolException, IOException {
337.1530 + issueCommandCheck("ABOR");
337.1531 + // TODO: Must check the ReplyCode:
337.1532 + /*
337.1533 + * From the RFC:
337.1534 + * There are two cases for the server upon receipt of this
337.1535 + * command: (1) the FTP service command was already completed,
337.1536 + * or (2) the FTP service command is still in progress.
337.1537 + * In the first case, the server closes the data connection
337.1538 + * (if it is open) and responds with a 226 reply, indicating
337.1539 + * that the abort command was successfully processed.
337.1540 + * In the second case, the server aborts the FTP service in
337.1541 + * progress and closes the data connection, returning a 426
337.1542 + * reply to indicate that the service request terminated
337.1543 + * abnormally. The server then sends a 226 reply,
337.1544 + * indicating that the abort command was successfully
337.1545 + * processed.
337.1546 + */
337.1547 +
337.1548 +
337.1549 + return this;
337.1550 + }
337.1551 +
337.1552 + /**
337.1553 + * Some methods do not wait until completion before returning, so this
337.1554 + * method can be called to wait until completion. This is typically the case
337.1555 + * with commands that trigger a transfer like {@link #getFileStream(String)}.
337.1556 + * So this method should be called before accessing information related to
337.1557 + * such a command.
337.1558 + * <p>This method will actually block reading on the command channel for a
337.1559 + * notification from the server that the command is finished. Such a
337.1560 + * notification often carries extra information concerning the completion
337.1561 + * of the pending action (e.g. number of bytes transfered).</p>
337.1562 + * <p>Note that this will return true immediately if no command or action
337.1563 + * is pending</p>
337.1564 + * <p>It should be also noted that most methods issuing commands to the ftp
337.1565 + * server will call this method if a previous command is pending.
337.1566 + * <p>Example of use:
337.1567 + * <pre>
337.1568 + * InputStream in = cl.getFileStream("file");
337.1569 + * ...
337.1570 + * cl.completePending();
337.1571 + * long size = cl.getLastTransferSize();
337.1572 + * </pre>
337.1573 + * On the other hand, it's not necessary in a case like:
337.1574 + * <pre>
337.1575 + * InputStream in = cl.getFileStream("file");
337.1576 + * // read content
337.1577 + * ...
337.1578 + * cl.logout();
337.1579 + * </pre>
337.1580 + * <p>Since {@link #logout()} will call completePending() if necessary.</p>
337.1581 + * @return <code>true</code> if the completion was successful or if no
337.1582 + * action was pending.
337.1583 + * @throws IOException
337.1584 + */
337.1585 + public sun.net.ftp.FtpClient completePending() throws sun.net.ftp.FtpProtocolException, IOException {
337.1586 + while (replyPending) {
337.1587 + replyPending = false;
337.1588 + if (!readReply()) {
337.1589 + throw new sun.net.ftp.FtpProtocolException(getLastResponseString(), lastReplyCode);
337.1590 + }
337.1591 + }
337.1592 + return this;
337.1593 + }
337.1594 +
337.1595 + /**
337.1596 + * Reinitializes the USER parameters on the FTP server
337.1597 + *
337.1598 + * @throws FtpProtocolException if the command fails
337.1599 + */
337.1600 + public sun.net.ftp.FtpClient reInit() throws sun.net.ftp.FtpProtocolException, IOException {
337.1601 + issueCommandCheck("REIN");
337.1602 + loggedIn = false;
337.1603 + if (useCrypto) {
337.1604 + if (server instanceof SSLSocket) {
337.1605 + javax.net.ssl.SSLSession session = ((SSLSocket) server).getSession();
337.1606 + session.invalidate();
337.1607 + // Restore previous socket and streams
337.1608 + server = oldSocket;
337.1609 + oldSocket = null;
337.1610 + try {
337.1611 + out = new PrintStream(new BufferedOutputStream(server.getOutputStream()),
337.1612 + true, encoding);
337.1613 + } catch (UnsupportedEncodingException e) {
337.1614 + throw new InternalError(encoding + "encoding not found");
337.1615 + }
337.1616 + in = new BufferedInputStream(server.getInputStream());
337.1617 + }
337.1618 + }
337.1619 + useCrypto = false;
337.1620 + return this;
337.1621 + }
337.1622 +
337.1623 + /**
337.1624 + * Changes the transfer type (binary, ascii, ebcdic) and issue the
337.1625 + * proper command (e.g. TYPE A) to the server.
337.1626 + *
337.1627 + * @param type the <code>FtpTransferType</code> to use.
337.1628 + * @return This FtpClient
337.1629 + * @throws IOException if an error occurs during transmission.
337.1630 + */
337.1631 + public sun.net.ftp.FtpClient setType(TransferType type) throws sun.net.ftp.FtpProtocolException, IOException {
337.1632 + String cmd = "NOOP";
337.1633 +
337.1634 + this.type = type;
337.1635 + if (type == TransferType.ASCII) {
337.1636 + cmd = "TYPE A";
337.1637 + }
337.1638 + if (type == TransferType.BINARY) {
337.1639 + cmd = "TYPE I";
337.1640 + }
337.1641 + if (type == TransferType.EBCDIC) {
337.1642 + cmd = "TYPE E";
337.1643 + }
337.1644 + issueCommandCheck(cmd);
337.1645 + return this;
337.1646 + }
337.1647 +
337.1648 + /**
337.1649 + * Issues a LIST command to the server to get the current directory
337.1650 + * listing, and returns the InputStream from the data connection.
337.1651 + * {@link #completePending()} <b>has</b> to be called once the application
337.1652 + * is finished writing to the stream.
337.1653 + *
337.1654 + * @param path the pathname of the directory to list, or <code>null</code>
337.1655 + * for the current working directory.
337.1656 + * @return the <code>InputStream</code> from the resulting data connection
337.1657 + * @throws IOException if an error occurs during the transmission.
337.1658 + * @see #changeDirectory(String)
337.1659 + * @see #listFiles(String)
337.1660 + */
337.1661 + public InputStream list(String path) throws sun.net.ftp.FtpProtocolException, IOException {
337.1662 + Socket s;
337.1663 + s = openDataConnection(path == null ? "LIST" : "LIST " + path);
337.1664 + if (s != null) {
337.1665 + return createInputStream(s.getInputStream());
337.1666 + }
337.1667 + return null;
337.1668 + }
337.1669 +
337.1670 + /**
337.1671 + * Issues a NLST path command to server to get the specified directory
337.1672 + * content. It differs from {@link #list(String)} method by the fact that
337.1673 + * it will only list the file names which would make the parsing of the
337.1674 + * somewhat easier.
337.1675 + *
337.1676 + * {@link #completePending()} <b>has</b> to be called once the application
337.1677 + * is finished writing to the stream.
337.1678 + *
337.1679 + * @param path a <code>String</code> containing the pathname of the
337.1680 + * directory to list or <code>null</code> for the current working
337.1681 + * directory.
337.1682 + * @return the <code>InputStream</code> from the resulting data connection
337.1683 + * @throws IOException if an error occurs during the transmission.
337.1684 + */
337.1685 + public InputStream nameList(String path) throws sun.net.ftp.FtpProtocolException, IOException {
337.1686 + Socket s;
337.1687 + s = openDataConnection("NLST " + path);
337.1688 + if (s != null) {
337.1689 + return createInputStream(s.getInputStream());
337.1690 + }
337.1691 + return null;
337.1692 + }
337.1693 +
337.1694 + /**
337.1695 + * Issues the SIZE [path] command to the server to get the size of a
337.1696 + * specific file on the server.
337.1697 + * Note that this command may not be supported by the server. In which
337.1698 + * case -1 will be returned.
337.1699 + *
337.1700 + * @param path a <code>String</code> containing the pathname of the
337.1701 + * file.
337.1702 + * @return a <code>long</code> containing the size of the file or -1 if
337.1703 + * the server returned an error, which can be checked with
337.1704 + * {@link #getLastReplyCode()}.
337.1705 + * @throws IOException if an error occurs during the transmission.
337.1706 + */
337.1707 + public long getSize(String path) throws sun.net.ftp.FtpProtocolException, IOException {
337.1708 + if (path == null || path.length() == 0) {
337.1709 + throw new IllegalArgumentException("path can't be null or empty");
337.1710 + }
337.1711 + issueCommandCheck("SIZE " + path);
337.1712 + if (lastReplyCode == FtpReplyCode.FILE_STATUS) {
337.1713 + String s = getResponseString();
337.1714 + s = s.substring(4, s.length() - 1);
337.1715 + return Long.parseLong(s);
337.1716 + }
337.1717 + return -1;
337.1718 + }
337.1719 + private static String[] MDTMformats = {
337.1720 + "yyyyMMddHHmmss.SSS",
337.1721 + "yyyyMMddHHmmss"
337.1722 + };
337.1723 + private static SimpleDateFormat[] dateFormats = new SimpleDateFormat[MDTMformats.length];
337.1724 +
337.1725 + static {
337.1726 + for (int i = 0; i < MDTMformats.length; i++) {
337.1727 + dateFormats[i] = new SimpleDateFormat(MDTMformats[i]);
337.1728 + dateFormats[i].setTimeZone(TimeZone.getTimeZone("GMT"));
337.1729 + }
337.1730 + }
337.1731 +
337.1732 + /**
337.1733 + * Issues the MDTM [path] command to the server to get the modification
337.1734 + * time of a specific file on the server.
337.1735 + * Note that this command may not be supported by the server, in which
337.1736 + * case <code>null</code> will be returned.
337.1737 + *
337.1738 + * @param path a <code>String</code> containing the pathname of the file.
337.1739 + * @return a <code>Date</code> representing the last modification time
337.1740 + * or <code>null</code> if the server returned an error, which
337.1741 + * can be checked with {@link #getLastReplyCode()}.
337.1742 + * @throws IOException if an error occurs during the transmission.
337.1743 + */
337.1744 + public Date getLastModified(String path) throws sun.net.ftp.FtpProtocolException, IOException {
337.1745 + issueCommandCheck("MDTM " + path);
337.1746 + if (lastReplyCode == FtpReplyCode.FILE_STATUS) {
337.1747 + String s = getResponseString().substring(4);
337.1748 + Date d = null;
337.1749 + for (SimpleDateFormat dateFormat : dateFormats) {
337.1750 + try {
337.1751 + d = dateFormat.parse(s);
337.1752 + } catch (ParseException ex) {
337.1753 + }
337.1754 + if (d != null) {
337.1755 + return d;
337.1756 + }
337.1757 + }
337.1758 + }
337.1759 + return null;
337.1760 + }
337.1761 +
337.1762 + /**
337.1763 + * Sets the parser used to handle the directory output to the specified
337.1764 + * one. By default the parser is set to one that can handle most FTP
337.1765 + * servers output (Unix base mostly). However it may be necessary for
337.1766 + * and application to provide its own parser due to some uncommon
337.1767 + * output format.
337.1768 + *
337.1769 + * @param p The <code>FtpDirParser</code> to use.
337.1770 + * @see #listFiles(String)
337.1771 + */
337.1772 + public sun.net.ftp.FtpClient setDirParser(FtpDirParser p) {
337.1773 + parser = p;
337.1774 + return this;
337.1775 + }
337.1776 +
337.1777 + private class FtpFileIterator implements Iterator<FtpDirEntry>, Closeable {
337.1778 +
337.1779 + private BufferedReader in = null;
337.1780 + private FtpDirEntry nextFile = null;
337.1781 + private FtpDirParser fparser = null;
337.1782 + private boolean eof = false;
337.1783 +
337.1784 + public FtpFileIterator(FtpDirParser p, BufferedReader in) {
337.1785 + this.in = in;
337.1786 + this.fparser = p;
337.1787 + readNext();
337.1788 + }
337.1789 +
337.1790 + private void readNext() {
337.1791 + nextFile = null;
337.1792 + if (eof) {
337.1793 + return;
337.1794 + }
337.1795 + String line = null;
337.1796 + try {
337.1797 + do {
337.1798 + line = in.readLine();
337.1799 + if (line != null) {
337.1800 + nextFile = fparser.parseLine(line);
337.1801 + if (nextFile != null) {
337.1802 + return;
337.1803 + }
337.1804 + }
337.1805 + } while (line != null);
337.1806 + in.close();
337.1807 + } catch (IOException iOException) {
337.1808 + }
337.1809 + eof = true;
337.1810 + }
337.1811 +
337.1812 + public boolean hasNext() {
337.1813 + return nextFile != null;
337.1814 + }
337.1815 +
337.1816 + public FtpDirEntry next() {
337.1817 + FtpDirEntry ret = nextFile;
337.1818 + readNext();
337.1819 + return ret;
337.1820 + }
337.1821 +
337.1822 + public void remove() {
337.1823 + throw new UnsupportedOperationException("Not supported yet.");
337.1824 + }
337.1825 +
337.1826 + public void close() throws IOException {
337.1827 + if (in != null && !eof) {
337.1828 + in.close();
337.1829 + }
337.1830 + eof = true;
337.1831 + nextFile = null;
337.1832 + }
337.1833 + }
337.1834 +
337.1835 + /**
337.1836 + * Issues a MLSD command to the server to get the specified directory
337.1837 + * listing and applies the current parser to create an Iterator of
337.1838 + * {@link java.net.ftp.FtpDirEntry}. Note that the Iterator returned is also a
337.1839 + * {@link java.io.Closeable}.
337.1840 + * If the server doesn't support the MLSD command, the LIST command is used
337.1841 + * instead.
337.1842 + *
337.1843 + * {@link #completePending()} <b>has</b> to be called once the application
337.1844 + * is finished iterating through the files.
337.1845 + *
337.1846 + * @param path the pathname of the directory to list or <code>null</code>
337.1847 + * for the current working directoty.
337.1848 + * @return a <code>Iterator</code> of files or <code>null</code> if the
337.1849 + * command failed.
337.1850 + * @throws IOException if an error occured during the transmission
337.1851 + * @see #setDirParser(FtpDirParser)
337.1852 + * @see #changeDirectory(String)
337.1853 + */
337.1854 + public Iterator<FtpDirEntry> listFiles(String path) throws sun.net.ftp.FtpProtocolException, IOException {
337.1855 + Socket s = null;
337.1856 + BufferedReader sin = null;
337.1857 + try {
337.1858 + s = openDataConnection(path == null ? "MLSD" : "MLSD " + path);
337.1859 + } catch (sun.net.ftp.FtpProtocolException FtpException) {
337.1860 + // The server doesn't understand new MLSD command, ignore and fall
337.1861 + // back to LIST
337.1862 + }
337.1863 +
337.1864 + if (s != null) {
337.1865 + sin = new BufferedReader(new InputStreamReader(s.getInputStream()));
337.1866 + return new FtpFileIterator(mlsxParser, sin);
337.1867 + } else {
337.1868 + s = openDataConnection(path == null ? "LIST" : "LIST " + path);
337.1869 + if (s != null) {
337.1870 + sin = new BufferedReader(new InputStreamReader(s.getInputStream()));
337.1871 + return new FtpFileIterator(parser, sin);
337.1872 + }
337.1873 + }
337.1874 + return null;
337.1875 + }
337.1876 +
337.1877 + private boolean sendSecurityData(byte[] buf) throws IOException {
337.1878 + BASE64Encoder encoder = new BASE64Encoder();
337.1879 + String s = encoder.encode(buf);
337.1880 + return issueCommand("ADAT " + s);
337.1881 + }
337.1882 +
337.1883 + private byte[] getSecurityData() {
337.1884 + String s = getLastResponseString();
337.1885 + if (s.substring(4, 9).equalsIgnoreCase("ADAT=")) {
337.1886 + BASE64Decoder decoder = new BASE64Decoder();
337.1887 + try {
337.1888 + // Need to get rid of the leading '315 ADAT='
337.1889 + // and the trailing newline
337.1890 + return decoder.decodeBuffer(s.substring(9, s.length() - 1));
337.1891 + } catch (IOException e) {
337.1892 + //
337.1893 + }
337.1894 + }
337.1895 + return null;
337.1896 + }
337.1897 +
337.1898 + /**
337.1899 + * Attempts to use Kerberos GSSAPI as an authentication mechanism with the
337.1900 + * ftp server. This will issue an <code>AUTH GSSAPI</code> command, and if
337.1901 + * it is accepted by the server, will followup with <code>ADAT</code>
337.1902 + * command to exchange the various tokens until authentification is
337.1903 + * successful. This conforms to Appendix I of RFC 2228.
337.1904 + *
337.1905 + * @return <code>true</code> if authentication was successful.
337.1906 + * @throws IOException if an error occurs during the transmission.
337.1907 + */
337.1908 + public sun.net.ftp.FtpClient useKerberos() throws sun.net.ftp.FtpProtocolException, IOException {
337.1909 + /*
337.1910 + * Comment out for the moment since it's not in use and would create
337.1911 + * needless cross-package links.
337.1912 + *
337.1913 + issueCommandCheck("AUTH GSSAPI");
337.1914 + if (lastReplyCode != FtpReplyCode.NEED_ADAT)
337.1915 + throw new sun.net.ftp.FtpProtocolException("Unexpected reply from server");
337.1916 + try {
337.1917 + GSSManager manager = GSSManager.getInstance();
337.1918 + GSSName name = manager.createName("SERVICE:ftp@"+
337.1919 + serverAddr.getHostName(), null);
337.1920 + GSSContext context = manager.createContext(name, null, null,
337.1921 + GSSContext.DEFAULT_LIFETIME);
337.1922 + context.requestMutualAuth(true);
337.1923 + context.requestReplayDet(true);
337.1924 + context.requestSequenceDet(true);
337.1925 + context.requestCredDeleg(true);
337.1926 + byte []inToken = new byte[0];
337.1927 + while (!context.isEstablished()) {
337.1928 + byte[] outToken
337.1929 + = context.initSecContext(inToken, 0, inToken.length);
337.1930 + // send the output token if generated
337.1931 + if (outToken != null) {
337.1932 + if (sendSecurityData(outToken)) {
337.1933 + inToken = getSecurityData();
337.1934 + }
337.1935 + }
337.1936 + }
337.1937 + loggedIn = true;
337.1938 + } catch (GSSException e) {
337.1939 +
337.1940 + }
337.1941 + */
337.1942 + return this;
337.1943 + }
337.1944 +
337.1945 + /**
337.1946 + * Returns the Welcome string the server sent during initial connection.
337.1947 + *
337.1948 + * @return a <code>String</code> containing the message the server
337.1949 + * returned during connection or <code>null</code>.
337.1950 + */
337.1951 + public String getWelcomeMsg() {
337.1952 + return welcomeMsg;
337.1953 + }
337.1954 +
337.1955 + /**
337.1956 + * Returns the last reply code sent by the server.
337.1957 + *
337.1958 + * @return the lastReplyCode
337.1959 + */
337.1960 + public FtpReplyCode getLastReplyCode() {
337.1961 + return lastReplyCode;
337.1962 + }
337.1963 +
337.1964 + /**
337.1965 + * Returns the last response string sent by the server.
337.1966 + *
337.1967 + * @return the message string, which can be quite long, last returned
337.1968 + * by the server.
337.1969 + */
337.1970 + public String getLastResponseString() {
337.1971 + StringBuffer sb = new StringBuffer();
337.1972 + if (serverResponse != null) {
337.1973 + for (String l : serverResponse) {
337.1974 + if (l != null) {
337.1975 + sb.append(l);
337.1976 + }
337.1977 + }
337.1978 + }
337.1979 + return sb.toString();
337.1980 + }
337.1981 +
337.1982 + /**
337.1983 + * Returns, when available, the size of the latest started transfer.
337.1984 + * This is retreived by parsing the response string received as an initial
337.1985 + * response to a RETR or similar request.
337.1986 + *
337.1987 + * @return the size of the latest transfer or -1 if either there was no
337.1988 + * transfer or the information was unavailable.
337.1989 + */
337.1990 + public long getLastTransferSize() {
337.1991 + return lastTransSize;
337.1992 + }
337.1993 +
337.1994 + /**
337.1995 + * Returns, when available, the remote name of the last transfered file.
337.1996 + * This is mainly useful for "put" operation when the unique flag was
337.1997 + * set since it allows to recover the unique file name created on the
337.1998 + * server which may be different from the one submitted with the command.
337.1999 + *
337.2000 + * @return the name the latest transfered file remote name, or
337.2001 + * <code>null</code> if that information is unavailable.
337.2002 + */
337.2003 + public String getLastFileName() {
337.2004 + return lastFileName;
337.2005 + }
337.2006 +
337.2007 + /**
337.2008 + * Attempts to switch to a secure, encrypted connection. This is done by
337.2009 + * sending the "AUTH TLS" command.
337.2010 + * <p>See <a href="http://www.ietf.org/rfc/rfc4217.txt">RFC 4217</a></p>
337.2011 + * If successful this will establish a secure command channel with the
337.2012 + * server, it will also make it so that all other transfers (e.g. a RETR
337.2013 + * command) will be done over an encrypted channel as well unless a
337.2014 + * {@link #reInit()} command or a {@link #endSecureSession()} command is issued.
337.2015 + *
337.2016 + * @return <code>true</code> if the operation was successful.
337.2017 + * @throws IOException if an error occured during the transmission.
337.2018 + * @see #endSecureSession()
337.2019 + */
337.2020 + public sun.net.ftp.FtpClient startSecureSession() throws sun.net.ftp.FtpProtocolException, IOException {
337.2021 + if (!isConnected()) {
337.2022 + throw new sun.net.ftp.FtpProtocolException("Not connected yet", FtpReplyCode.BAD_SEQUENCE);
337.2023 + }
337.2024 + if (sslFact == null) {
337.2025 + try {
337.2026 + sslFact = (SSLSocketFactory) SSLSocketFactory.getDefault();
337.2027 + } catch (Exception e) {
337.2028 + throw new IOException(e.getLocalizedMessage());
337.2029 + }
337.2030 + }
337.2031 + issueCommandCheck("AUTH TLS");
337.2032 + Socket s = null;
337.2033 + try {
337.2034 + s = sslFact.createSocket(server, serverAddr.getHostName(), serverAddr.getPort(), true);
337.2035 + } catch (javax.net.ssl.SSLException ssle) {
337.2036 + try {
337.2037 + disconnect();
337.2038 + } catch (Exception e) {
337.2039 + }
337.2040 + throw ssle;
337.2041 + }
337.2042 + // Remember underlying socket so we can restore it later
337.2043 + oldSocket = server;
337.2044 + server = s;
337.2045 + try {
337.2046 + out = new PrintStream(new BufferedOutputStream(server.getOutputStream()),
337.2047 + true, encoding);
337.2048 + } catch (UnsupportedEncodingException e) {
337.2049 + throw new InternalError(encoding + "encoding not found");
337.2050 + }
337.2051 + in = new BufferedInputStream(server.getInputStream());
337.2052 +
337.2053 + issueCommandCheck("PBSZ 0");
337.2054 + issueCommandCheck("PROT P");
337.2055 + useCrypto = true;
337.2056 + return this;
337.2057 + }
337.2058 +
337.2059 + /**
337.2060 + * Sends a <code>CCC</code> command followed by a <code>PROT C</code>
337.2061 + * command to the server terminating an encrypted session and reverting
337.2062 + * back to a non crypted transmission.
337.2063 + *
337.2064 + * @return <code>true</code> if the operation was successful.
337.2065 + * @throws IOException if an error occured during transmission.
337.2066 + * @see #startSecureSession()
337.2067 + */
337.2068 + public sun.net.ftp.FtpClient endSecureSession() throws sun.net.ftp.FtpProtocolException, IOException {
337.2069 + if (!useCrypto) {
337.2070 + return this;
337.2071 + }
337.2072 +
337.2073 + issueCommandCheck("CCC");
337.2074 + issueCommandCheck("PROT C");
337.2075 + useCrypto = false;
337.2076 + // Restore previous socket and streams
337.2077 + server = oldSocket;
337.2078 + oldSocket = null;
337.2079 + try {
337.2080 + out = new PrintStream(new BufferedOutputStream(server.getOutputStream()),
337.2081 + true, encoding);
337.2082 + } catch (UnsupportedEncodingException e) {
337.2083 + throw new InternalError(encoding + "encoding not found");
337.2084 + }
337.2085 + in = new BufferedInputStream(server.getInputStream());
337.2086 +
337.2087 + return this;
337.2088 + }
337.2089 +
337.2090 + /**
337.2091 + * Sends the "Allocate" (ALLO) command to the server telling it to
337.2092 + * pre-allocate the specified number of bytes for the next transfer.
337.2093 + *
337.2094 + * @param size The number of bytes to allocate.
337.2095 + * @return <code>true</code> if the operation was successful.
337.2096 + * @throws IOException if an error occured during the transmission.
337.2097 + */
337.2098 + public sun.net.ftp.FtpClient allocate(long size) throws sun.net.ftp.FtpProtocolException, IOException {
337.2099 + issueCommandCheck("ALLO " + size);
337.2100 + return this;
337.2101 + }
337.2102 +
337.2103 + /**
337.2104 + * Sends the "Structure Mount" (SMNT) command to the server. This let the
337.2105 + * user mount a different file system data structure without altering his
337.2106 + * login or accounting information.
337.2107 + *
337.2108 + * @param struct a <code>String</code> containing the name of the
337.2109 + * structure to mount.
337.2110 + * @return <code>true</code> if the operation was successful.
337.2111 + * @throws IOException if an error occured during the transmission.
337.2112 + */
337.2113 + public sun.net.ftp.FtpClient structureMount(String struct) throws sun.net.ftp.FtpProtocolException, IOException {
337.2114 + issueCommandCheck("SMNT " + struct);
337.2115 + return this;
337.2116 + }
337.2117 +
337.2118 + /**
337.2119 + * Sends a SYST (System) command to the server and returns the String
337.2120 + * sent back by the server describing the operating system at the
337.2121 + * server.
337.2122 + *
337.2123 + * @return a <code>String</code> describing the OS, or <code>null</code>
337.2124 + * if the operation was not successful.
337.2125 + * @throws IOException if an error occured during the transmission.
337.2126 + */
337.2127 + public String getSystem() throws sun.net.ftp.FtpProtocolException, IOException {
337.2128 + issueCommandCheck("SYST");
337.2129 + /*
337.2130 + * 215 UNIX Type: L8 Version: SUNOS
337.2131 + */
337.2132 + String resp = getResponseString();
337.2133 + // Get rid of the leading code and blank
337.2134 + return resp.substring(4);
337.2135 + }
337.2136 +
337.2137 + /**
337.2138 + * Sends the HELP command to the server, with an optional command, like
337.2139 + * SITE, and returns the text sent back by the server.
337.2140 + *
337.2141 + * @param cmd the command for which the help is requested or
337.2142 + * <code>null</code> for the general help
337.2143 + * @return a <code>String</code> containing the text sent back by the
337.2144 + * server, or <code>null</code> if the command failed.
337.2145 + * @throws IOException if an error occured during transmission
337.2146 + */
337.2147 + public String getHelp(String cmd) throws sun.net.ftp.FtpProtocolException, IOException {
337.2148 + issueCommandCheck("HELP " + cmd);
337.2149 + /**
337.2150 + *
337.2151 + * HELP
337.2152 + * 214-The following commands are implemented.
337.2153 + * USER EPRT STRU ALLO DELE SYST RMD MDTM ADAT
337.2154 + * PASS EPSV MODE REST CWD STAT PWD PROT
337.2155 + * QUIT LPRT RETR RNFR LIST HELP CDUP PBSZ
337.2156 + * PORT LPSV STOR RNTO NLST NOOP STOU AUTH
337.2157 + * PASV TYPE APPE ABOR SITE MKD SIZE CCC
337.2158 + * 214 Direct comments to ftp-bugs@jsn.
337.2159 + *
337.2160 + * HELP SITE
337.2161 + * 214-The following SITE commands are implemented.
337.2162 + * UMASK HELP GROUPS
337.2163 + * IDLE ALIAS CHECKMETHOD
337.2164 + * CHMOD CDPATH CHECKSUM
337.2165 + * 214 Direct comments to ftp-bugs@jsn.
337.2166 + */
337.2167 + Vector<String> resp = getResponseStrings();
337.2168 + if (resp.size() == 1) {
337.2169 + // Single line response
337.2170 + return resp.get(0).substring(4);
337.2171 + }
337.2172 + // on multiple lines answers, like the ones above, remove 1st and last
337.2173 + // line, concat the the others.
337.2174 + StringBuffer sb = new StringBuffer();
337.2175 + for (int i = 1; i < resp.size() - 1; i++) {
337.2176 + sb.append(resp.get(i).substring(3));
337.2177 + }
337.2178 + return sb.toString();
337.2179 + }
337.2180 +
337.2181 + /**
337.2182 + * Sends the SITE command to the server. This is used by the server
337.2183 + * to provide services specific to his system that are essential
337.2184 + * to file transfer.
337.2185 + *
337.2186 + * @param cmd the command to be sent.
337.2187 + * @return <code>true</code> if the command was successful.
337.2188 + * @throws IOException if an error occured during transmission
337.2189 + */
337.2190 + public sun.net.ftp.FtpClient siteCmd(String cmd) throws sun.net.ftp.FtpProtocolException, IOException {
337.2191 + issueCommandCheck("SITE " + cmd);
337.2192 + return this;
337.2193 + }
337.2194 +}
338.1 --- a/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java Mon Nov 23 10:04:47 2009 +0000
338.2 +++ b/src/share/classes/sun/net/www/protocol/ftp/FtpURLConnection.java Wed Nov 25 11:08:25 2009 -0800
338.3 @@ -1,5 +1,5 @@
338.4 /*
338.5 - * Copyright 1994-2008 Sun Microsystems, Inc. All Rights Reserved.
338.6 + * Copyright 1994-2009 Sun Microsystems, Inc. All Rights Reserved.
338.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
338.8 *
338.9 * This code is free software; you can redistribute it and/or modify it
338.10 @@ -37,10 +37,8 @@
338.11 import java.io.FilterOutputStream;
338.12 import java.io.FileNotFoundException;
338.13 import java.net.URL;
338.14 -import java.net.URLStreamHandler;
338.15 import java.net.SocketPermission;
338.16 import java.net.UnknownHostException;
338.17 -import java.net.MalformedURLException;
338.18 import java.net.InetSocketAddress;
338.19 import java.net.URI;
338.20 import java.net.Proxy;
338.21 @@ -84,7 +82,6 @@
338.22 // In case we have to use proxies, we use HttpURLConnection
338.23 HttpURLConnection http = null;
338.24 private Proxy instProxy;
338.25 - Proxy proxy = null;
338.26
338.27 InputStream is = null;
338.28 OutputStream os = null;
338.29 @@ -125,12 +122,11 @@
338.30 ftp = cl;
338.31 }
338.32
338.33 + @Override
338.34 public void close() throws IOException {
338.35 super.close();
338.36 - try {
338.37 - if (ftp != null)
338.38 - ftp.closeServer();
338.39 - } catch (IOException ex) {
338.40 + if (ftp != null) {
338.41 + ftp.close();
338.42 }
338.43 }
338.44 }
338.45 @@ -149,12 +145,11 @@
338.46 ftp = cl;
338.47 }
338.48
338.49 + @Override
338.50 public void close() throws IOException {
338.51 super.close();
338.52 - try {
338.53 - if (ftp != null)
338.54 - ftp.closeServer();
338.55 - } catch (IOException ex) {
338.56 + if (ftp != null) {
338.57 + ftp.close();
338.58 }
338.59 }
338.60 }
338.61 @@ -192,10 +187,12 @@
338.62
338.63 private void setTimeouts() {
338.64 if (ftp != null) {
338.65 - if (connectTimeout >= 0)
338.66 + if (connectTimeout >= 0) {
338.67 ftp.setConnectTimeout(connectTimeout);
338.68 - if (readTimeout >= 0)
338.69 + }
338.70 + if (readTimeout >= 0) {
338.71 ftp.setReadTimeout(readTimeout);
338.72 + }
338.73 }
338.74 }
338.75
338.76 @@ -218,21 +215,22 @@
338.77 * Do we have to use a proxy?
338.78 */
338.79 ProxySelector sel = java.security.AccessController.doPrivileged(
338.80 - new java.security.PrivilegedAction<ProxySelector>() {
338.81 - public ProxySelector run() {
338.82 - return ProxySelector.getDefault();
338.83 - }
338.84 - });
338.85 + new java.security.PrivilegedAction<ProxySelector>() {
338.86 + public ProxySelector run() {
338.87 + return ProxySelector.getDefault();
338.88 + }
338.89 + });
338.90 if (sel != null) {
338.91 URI uri = sun.net.www.ParseUtil.toURI(url);
338.92 Iterator<Proxy> it = sel.select(uri).iterator();
338.93 while (it.hasNext()) {
338.94 p = it.next();
338.95 if (p == null || p == Proxy.NO_PROXY ||
338.96 - p.type() == Proxy.Type.SOCKS)
338.97 + p.type() == Proxy.Type.SOCKS) {
338.98 break;
338.99 + }
338.100 if (p.type() != Proxy.Type.HTTP ||
338.101 - !(p.address() instanceof InetSocketAddress)) {
338.102 + !(p.address() instanceof InetSocketAddress)) {
338.103 sel.connectFailed(uri, p.address(), new IOException("Wrong proxy type"));
338.104 continue;
338.105 }
338.106 @@ -240,10 +238,14 @@
338.107 InetSocketAddress paddr = (InetSocketAddress) p.address();
338.108 try {
338.109 http = new HttpURLConnection(url, p);
338.110 - if (connectTimeout >= 0)
338.111 + http.setDoInput(getDoInput());
338.112 + http.setDoOutput(getDoOutput());
338.113 + if (connectTimeout >= 0) {
338.114 http.setConnectTimeout(connectTimeout);
338.115 - if (readTimeout >= 0)
338.116 + }
338.117 + if (readTimeout >= 0) {
338.118 http.setReadTimeout(readTimeout);
338.119 + }
338.120 http.connect();
338.121 connected = true;
338.122 return;
338.123 @@ -257,10 +259,14 @@
338.124 p = instProxy;
338.125 if (p.type() == Proxy.Type.HTTP) {
338.126 http = new HttpURLConnection(url, instProxy);
338.127 - if (connectTimeout >= 0)
338.128 + http.setDoInput(getDoInput());
338.129 + http.setDoOutput(getDoOutput());
338.130 + if (connectTimeout >= 0) {
338.131 http.setConnectTimeout(connectTimeout);
338.132 - if (readTimeout >= 0)
338.133 + }
338.134 + if (readTimeout >= 0) {
338.135 http.setReadTimeout(readTimeout);
338.136 + }
338.137 http.connect();
338.138 connected = true;
338.139 return;
338.140 @@ -270,31 +276,35 @@
338.141 if (user == null) {
338.142 user = "anonymous";
338.143 String vers = java.security.AccessController.doPrivileged(
338.144 - new GetPropertyAction("java.version"));
338.145 + new GetPropertyAction("java.version"));
338.146 password = java.security.AccessController.doPrivileged(
338.147 - new GetPropertyAction("ftp.protocol.user",
338.148 - "Java" + vers +"@"));
338.149 + new GetPropertyAction("ftp.protocol.user",
338.150 + "Java" + vers + "@"));
338.151 }
338.152 try {
338.153 - if (p != null)
338.154 - ftp = new FtpClient(p);
338.155 - else
338.156 - ftp = new FtpClient();
338.157 + ftp = FtpClient.create();
338.158 + if (p != null) {
338.159 + ftp.setProxy(p);
338.160 + }
338.161 setTimeouts();
338.162 - if (port != -1)
338.163 - ftp.openServer(host, port);
338.164 - else
338.165 - ftp.openServer(host);
338.166 + if (port != -1) {
338.167 + ftp.connect(new InetSocketAddress(host, port));
338.168 + } else {
338.169 + ftp.connect(new InetSocketAddress(host, FtpClient.defaultPort()));
338.170 + }
338.171 } catch (UnknownHostException e) {
338.172 // Maybe do something smart here, like use a proxy like iftp.
338.173 // Just keep throwing for now.
338.174 throw e;
338.175 + } catch (FtpProtocolException fe) {
338.176 + throw new IOException(fe);
338.177 }
338.178 try {
338.179 - ftp.login(user, password);
338.180 - } catch (sun.net.ftp.FtpLoginException e) {
338.181 - ftp.closeServer();
338.182 - throw e;
338.183 + ftp.login(user, password.toCharArray());
338.184 + } catch (sun.net.ftp.FtpProtocolException e) {
338.185 + ftp.close();
338.186 + // Backward compatibility
338.187 + throw new sun.net.ftp.FtpLoginException("Invalid username/password");
338.188 }
338.189 connected = true;
338.190 }
338.191 @@ -306,24 +316,29 @@
338.192 private void decodePath(String path) {
338.193 int i = path.indexOf(";type=");
338.194 if (i >= 0) {
338.195 - String s1 = path.substring(i+6, path.length());
338.196 - if ("i".equalsIgnoreCase(s1))
338.197 + String s1 = path.substring(i + 6, path.length());
338.198 + if ("i".equalsIgnoreCase(s1)) {
338.199 type = BIN;
338.200 - if ("a".equalsIgnoreCase(s1))
338.201 + }
338.202 + if ("a".equalsIgnoreCase(s1)) {
338.203 type = ASCII;
338.204 - if ("d".equalsIgnoreCase(s1))
338.205 + }
338.206 + if ("d".equalsIgnoreCase(s1)) {
338.207 type = DIR;
338.208 + }
338.209 path = path.substring(0, i);
338.210 }
338.211 if (path != null && path.length() > 1 &&
338.212 - path.charAt(0) == '/')
338.213 + path.charAt(0) == '/') {
338.214 path = path.substring(1);
338.215 - if (path == null || path.length() == 0)
338.216 + }
338.217 + if (path == null || path.length() == 0) {
338.218 path = "./";
338.219 + }
338.220 if (!path.endsWith("/")) {
338.221 i = path.lastIndexOf('/');
338.222 if (i > 0) {
338.223 - filename = path.substring(i+1, path.length());
338.224 + filename = path.substring(i + 1, path.length());
338.225 filename = ParseUtil.decode(filename);
338.226 pathname = path.substring(0, i);
338.227 } else {
338.228 @@ -334,10 +349,11 @@
338.229 pathname = path.substring(0, path.length() - 1);
338.230 filename = null;
338.231 }
338.232 - if (pathname != null)
338.233 + if (pathname != null) {
338.234 fullpath = pathname + "/" + (filename != null ? filename : "");
338.235 - else
338.236 + } else {
338.237 fullpath = filename;
338.238 + }
338.239 }
338.240
338.241 /*
338.242 @@ -346,18 +362,19 @@
338.243 * This is because, '/' is not necessarly the directory delimiter
338.244 * on every systems.
338.245 */
338.246 -
338.247 - private void cd(String path) throws IOException {
338.248 - if (path == null || "".equals(path))
338.249 + private void cd(String path) throws FtpProtocolException, IOException {
338.250 + if (path == null || path.isEmpty()) {
338.251 return;
338.252 + }
338.253 if (path.indexOf('/') == -1) {
338.254 - ftp.cd(ParseUtil.decode(path));
338.255 + ftp.changeDirectory(ParseUtil.decode(path));
338.256 return;
338.257 }
338.258
338.259 - StringTokenizer token = new StringTokenizer(path,"/");
338.260 - while (token.hasMoreTokens())
338.261 - ftp.cd(ParseUtil.decode(token.nextToken()));
338.262 + StringTokenizer token = new StringTokenizer(path, "/");
338.263 + while (token.hasMoreTokens()) {
338.264 + ftp.changeDirectory(ParseUtil.decode(token.nextToken()));
338.265 + }
338.266 }
338.267
338.268 /**
338.269 @@ -369,16 +386,19 @@
338.270 * @throws IOException if already opened for output
338.271 * @throws FtpProtocolException if errors occur during the transfert.
338.272 */
338.273 + @Override
338.274 public InputStream getInputStream() throws IOException {
338.275 if (!connected) {
338.276 connect();
338.277 }
338.278
338.279 - if (http != null)
338.280 + if (http != null) {
338.281 return http.getInputStream();
338.282 + }
338.283
338.284 - if (os != null)
338.285 + if (os != null) {
338.286 throw new IOException("Already opened for output");
338.287 + }
338.288
338.289 if (is != null) {
338.290 return is;
338.291 @@ -386,82 +406,85 @@
338.292
338.293 MessageHeader msgh = new MessageHeader();
338.294
338.295 + boolean isAdir = false;
338.296 try {
338.297 decodePath(url.getPath());
338.298 if (filename == null || type == DIR) {
338.299 - ftp.ascii();
338.300 + ftp.setAsciiType();
338.301 cd(pathname);
338.302 - if (filename == null)
338.303 - is = new FtpInputStream(ftp, ftp.list());
338.304 - else
338.305 + if (filename == null) {
338.306 + is = new FtpInputStream(ftp, ftp.list(null));
338.307 + } else {
338.308 is = new FtpInputStream(ftp, ftp.nameList(filename));
338.309 + }
338.310 } else {
338.311 - if (type == ASCII)
338.312 - ftp.ascii();
338.313 - else
338.314 - ftp.binary();
338.315 + if (type == ASCII) {
338.316 + ftp.setAsciiType();
338.317 + } else {
338.318 + ftp.setBinaryType();
338.319 + }
338.320 cd(pathname);
338.321 - is = new FtpInputStream(ftp, ftp.get(filename));
338.322 + is = new FtpInputStream(ftp, ftp.getFileStream(filename));
338.323 }
338.324
338.325 /* Try to get the size of the file in bytes. If that is
338.326 - successful, then create a MeteredStream. */
338.327 + successful, then create a MeteredStream. */
338.328 try {
338.329 - String response = ftp.getResponseString();
338.330 - int offset;
338.331 + long l = ftp.getLastTransferSize();
338.332 + msgh.add("content-length", Long.toString(l));
338.333 + if (l > 0) {
338.334
338.335 - if ((offset = response.indexOf(" bytes)")) != -1) {
338.336 - int i = offset;
338.337 - int c;
338.338 + // Wrap input stream with MeteredStream to ensure read() will always return -1
338.339 + // at expected length.
338.340
338.341 - while (--i >= 0 && ((c = response.charAt(i)) >= '0'
338.342 - && c <= '9'))
338.343 - ;
338.344 - long l = Long.parseLong(response.substring(i + 1, offset));
338.345 - msgh.add("content-length", Long.toString(l));
338.346 - if (l > 0) {
338.347 + // Check if URL should be metered
338.348 + boolean meteredInput = ProgressMonitor.getDefault().shouldMeterInput(url, "GET");
338.349 + ProgressSource pi = null;
338.350
338.351 - // Wrap input stream with MeteredStream to ensure read() will always return -1
338.352 - // at expected length.
338.353 + if (meteredInput) {
338.354 + pi = new ProgressSource(url, "GET", l);
338.355 + pi.beginTracking();
338.356 + }
338.357
338.358 - // Check if URL should be metered
338.359 - boolean meteredInput = ProgressMonitor.getDefault().shouldMeterInput(url, "GET");
338.360 - ProgressSource pi = null;
338.361 -
338.362 - if (meteredInput) {
338.363 - pi = new ProgressSource(url, "GET", l);
338.364 - pi.beginTracking();
338.365 - }
338.366 -
338.367 - is = new MeteredStream(is, pi, l);
338.368 - }
338.369 + is = new MeteredStream(is, pi, l);
338.370 }
338.371 } catch (Exception e) {
338.372 e.printStackTrace();
338.373 - /* do nothing, since all we were doing was trying to
338.374 - get the size in bytes of the file */
338.375 + /* do nothing, since all we were doing was trying to
338.376 + get the size in bytes of the file */
338.377 }
338.378
338.379 - String type = guessContentTypeFromName(fullpath);
338.380 - if (type == null && is.markSupported()) {
338.381 - type = guessContentTypeFromStream(is);
338.382 - }
338.383 - if (type != null) {
338.384 - msgh.add("content-type", type);
338.385 + if (isAdir) {
338.386 + msgh.add("content-type", "text/plain");
338.387 + msgh.add("access-type", "directory");
338.388 + } else {
338.389 + msgh.add("access-type", "file");
338.390 + String ftype = guessContentTypeFromName(fullpath);
338.391 + if (ftype == null && is.markSupported()) {
338.392 + ftype = guessContentTypeFromStream(is);
338.393 + }
338.394 + if (ftype != null) {
338.395 + msgh.add("content-type", ftype);
338.396 + }
338.397 }
338.398 } catch (FileNotFoundException e) {
338.399 try {
338.400 cd(fullpath);
338.401 /* if that worked, then make a directory listing
338.402 - and build an html stream with all the files in
338.403 - the directory */
338.404 - ftp.ascii();
338.405 + and build an html stream with all the files in
338.406 + the directory */
338.407 + ftp.setAsciiType();
338.408
338.409 - is = new FtpInputStream(ftp, ftp.list());
338.410 + is = new FtpInputStream(ftp, ftp.list(null));
338.411 msgh.add("content-type", "text/plain");
338.412 + msgh.add("access-type", "directory");
338.413 } catch (IOException ex) {
338.414 throw new FileNotFoundException(fullpath);
338.415 + } catch (FtpProtocolException ex2) {
338.416 + throw new FileNotFoundException(fullpath);
338.417 }
338.418 + } catch (FtpProtocolException ftpe) {
338.419 + throw new IOException(ftpe);
338.420 }
338.421 setProperties(msgh);
338.422 return is;
338.423 @@ -477,31 +500,45 @@
338.424 * points to a directory
338.425 * @throws FtpProtocolException if errors occur during the transfert.
338.426 */
338.427 + @Override
338.428 public OutputStream getOutputStream() throws IOException {
338.429 if (!connected) {
338.430 connect();
338.431 }
338.432
338.433 - if (http != null)
338.434 - return http.getOutputStream();
338.435 + if (http != null) {
338.436 + OutputStream out = http.getOutputStream();
338.437 + // getInputStream() is neccessary to force a writeRequests()
338.438 + // on the http client.
338.439 + http.getInputStream();
338.440 + return out;
338.441 + }
338.442
338.443 - if (is != null)
338.444 + if (is != null) {
338.445 throw new IOException("Already opened for input");
338.446 + }
338.447
338.448 if (os != null) {
338.449 return os;
338.450 }
338.451
338.452 decodePath(url.getPath());
338.453 - if (filename == null || filename.length() == 0)
338.454 + if (filename == null || filename.length() == 0) {
338.455 throw new IOException("illegal filename for a PUT");
338.456 - if (pathname != null)
338.457 - cd(pathname);
338.458 - if (type == ASCII)
338.459 - ftp.ascii();
338.460 - else
338.461 - ftp.binary();
338.462 - os = new FtpOutputStream(ftp, ftp.put(filename));
338.463 + }
338.464 + try {
338.465 + if (pathname != null) {
338.466 + cd(pathname);
338.467 + }
338.468 + if (type == ASCII) {
338.469 + ftp.setAsciiType();
338.470 + } else {
338.471 + ftp.setBinaryType();
338.472 + }
338.473 + os = new FtpOutputStream(ftp, ftp.putFileStream(filename, false));
338.474 + } catch (FtpProtocolException e) {
338.475 + throw new IOException(e);
338.476 + }
338.477 return os;
338.478 }
338.479
338.480 @@ -514,12 +551,13 @@
338.481 *
338.482 * @return The <code>Permission</code> object.
338.483 */
338.484 + @Override
338.485 public Permission getPermission() {
338.486 if (permission == null) {
338.487 - int port = url.getPort();
338.488 - port = port < 0 ? FtpClient.FTP_PORT : port;
338.489 - String host = this.host + ":" + port;
338.490 - permission = new SocketPermission(host, "connect");
338.491 + int urlport = url.getPort();
338.492 + urlport = urlport < 0 ? FtpClient.defaultPort() : urlport;
338.493 + String urlhost = this.host + ":" + urlport;
338.494 + permission = new SocketPermission(urlhost, "connect");
338.495 }
338.496 return permission;
338.497 }
338.498 @@ -534,21 +572,22 @@
338.499 * @throws IllegalStateException if already connected
338.500 * @see #getRequestProperty(java.lang.String)
338.501 */
338.502 + @Override
338.503 public void setRequestProperty(String key, String value) {
338.504 - super.setRequestProperty (key, value);
338.505 - if ("type".equals (key)) {
338.506 - if ("i".equalsIgnoreCase(value))
338.507 + super.setRequestProperty(key, value);
338.508 + if ("type".equals(key)) {
338.509 + if ("i".equalsIgnoreCase(value)) {
338.510 type = BIN;
338.511 - else if ("a".equalsIgnoreCase(value))
338.512 + } else if ("a".equalsIgnoreCase(value)) {
338.513 type = ASCII;
338.514 - else
338.515 - if ("d".equalsIgnoreCase(value))
338.516 - type = DIR;
338.517 - else
338.518 + } else if ("d".equalsIgnoreCase(value)) {
338.519 + type = DIR;
338.520 + } else {
338.521 throw new IllegalArgumentException(
338.522 - "Value of '" + key +
338.523 - "' request property was '" + value +
338.524 - "' when it must be either 'i', 'a' or 'd'");
338.525 + "Value of '" + key +
338.526 + "' request property was '" + value +
338.527 + "' when it must be either 'i', 'a' or 'd'");
338.528 + }
338.529 }
338.530 }
338.531
338.532 @@ -562,33 +601,41 @@
338.533 * @throws IllegalStateException if already connected
338.534 * @see #setRequestProperty(java.lang.String, java.lang.String)
338.535 */
338.536 + @Override
338.537 public String getRequestProperty(String key) {
338.538 - String value = super.getRequestProperty (key);
338.539 + String value = super.getRequestProperty(key);
338.540
338.541 if (value == null) {
338.542 - if ("type".equals (key))
338.543 + if ("type".equals(key)) {
338.544 value = (type == ASCII ? "a" : type == DIR ? "d" : "i");
338.545 + }
338.546 }
338.547
338.548 return value;
338.549 }
338.550
338.551 + @Override
338.552 public void setConnectTimeout(int timeout) {
338.553 - if (timeout < 0)
338.554 + if (timeout < 0) {
338.555 throw new IllegalArgumentException("timeouts can't be negative");
338.556 + }
338.557 connectTimeout = timeout;
338.558 }
338.559
338.560 + @Override
338.561 public int getConnectTimeout() {
338.562 return (connectTimeout < 0 ? 0 : connectTimeout);
338.563 }
338.564
338.565 + @Override
338.566 public void setReadTimeout(int timeout) {
338.567 - if (timeout < 0)
338.568 + if (timeout < 0) {
338.569 throw new IllegalArgumentException("timeouts can't be negative");
338.570 + }
338.571 readTimeout = timeout;
338.572 }
338.573
338.574 + @Override
338.575 public int getReadTimeout() {
338.576 return readTimeout < 0 ? 0 : readTimeout;
338.577 }
339.1 --- a/src/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java Mon Nov 23 10:04:47 2009 +0000
339.2 +++ b/src/share/classes/sun/net/www/protocol/http/AuthenticationInfo.java Wed Nov 25 11:08:25 2009 -0800
339.3 @@ -25,12 +25,10 @@
339.4
339.5 package sun.net.www.protocol.http;
339.6
339.7 -import java.io.*;
339.8 -import java.net.*;
339.9 -import java.util.Hashtable;
339.10 -import java.util.LinkedList;
339.11 -import java.util.ListIterator;
339.12 -import java.util.Enumeration;
339.13 +import java.io.IOException;
339.14 +import java.io.ObjectInputStream;
339.15 +import java.net.PasswordAuthentication;
339.16 +import java.net.URL;
339.17 import java.util.HashMap;
339.18
339.19 import sun.net.www.HeaderParser;
339.20 @@ -51,12 +49,12 @@
339.21 // policy in HttpURLConnection. A failure on baz.foo.com shouldn't
339.22 // uncache foo.com!
339.23
339.24 -abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable {
339.25 +public abstract class AuthenticationInfo extends AuthCacheValue implements Cloneable {
339.26
339.27 // Constants saying what kind of authroization this is. This determines
339.28 // the namespace in the hash table lookup.
339.29 - static final char SERVER_AUTHENTICATION = 's';
339.30 - static final char PROXY_AUTHENTICATION = 'p';
339.31 + public static final char SERVER_AUTHENTICATION = 's';
339.32 + public static final char PROXY_AUTHENTICATION = 'p';
339.33
339.34 /**
339.35 * If true, then simultaneous authentication requests to the same realm/proxy
339.36 @@ -188,7 +186,7 @@
339.37 String path;
339.38
339.39 /** Use this constructor only for proxy entries */
339.40 - AuthenticationInfo(char type, AuthScheme authScheme, String host, int port, String realm) {
339.41 + public AuthenticationInfo(char type, AuthScheme authScheme, String host, int port, String realm) {
339.42 this.type = type;
339.43 this.authScheme = authScheme;
339.44 this.protocol = "";
339.45 @@ -211,7 +209,7 @@
339.46 * Constructor used to limit the authorization to the path within
339.47 * the URL. Use this constructor for origin server entries.
339.48 */
339.49 - AuthenticationInfo(char type, AuthScheme authScheme, URL url, String realm) {
339.50 + public AuthenticationInfo(char type, AuthScheme authScheme, URL url, String realm) {
339.51 this.type = type;
339.52 this.authScheme = authScheme;
339.53 this.protocol = url.getProtocol().toLowerCase();
339.54 @@ -358,13 +356,19 @@
339.55 /**
339.56 * @return true if this authentication supports preemptive authorization
339.57 */
339.58 - abstract boolean supportsPreemptiveAuthorization();
339.59 + public abstract boolean supportsPreemptiveAuthorization();
339.60
339.61 /**
339.62 * @return the name of the HTTP header this authentication wants set.
339.63 * This is used for preemptive authorization.
339.64 */
339.65 - abstract String getHeaderName();
339.66 + public String getHeaderName() {
339.67 + if (type == SERVER_AUTHENTICATION) {
339.68 + return "Authorization";
339.69 + } else {
339.70 + return "Proxy-authorization";
339.71 + }
339.72 + }
339.73
339.74 /**
339.75 * Calculates and returns the authentication header value based
339.76 @@ -375,7 +379,7 @@
339.77 * @return the value of the HTTP header this authentication wants set.
339.78 * Used for preemptive authorization.
339.79 */
339.80 - abstract String getHeaderValue(URL url, String method);
339.81 + public abstract String getHeaderValue(URL url, String method);
339.82
339.83 /**
339.84 * Set header(s) on the given connection. Subclasses must override
339.85 @@ -386,7 +390,7 @@
339.86 * @param raw The raw header field (if needed)
339.87 * @return true if all goes well, false if no headers were set.
339.88 */
339.89 - abstract boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw);
339.90 + public abstract boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw);
339.91
339.92 /**
339.93 * Check if the header indicates that the current auth. parameters are stale.
339.94 @@ -396,7 +400,7 @@
339.95 * returning false means we have to go back to the user to ask for a new
339.96 * username password.
339.97 */
339.98 - abstract boolean isAuthorizationStale (String header);
339.99 + public abstract boolean isAuthorizationStale (String header);
339.100
339.101 /**
339.102 * Give a key for hash table lookups.
340.1 --- a/src/share/classes/sun/net/www/protocol/http/BasicAuthentication.java Mon Nov 23 10:04:47 2009 +0000
340.2 +++ b/src/share/classes/sun/net/www/protocol/http/BasicAuthentication.java Wed Nov 25 11:08:25 2009 -0800
340.3 @@ -131,22 +131,12 @@
340.4 /**
340.5 * @return true if this authentication supports preemptive authorization
340.6 */
340.7 - boolean supportsPreemptiveAuthorization() {
340.8 + @Override
340.9 + public boolean supportsPreemptiveAuthorization() {
340.10 return true;
340.11 }
340.12
340.13 /**
340.14 - * @return the name of the HTTP header this authentication wants set
340.15 - */
340.16 - String getHeaderName() {
340.17 - if (type == SERVER_AUTHENTICATION) {
340.18 - return "Authorization";
340.19 - } else {
340.20 - return "Proxy-authorization";
340.21 - }
340.22 - }
340.23 -
340.24 - /**
340.25 * Set header(s) on the given connection. This will only be called for
340.26 * definitive (i.e. non-preemptive) authorization.
340.27 * @param conn The connection to apply the header(s) to
340.28 @@ -154,7 +144,8 @@
340.29 * @param raw The raw header values for this connection, if needed.
340.30 * @return true if all goes well, false if no headers were set.
340.31 */
340.32 - boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
340.33 + @Override
340.34 + public boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
340.35 conn.setAuthenticationProperty(getHeaderName(), getHeaderValue(null,null));
340.36 return true;
340.37 }
340.38 @@ -162,7 +153,8 @@
340.39 /**
340.40 * @return the value of the HTTP header this authentication wants set
340.41 */
340.42 - String getHeaderValue(URL url, String method) {
340.43 + @Override
340.44 + public String getHeaderValue(URL url, String method) {
340.45 /* For Basic the authorization string does not depend on the request URL
340.46 * or the request method
340.47 */
340.48 @@ -174,7 +166,8 @@
340.49 * In other words there is no possibility to reuse the credentials.
340.50 * They are always either valid or invalid.
340.51 */
340.52 - boolean isAuthorizationStale (String header) {
340.53 + @Override
340.54 + public boolean isAuthorizationStale (String header) {
340.55 return false;
340.56 }
340.57
341.1 --- a/src/share/classes/sun/net/www/protocol/http/DigestAuthentication.java Mon Nov 23 10:04:47 2009 +0000
341.2 +++ b/src/share/classes/sun/net/www/protocol/http/DigestAuthentication.java Wed Nov 25 11:08:25 2009 -0800
341.3 @@ -200,22 +200,12 @@
341.4 /**
341.5 * @return true if this authentication supports preemptive authorization
341.6 */
341.7 - boolean supportsPreemptiveAuthorization() {
341.8 + @Override
341.9 + public boolean supportsPreemptiveAuthorization() {
341.10 return true;
341.11 }
341.12
341.13 /**
341.14 - * @return the name of the HTTP header this authentication wants set
341.15 - */
341.16 - String getHeaderName() {
341.17 - if (type == SERVER_AUTHENTICATION) {
341.18 - return "Authorization";
341.19 - } else {
341.20 - return "Proxy-Authorization";
341.21 - }
341.22 - }
341.23 -
341.24 - /**
341.25 * Reclaculates the request-digest and returns it.
341.26 *
341.27 * <P> Used in the common case where the requestURI is simply the
341.28 @@ -229,7 +219,8 @@
341.29 *
341.30 * @return the value of the HTTP header this authentication wants set
341.31 */
341.32 - String getHeaderValue(URL url, String method) {
341.33 + @Override
341.34 + public String getHeaderValue(URL url, String method) {
341.35 return getHeaderValueImpl(url.getFile(), method);
341.36 }
341.37
341.38 @@ -259,7 +250,8 @@
341.39 * returning false means we have to go back to the user to ask for a new
341.40 * username password.
341.41 */
341.42 - boolean isAuthorizationStale (String header) {
341.43 + @Override
341.44 + public boolean isAuthorizationStale (String header) {
341.45 HeaderParser p = new HeaderParser (header);
341.46 String s = p.findValue ("stale");
341.47 if (s == null || !s.equals("true"))
341.48 @@ -279,19 +271,22 @@
341.49 * @param raw Raw header values for this connection, if needed.
341.50 * @return true if all goes well, false if no headers were set.
341.51 */
341.52 - boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
341.53 + @Override
341.54 + public boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
341.55 params.setNonce (p.findValue("nonce"));
341.56 params.setOpaque (p.findValue("opaque"));
341.57 params.setQop (p.findValue("qop"));
341.58
341.59 - String uri;
341.60 + String uri="";
341.61 String method;
341.62 if (type == PROXY_AUTHENTICATION &&
341.63 conn.tunnelState() == HttpURLConnection.TunnelState.SETUP) {
341.64 uri = HttpURLConnection.connectRequestURI(conn.getURL());
341.65 method = HTTP_CONNECT;
341.66 } else {
341.67 - uri = conn.getRequestURI();
341.68 + try {
341.69 + uri = conn.getRequestURI();
341.70 + } catch (IOException e) {}
341.71 method = conn.getMethod();
341.72 }
341.73
342.1 --- a/src/share/classes/sun/net/www/protocol/http/HttpLogFormatter.java Mon Nov 23 10:04:47 2009 +0000
342.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
342.3 @@ -1,131 +0,0 @@
342.4 -/*
342.5 - * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
342.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
342.7 - *
342.8 - * This code is free software; you can redistribute it and/or modify it
342.9 - * under the terms of the GNU General Public License version 2 only, as
342.10 - * published by the Free Software Foundation. Sun designates this
342.11 - * particular file as subject to the "Classpath" exception as provided
342.12 - * by Sun in the LICENSE file that accompanied this code.
342.13 - *
342.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
342.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
342.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
342.17 - * version 2 for more details (a copy is included in the LICENSE file that
342.18 - * accompanied this code).
342.19 - *
342.20 - * You should have received a copy of the GNU General Public License version
342.21 - * 2 along with this work; if not, write to the Free Software Foundation,
342.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
342.23 - *
342.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
342.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
342.26 - * have any questions.
342.27 - */
342.28 -
342.29 -package sun.net.www.protocol.http;
342.30 -
342.31 -import java.util.logging.LogRecord;
342.32 -import java.util.regex.*;
342.33 -
342.34 -/**
342.35 - * A Formatter to make the HTTP logs a bit more palatable to the developer
342.36 - * looking at them. The idea is to present the HTTP events in such a way that
342.37 - * commands and headers are easily spotted (i.e. on separate lines).
342.38 - * @author jccollet
342.39 - */
342.40 -public class HttpLogFormatter extends java.util.logging.SimpleFormatter {
342.41 - // Pattern for MessageHeader data. Mostly pairs within curly brackets
342.42 - private static volatile Pattern pattern = null;
342.43 - // Pattern for Cookies
342.44 - private static volatile Pattern cpattern = null;
342.45 -
342.46 - public HttpLogFormatter() {
342.47 - if (pattern == null) {
342.48 - pattern = Pattern.compile("\\{[^\\}]*\\}");
342.49 - cpattern = Pattern.compile("[^,\\] ]{2,}");
342.50 - }
342.51 - }
342.52 -
342.53 - @Override
342.54 - public String format(LogRecord record) {
342.55 - String sourceClassName = record.getSourceClassName();
342.56 - if (sourceClassName == null ||
342.57 - !(sourceClassName.startsWith("sun.net.www.protocol.http") ||
342.58 - sourceClassName.startsWith("sun.net.www.http"))) {
342.59 - return super.format(record);
342.60 - }
342.61 - String src = record.getMessage();
342.62 - StringBuilder buf = new StringBuilder("HTTP: ");
342.63 - if (src.startsWith("sun.net.www.MessageHeader@")) {
342.64 - // MessageHeader logs are composed of pairs within curly brackets
342.65 - // Let's extract them to make it more readable. That way we get one
342.66 - // header pair (name, value) per line. A lot easier to read.
342.67 - Matcher match = pattern.matcher(src);
342.68 - while (match.find()) {
342.69 - int i = match.start();
342.70 - int j = match.end();
342.71 - String s = src.substring(i + 1, j - 1);
342.72 - if (s.startsWith("null: ")) {
342.73 - s = s.substring(6);
342.74 - }
342.75 - if (s.endsWith(": null")) {
342.76 - s = s.substring(0, s.length() - 6);
342.77 - }
342.78 - buf.append("\t").append(s).append("\n");
342.79 - }
342.80 - } else if (src.startsWith("Cookies retrieved: {")) {
342.81 - // This comes from the Cookie handler, let's clean up the format a bit
342.82 - String s = src.substring(20);
342.83 - buf.append("Cookies from handler:\n");
342.84 - while (s.length() >= 7) {
342.85 - if (s.startsWith("Cookie=[")) {
342.86 - String s2 = s.substring(8);
342.87 - int c = s2.indexOf("Cookie2=[");
342.88 - if (c > 0) {
342.89 - s2 = s2.substring(0, c-1);
342.90 - s = s2.substring(c);
342.91 - } else {
342.92 - s = "";
342.93 - }
342.94 - if (s2.length() < 4) {
342.95 - continue;
342.96 - }
342.97 - Matcher m = cpattern.matcher(s2);
342.98 - while (m.find()) {
342.99 - int i = m.start();
342.100 - int j = m.end();
342.101 - if (i >= 0) {
342.102 - String cookie = s2.substring(i + 1, j > 0 ? j - 1 : s2.length() - 1);
342.103 - buf.append("\t").append(cookie).append("\n");
342.104 - }
342.105 - }
342.106 - }
342.107 - if (s.startsWith("Cookie2=[")) {
342.108 - String s2 = s.substring(9);
342.109 - int c = s2.indexOf("Cookie=[");
342.110 - if (c > 0) {
342.111 - s2 = s2.substring(0, c-1);
342.112 - s = s2.substring(c);
342.113 - } else {
342.114 - s = "";
342.115 - }
342.116 - Matcher m = cpattern.matcher(s2);
342.117 - while (m.find()) {
342.118 - int i = m.start();
342.119 - int j = m.end();
342.120 - if (i >= 0) {
342.121 - String cookie = s2.substring(i+1, j > 0 ? j-1 : s2.length() - 1);
342.122 - buf.append("\t").append(cookie).append("\n");
342.123 - }
342.124 - }
342.125 - }
342.126 - }
342.127 - } else {
342.128 - // Anything else we let as is.
342.129 - buf.append(src).append("\n");
342.130 - }
342.131 - return buf.toString();
342.132 - }
342.133 -
342.134 -}
343.1 --- a/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Mon Nov 23 10:04:47 2009 +0000
343.2 +++ b/src/share/classes/sun/net/www/protocol/http/HttpURLConnection.java Wed Nov 25 11:08:25 2009 -0800
343.3 @@ -243,7 +243,7 @@
343.4 private boolean tryTransparentNTLMProxy = true;
343.5
343.6 /* Used by Windows specific code */
343.7 - Object authObj;
343.8 + private Object authObj;
343.9
343.10 /* Set if the user is manually setting the Authorization or Proxy-Authorization headers */
343.11 boolean isUserServerAuth;
343.12 @@ -332,6 +332,15 @@
343.13 return logger;
343.14 }
343.15
343.16 + /* Used for Windows NTLM implementation */
343.17 + public Object authObj() {
343.18 + return authObj;
343.19 + }
343.20 +
343.21 + public void authObj(Object authObj) {
343.22 + this.authObj = authObj;
343.23 + }
343.24 +
343.25 /*
343.26 * checks the validity of http message header and throws
343.27 * IllegalArgumentException if invalid.
343.28 @@ -1543,7 +1552,7 @@
343.29 * because ntlm does not support this feature.
343.30 */
343.31 private AuthenticationInfo
343.32 - resetProxyAuthentication(AuthenticationInfo proxyAuthentication, AuthenticationHeader auth) {
343.33 + resetProxyAuthentication(AuthenticationInfo proxyAuthentication, AuthenticationHeader auth) throws IOException {
343.34 if ((proxyAuthentication != null )&&
343.35 proxyAuthentication.getAuthScheme() != NTLM) {
343.36 String raw = auth.raw();
343.37 @@ -1767,7 +1776,7 @@
343.38 /**
343.39 * Sets pre-emptive proxy authentication in header
343.40 */
343.41 - private void setPreemptiveProxyAuthentication(MessageHeader requests) {
343.42 + private void setPreemptiveProxyAuthentication(MessageHeader requests) throws IOException {
343.43 AuthenticationInfo pauth
343.44 = AuthenticationInfo.getProxyAuth(http.getProxyHostUsed(),
343.45 http.getProxyPortUsed());
343.46 @@ -2123,13 +2132,9 @@
343.47
343.48 String requestURI = null;
343.49
343.50 - String getRequestURI() {
343.51 + String getRequestURI() throws IOException {
343.52 if (requestURI == null) {
343.53 - try {
343.54 - requestURI = http.getURLFile();
343.55 - } catch (IOException e) {
343.56 - requestURI = "";
343.57 - }
343.58 + requestURI = http.getURLFile();
343.59 }
343.60 return requestURI;
343.61 }
343.62 @@ -2529,7 +2534,7 @@
343.63 // Set a property for authentication. This can safely disregard
343.64 // the connected test.
343.65 //
343.66 - void setAuthenticationProperty(String key, String value) {
343.67 + public void setAuthenticationProperty(String key, String value) {
343.68 checkMessageHeader(key, value);
343.69 requests.set(key, value);
343.70 }
344.1 --- a/src/share/classes/sun/net/www/protocol/http/NTLMAuthenticationProxy.java Mon Nov 23 10:04:47 2009 +0000
344.2 +++ b/src/share/classes/sun/net/www/protocol/http/NTLMAuthenticationProxy.java Wed Nov 25 11:08:25 2009 -0800
344.3 @@ -36,7 +36,7 @@
344.4 */
344.5 class NTLMAuthenticationProxy {
344.6 private static Method supportsTA;
344.7 - private static final String clazzStr = "sun.net.www.protocol.http.NTLMAuthentication";
344.8 + private static final String clazzStr = "sun.net.www.protocol.http.ntlm.NTLMAuthentication";
344.9 private static final String supportsTAStr = "supportsTransparentAuth";
344.10
344.11 static final NTLMAuthenticationProxy proxy = tryLoadNTLMAuthentication();
345.1 --- a/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java Mon Nov 23 10:04:47 2009 +0000
345.2 +++ b/src/share/classes/sun/net/www/protocol/http/NegotiateAuthentication.java Wed Nov 25 11:08:25 2009 -0800
345.3 @@ -25,17 +25,13 @@
345.4
345.5 package sun.net.www.protocol.http;
345.6
345.7 +import java.net.URL;
345.8 +import java.io.IOException;
345.9 +import java.net.Authenticator.RequestorType;
345.10 import java.util.HashMap;
345.11 -
345.12 import sun.net.www.HeaderParser;
345.13 import sun.misc.BASE64Decoder;
345.14 import sun.misc.BASE64Encoder;
345.15 -import sun.util.logging.PlatformLogger;
345.16 -
345.17 -import java.net.URL;
345.18 -import java.io.IOException;
345.19 -import java.net.Authenticator.RequestorType;
345.20 -import java.lang.reflect.Constructor;
345.21 import static sun.net.www.protocol.http.AuthScheme.NEGOTIATE;
345.22 import static sun.net.www.protocol.http.AuthScheme.KERBEROS;
345.23
345.24 @@ -78,7 +74,8 @@
345.25 /**
345.26 * @return true if this authentication supports preemptive authorization
345.27 */
345.28 - boolean supportsPreemptiveAuthorization() {
345.29 + @Override
345.30 + public boolean supportsPreemptiveAuthorization() {
345.31 return false;
345.32 }
345.33
345.34 @@ -104,34 +101,24 @@
345.35 return supported.get(hostname);
345.36 }
345.37
345.38 - try {
345.39 - Negotiator neg = Negotiator.getSupported(hci);
345.40 + Negotiator neg = Negotiator.getNegotiator(hci);
345.41 + if (neg != null) {
345.42 supported.put(hostname, true);
345.43 // the only place cache.put is called. here we can make sure
345.44 // the object is valid and the oneToken inside is not null
345.45 cache.put(hostname, neg);
345.46 return true;
345.47 - } catch(Exception e) {
345.48 + } else {
345.49 supported.put(hostname, false);
345.50 return false;
345.51 }
345.52 }
345.53
345.54 /**
345.55 - * @return the name of the HTTP header this authentication wants to set
345.56 - */
345.57 - String getHeaderName() {
345.58 - if (type == SERVER_AUTHENTICATION) {
345.59 - return "Authorization";
345.60 - } else {
345.61 - return "Proxy-Authorization";
345.62 - }
345.63 - }
345.64 -
345.65 - /**
345.66 * Not supported. Must use the setHeaders() method
345.67 */
345.68 - String getHeaderValue(URL url, String method) {
345.69 + @Override
345.70 + public String getHeaderValue(URL url, String method) {
345.71 throw new RuntimeException ("getHeaderValue not supported");
345.72 }
345.73
345.74 @@ -143,7 +130,8 @@
345.75 * returning false means we have to go back to the user to ask for a new
345.76 * username password.
345.77 */
345.78 - boolean isAuthorizationStale (String header) {
345.79 + @Override
345.80 + public boolean isAuthorizationStale (String header) {
345.81 return false; /* should not be called for Negotiate */
345.82 }
345.83
345.84 @@ -155,7 +143,8 @@
345.85 * @param raw The raw header field.
345.86 * @return true if all goes well, false if no headers were set.
345.87 */
345.88 - synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
345.89 + @Override
345.90 + public synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
345.91
345.92 try {
345.93 String response;
345.94 @@ -177,7 +166,7 @@
345.95 /**
345.96 * return the first token.
345.97 * @returns the token
345.98 - * @throws IOException if <code>Negotiator.getSupported()</code> or
345.99 + * @throws IOException if <code>Negotiator.getNegotiator()</code> or
345.100 * <code>Negotiator.firstToken()</code> failed.
345.101 */
345.102 private byte[] firstToken() throws IOException {
345.103 @@ -191,11 +180,9 @@
345.104 }
345.105 }
345.106 if (negotiator == null) {
345.107 - try {
345.108 - negotiator = Negotiator.getSupported(hci);
345.109 - } catch(Exception e) {
345.110 + negotiator = Negotiator.getNegotiator(hci);
345.111 + if (negotiator == null) {
345.112 IOException ioe = new IOException("Cannot initialize Negotiator");
345.113 - ioe.initCause(e);
345.114 throw ioe;
345.115 }
345.116 }
345.117 @@ -228,55 +215,3 @@
345.118 // Currently we ignore this header.
345.119
345.120 }
345.121 -
345.122 -/**
345.123 - * This abstract class is a bridge to connect NegotiteAuthentication and
345.124 - * NegotiatorImpl, so that JAAS and JGSS calls can be made
345.125 - */
345.126 -abstract class Negotiator {
345.127 - static Negotiator getSupported(HttpCallerInfo hci)
345.128 - throws Exception {
345.129 -
345.130 - // These lines are equivalent to
345.131 - // return new NegotiatorImpl(hci);
345.132 - // The current implementation will make sure NegotiatorImpl is not
345.133 - // directly referenced when compiling, thus smooth the way of building
345.134 - // the J2SE platform where HttpURLConnection is a bootstrap class.
345.135 - //
345.136 - // Makes NegotiatorImpl, and the security classes it references, a
345.137 - // runtime dependency rather than a static one.
345.138 -
345.139 - Class clazz;
345.140 - Constructor c;
345.141 - try {
345.142 - clazz = Class.forName("sun.net.www.protocol.http.NegotiatorImpl", true, null);
345.143 - c = clazz.getConstructor(HttpCallerInfo.class);
345.144 - } catch (ClassNotFoundException cnfe) {
345.145 - finest(cnfe);
345.146 - throw cnfe;
345.147 - } catch (ReflectiveOperationException roe) {
345.148 - // if the class is there then something seriously wrong if
345.149 - // the constructor is not.
345.150 - throw new AssertionError(roe);
345.151 - }
345.152 -
345.153 - try {
345.154 - return (Negotiator) (c.newInstance(hci));
345.155 - } catch (ReflectiveOperationException roe) {
345.156 - finest(roe);
345.157 - Throwable t = roe.getCause();
345.158 - if (t != null && t instanceof Exception)
345.159 - finest((Exception)t);
345.160 - throw roe;
345.161 - }
345.162 - }
345.163 -
345.164 - abstract byte[] firstToken() throws IOException;
345.165 -
345.166 - abstract byte[] nextToken(byte[] in) throws IOException;
345.167 -
345.168 - static void finest(Exception e) {
345.169 - PlatformLogger logger = HttpURLConnection.getHttpLogger();
345.170 - logger.finest("NegotiateAuthentication: " + e);
345.171 - }
345.172 -}
346.1 --- a/src/share/classes/sun/net/www/protocol/http/NegotiateCallbackHandler.java Mon Nov 23 10:04:47 2009 +0000
346.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
346.3 @@ -1,89 +0,0 @@
346.4 -/*
346.5 - * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved.
346.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
346.7 - *
346.8 - * This code is free software; you can redistribute it and/or modify it
346.9 - * under the terms of the GNU General Public License version 2 only, as
346.10 - * published by the Free Software Foundation. Sun designates this
346.11 - * particular file as subject to the "Classpath" exception as provided
346.12 - * by Sun in the LICENSE file that accompanied this code.
346.13 - *
346.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
346.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
346.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
346.17 - * version 2 for more details (a copy is included in the LICENSE file that
346.18 - * accompanied this code).
346.19 - *
346.20 - * You should have received a copy of the GNU General Public License version
346.21 - * 2 along with this work; if not, write to the Free Software Foundation,
346.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
346.23 - *
346.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
346.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
346.26 - * have any questions.
346.27 - */
346.28 -
346.29 -package sun.net.www.protocol.http;
346.30 -import java.io.IOException;
346.31 -import java.net.Authenticator;
346.32 -import java.net.PasswordAuthentication;
346.33 -import java.util.Arrays;
346.34 -import javax.security.auth.callback.Callback;
346.35 -import javax.security.auth.callback.CallbackHandler;
346.36 -import javax.security.auth.callback.NameCallback;
346.37 -import javax.security.auth.callback.PasswordCallback;
346.38 -import javax.security.auth.callback.UnsupportedCallbackException;
346.39 -
346.40 -/**
346.41 - * @since 1.6
346.42 - * Special callback handler used in JGSS for the HttpCaller.
346.43 - */
346.44 -public class NegotiateCallbackHandler implements CallbackHandler {
346.45 -
346.46 - private String username;
346.47 - private char[] password;
346.48 -
346.49 - private final HttpCallerInfo hci;
346.50 -
346.51 - public NegotiateCallbackHandler(HttpCallerInfo hci) {
346.52 - this.hci = hci;
346.53 - }
346.54 -
346.55 - public void handle(Callback[] callbacks) throws
346.56 - UnsupportedCallbackException, IOException {
346.57 - for (int i=0; i<callbacks.length; i++) {
346.58 - Callback callBack = callbacks[i];
346.59 -
346.60 - if (callBack instanceof NameCallback) {
346.61 - if (username == null) {
346.62 - PasswordAuthentication passAuth =
346.63 - Authenticator.requestPasswordAuthentication(
346.64 - hci.host, hci.addr, hci.port, hci.protocol,
346.65 - hci.prompt, hci.scheme, hci.url, hci.authType);
346.66 - username = passAuth.getUserName();
346.67 - password = passAuth.getPassword();
346.68 - }
346.69 - NameCallback nameCallback =
346.70 - (NameCallback)callBack;
346.71 - nameCallback.setName(username);
346.72 -
346.73 - } else if (callBack instanceof PasswordCallback) {
346.74 - PasswordCallback passwordCallback =
346.75 - (PasswordCallback)callBack;
346.76 - if (password == null) {
346.77 - PasswordAuthentication passAuth =
346.78 - Authenticator.requestPasswordAuthentication(
346.79 - hci.host, hci.addr, hci.port, hci.protocol,
346.80 - hci.prompt, hci.scheme, hci.url, hci.authType);
346.81 - username = passAuth.getUserName();
346.82 - password = passAuth.getPassword();
346.83 - }
346.84 - passwordCallback.setPassword(password);
346.85 - Arrays.fill(password, ' ');
346.86 - } else {
346.87 - throw new UnsupportedCallbackException(callBack,
346.88 - "Call back not supported");
346.89 - }
346.90 - }
346.91 - }
346.92 -}
347.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
347.2 +++ b/src/share/classes/sun/net/www/protocol/http/Negotiator.java Wed Nov 25 11:08:25 2009 -0800
347.3 @@ -0,0 +1,82 @@
347.4 +/*
347.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
347.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
347.7 + *
347.8 + * This code is free software; you can redistribute it and/or modify it
347.9 + * under the terms of the GNU General Public License version 2 only, as
347.10 + * published by the Free Software Foundation. Sun designates this
347.11 + * particular file as subject to the "Classpath" exception as provided
347.12 + * by Sun in the LICENSE file that accompanied this code.
347.13 + *
347.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
347.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
347.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
347.17 + * version 2 for more details (a copy is included in the LICENSE file that
347.18 + * accompanied this code).
347.19 + *
347.20 + * You should have received a copy of the GNU General Public License version
347.21 + * 2 along with this work; if not, write to the Free Software Foundation,
347.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
347.23 + *
347.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
347.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
347.26 + * have any questions.
347.27 + */
347.28 +
347.29 +package sun.net.www.protocol.http;
347.30 +
347.31 +import java.io.IOException;
347.32 +import java.lang.reflect.Constructor;
347.33 +import sun.util.logging.PlatformLogger;
347.34 +
347.35 +/**
347.36 + * This abstract class is a bridge to connect NegotiteAuthentication and
347.37 + * NegotiatorImpl, so that JAAS and JGSS calls can be made
347.38 + */
347.39 +public abstract class Negotiator {
347.40 + static Negotiator getNegotiator(HttpCallerInfo hci) {
347.41 +
347.42 + // These lines are equivalent to
347.43 + // return new NegotiatorImpl(hci);
347.44 + // The current implementation will make sure NegotiatorImpl is not
347.45 + // directly referenced when compiling, thus smooth the way of building
347.46 + // the J2SE platform where HttpURLConnection is a bootstrap class.
347.47 + //
347.48 + // Makes NegotiatorImpl, and the security classes it references, a
347.49 + // runtime dependency rather than a static one.
347.50 +
347.51 + Class clazz;
347.52 + Constructor c;
347.53 + try {
347.54 + clazz = Class.forName("sun.net.www.protocol.http.spnego.NegotiatorImpl", true, null);
347.55 + c = clazz.getConstructor(HttpCallerInfo.class);
347.56 + } catch (ClassNotFoundException cnfe) {
347.57 + finest(cnfe);
347.58 + return null;
347.59 + } catch (ReflectiveOperationException roe) {
347.60 + // if the class is there then something seriously wrong if
347.61 + // the constructor is not.
347.62 + throw new AssertionError(roe);
347.63 + }
347.64 +
347.65 + try {
347.66 + return (Negotiator) (c.newInstance(hci));
347.67 + } catch (ReflectiveOperationException roe) {
347.68 + finest(roe);
347.69 + Throwable t = roe.getCause();
347.70 + if (t != null && t instanceof Exception)
347.71 + finest((Exception)t);
347.72 + return null;
347.73 + }
347.74 + }
347.75 +
347.76 + public abstract byte[] firstToken() throws IOException;
347.77 +
347.78 + public abstract byte[] nextToken(byte[] in) throws IOException;
347.79 +
347.80 + private static void finest(Exception e) {
347.81 + PlatformLogger logger = HttpURLConnection.getHttpLogger();
347.82 + logger.finest("NegotiateAuthentication: " + e);
347.83 + }
347.84 +}
347.85 +
348.1 --- a/src/share/classes/sun/net/www/protocol/http/NegotiatorImpl.java Mon Nov 23 10:04:47 2009 +0000
348.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
348.3 @@ -1,159 +0,0 @@
348.4 -/*
348.5 - * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved.
348.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
348.7 - *
348.8 - * This code is free software; you can redistribute it and/or modify it
348.9 - * under the terms of the GNU General Public License version 2 only, as
348.10 - * published by the Free Software Foundation. Sun designates this
348.11 - * particular file as subject to the "Classpath" exception as provided
348.12 - * by Sun in the LICENSE file that accompanied this code.
348.13 - *
348.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
348.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
348.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
348.17 - * version 2 for more details (a copy is included in the LICENSE file that
348.18 - * accompanied this code).
348.19 - *
348.20 - * You should have received a copy of the GNU General Public License version
348.21 - * 2 along with this work; if not, write to the Free Software Foundation,
348.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
348.23 - *
348.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
348.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
348.26 - * have any questions.
348.27 - */
348.28 -
348.29 -package sun.net.www.protocol.http;
348.30 -
348.31 -import java.io.IOException;
348.32 -
348.33 -import org.ietf.jgss.GSSContext;
348.34 -import org.ietf.jgss.GSSException;
348.35 -import org.ietf.jgss.GSSName;
348.36 -import org.ietf.jgss.Oid;
348.37 -
348.38 -import sun.security.jgss.GSSManagerImpl;
348.39 -import sun.security.jgss.GSSUtil;
348.40 -import sun.security.jgss.HttpCaller;
348.41 -
348.42 -/**
348.43 - * This class encapsulates all JAAS and JGSS API calls in a separate class
348.44 - * outside NegotiateAuthentication.java so that J2SE build can go smoothly
348.45 - * without the presence of it.
348.46 - *
348.47 - * @author weijun.wang@sun.com
348.48 - * @since 1.6
348.49 - */
348.50 -public class NegotiatorImpl extends Negotiator {
348.51 -
348.52 - private static final boolean DEBUG =
348.53 - java.security.AccessController.doPrivileged(
348.54 - new sun.security.action.GetBooleanAction("sun.security.krb5.debug"));
348.55 -
348.56 - private GSSContext context;
348.57 - private byte[] oneToken;
348.58 -
348.59 - /**
348.60 - * Initialize the object, which includes:<ul>
348.61 - * <li>Find out what GSS mechanism to use from the system property
348.62 - * <code>http.negotiate.mechanism.oid</code>, defaults SPNEGO
348.63 - * <li>Creating the GSSName for the target host, "HTTP/"+hostname
348.64 - * <li>Creating GSSContext
348.65 - * <li>A first call to initSecContext</ul>
348.66 - */
348.67 - private void init(HttpCallerInfo hci) throws GSSException {
348.68 - final Oid oid;
348.69 -
348.70 - if (hci.scheme.equalsIgnoreCase("Kerberos")) {
348.71 - // we can only use Kerberos mech when the scheme is kerberos
348.72 - oid = GSSUtil.GSS_KRB5_MECH_OID;
348.73 - } else {
348.74 - String pref = java.security.AccessController.doPrivileged(
348.75 - new java.security.PrivilegedAction<String>() {
348.76 - public String run() {
348.77 - return System.getProperty(
348.78 - "http.auth.preference",
348.79 - "spnego");
348.80 - }
348.81 - });
348.82 - if (pref.equalsIgnoreCase("kerberos")) {
348.83 - oid = GSSUtil.GSS_KRB5_MECH_OID;
348.84 - } else {
348.85 - // currently there is no 3rd mech we can use
348.86 - oid = GSSUtil.GSS_SPNEGO_MECH_OID;
348.87 - }
348.88 - }
348.89 -
348.90 - GSSManagerImpl manager = new GSSManagerImpl(
348.91 - new HttpCaller(hci));
348.92 -
348.93 - // RFC 4559 4.1 uses uppercase service name "HTTP".
348.94 - // RFC 4120 6.2.1 demands the host be lowercase
348.95 - String peerName = "HTTP@" + hci.host.toLowerCase();
348.96 -
348.97 - GSSName serverName = manager.createName(peerName,
348.98 - GSSName.NT_HOSTBASED_SERVICE);
348.99 - context = manager.createContext(serverName,
348.100 - oid,
348.101 - null,
348.102 - GSSContext.DEFAULT_LIFETIME);
348.103 -
348.104 - // In order to support credential delegation in HTTP/SPNEGO,
348.105 - // we always request it before initSecContext. The current
348.106 - // implementation will check the OK-AS-DELEGATE flag inside
348.107 - // the service ticket of the web server, and only enable
348.108 - // delegation when this flag is set. This check is only
348.109 - // performed when the GSS caller is CALLER_HTTP_NEGOTIATE,
348.110 - // so all other normal GSS-API calls are not affected.
348.111 -
348.112 - context.requestCredDeleg(true);
348.113 - oneToken = context.initSecContext(new byte[0], 0, 0);
348.114 - }
348.115 -
348.116 - /**
348.117 - * Constructor
348.118 - * @throws java.io.IOException If negotiator cannot be constructed
348.119 - */
348.120 - public NegotiatorImpl(HttpCallerInfo hci) throws IOException {
348.121 - try {
348.122 - init(hci);
348.123 - } catch (GSSException e) {
348.124 - if (DEBUG) {
348.125 - System.out.println("Negotiate support not initiated, will " +
348.126 - "fallback to other scheme if allowed. Reason:");
348.127 - e.printStackTrace();
348.128 - }
348.129 - IOException ioe = new IOException("Negotiate support not initiated");
348.130 - ioe.initCause(e);
348.131 - throw ioe;
348.132 - }
348.133 - }
348.134 -
348.135 - /**
348.136 - * Return the first token of GSS, in SPNEGO, it's called NegTokenInit
348.137 - * @return the first token
348.138 - */
348.139 - public byte[] firstToken() {
348.140 - return oneToken;
348.141 - }
348.142 -
348.143 - /**
348.144 - * Return the rest tokens of GSS, in SPNEGO, it's called NegTokenTarg
348.145 - * @param token the token received from server
348.146 - * @return the next token
348.147 - * @throws java.io.IOException if the token cannot be created successfully
348.148 - */
348.149 - public byte[] nextToken(byte[] token) throws IOException {
348.150 - try {
348.151 - return context.initSecContext(token, 0, token.length);
348.152 - } catch (GSSException e) {
348.153 - if (DEBUG) {
348.154 - System.out.println("Negotiate support cannot continue. Reason:");
348.155 - e.printStackTrace();
348.156 - }
348.157 - IOException ioe = new IOException("Negotiate support cannot continue");
348.158 - ioe.initCause(e);
348.159 - throw ioe;
348.160 - }
348.161 - }
348.162 -}
349.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
349.2 +++ b/src/share/classes/sun/net/www/protocol/http/logging/HttpLogFormatter.java Wed Nov 25 11:08:25 2009 -0800
349.3 @@ -0,0 +1,131 @@
349.4 +/*
349.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
349.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
349.7 + *
349.8 + * This code is free software; you can redistribute it and/or modify it
349.9 + * under the terms of the GNU General Public License version 2 only, as
349.10 + * published by the Free Software Foundation. Sun designates this
349.11 + * particular file as subject to the "Classpath" exception as provided
349.12 + * by Sun in the LICENSE file that accompanied this code.
349.13 + *
349.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
349.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
349.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
349.17 + * version 2 for more details (a copy is included in the LICENSE file that
349.18 + * accompanied this code).
349.19 + *
349.20 + * You should have received a copy of the GNU General Public License version
349.21 + * 2 along with this work; if not, write to the Free Software Foundation,
349.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
349.23 + *
349.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
349.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
349.26 + * have any questions.
349.27 + */
349.28 +
349.29 +package sun.net.www.protocol.http.logging;
349.30 +
349.31 +import java.util.logging.LogRecord;
349.32 +import java.util.regex.*;
349.33 +
349.34 +/**
349.35 + * A Formatter to make the HTTP logs a bit more palatable to the developer
349.36 + * looking at them. The idea is to present the HTTP events in such a way that
349.37 + * commands and headers are easily spotted (i.e. on separate lines).
349.38 + * @author jccollet
349.39 + */
349.40 +public class HttpLogFormatter extends java.util.logging.SimpleFormatter {
349.41 + // Pattern for MessageHeader data. Mostly pairs within curly brackets
349.42 + private static volatile Pattern pattern = null;
349.43 + // Pattern for Cookies
349.44 + private static volatile Pattern cpattern = null;
349.45 +
349.46 + public HttpLogFormatter() {
349.47 + if (pattern == null) {
349.48 + pattern = Pattern.compile("\\{[^\\}]*\\}");
349.49 + cpattern = Pattern.compile("[^,\\] ]{2,}");
349.50 + }
349.51 + }
349.52 +
349.53 + @Override
349.54 + public String format(LogRecord record) {
349.55 + String sourceClassName = record.getSourceClassName();
349.56 + if (sourceClassName == null ||
349.57 + !(sourceClassName.startsWith("sun.net.www.protocol.http") ||
349.58 + sourceClassName.startsWith("sun.net.www.http"))) {
349.59 + return super.format(record);
349.60 + }
349.61 + String src = record.getMessage();
349.62 + StringBuilder buf = new StringBuilder("HTTP: ");
349.63 + if (src.startsWith("sun.net.www.MessageHeader@")) {
349.64 + // MessageHeader logs are composed of pairs within curly brackets
349.65 + // Let's extract them to make it more readable. That way we get one
349.66 + // header pair (name, value) per line. A lot easier to read.
349.67 + Matcher match = pattern.matcher(src);
349.68 + while (match.find()) {
349.69 + int i = match.start();
349.70 + int j = match.end();
349.71 + String s = src.substring(i + 1, j - 1);
349.72 + if (s.startsWith("null: ")) {
349.73 + s = s.substring(6);
349.74 + }
349.75 + if (s.endsWith(": null")) {
349.76 + s = s.substring(0, s.length() - 6);
349.77 + }
349.78 + buf.append("\t").append(s).append("\n");
349.79 + }
349.80 + } else if (src.startsWith("Cookies retrieved: {")) {
349.81 + // This comes from the Cookie handler, let's clean up the format a bit
349.82 + String s = src.substring(20);
349.83 + buf.append("Cookies from handler:\n");
349.84 + while (s.length() >= 7) {
349.85 + if (s.startsWith("Cookie=[")) {
349.86 + String s2 = s.substring(8);
349.87 + int c = s2.indexOf("Cookie2=[");
349.88 + if (c > 0) {
349.89 + s2 = s2.substring(0, c-1);
349.90 + s = s2.substring(c);
349.91 + } else {
349.92 + s = "";
349.93 + }
349.94 + if (s2.length() < 4) {
349.95 + continue;
349.96 + }
349.97 + Matcher m = cpattern.matcher(s2);
349.98 + while (m.find()) {
349.99 + int i = m.start();
349.100 + int j = m.end();
349.101 + if (i >= 0) {
349.102 + String cookie = s2.substring(i + 1, j > 0 ? j - 1 : s2.length() - 1);
349.103 + buf.append("\t").append(cookie).append("\n");
349.104 + }
349.105 + }
349.106 + }
349.107 + if (s.startsWith("Cookie2=[")) {
349.108 + String s2 = s.substring(9);
349.109 + int c = s2.indexOf("Cookie=[");
349.110 + if (c > 0) {
349.111 + s2 = s2.substring(0, c-1);
349.112 + s = s2.substring(c);
349.113 + } else {
349.114 + s = "";
349.115 + }
349.116 + Matcher m = cpattern.matcher(s2);
349.117 + while (m.find()) {
349.118 + int i = m.start();
349.119 + int j = m.end();
349.120 + if (i >= 0) {
349.121 + String cookie = s2.substring(i+1, j > 0 ? j-1 : s2.length() - 1);
349.122 + buf.append("\t").append(cookie).append("\n");
349.123 + }
349.124 + }
349.125 + }
349.126 + }
349.127 + } else {
349.128 + // Anything else we let as is.
349.129 + buf.append(src).append("\n");
349.130 + }
349.131 + return buf.toString();
349.132 + }
349.133 +
349.134 +}
350.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
350.2 +++ b/src/share/classes/sun/net/www/protocol/http/spnego/NegotiateCallbackHandler.java Wed Nov 25 11:08:25 2009 -0800
350.3 @@ -0,0 +1,91 @@
350.4 +/*
350.5 + * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved.
350.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
350.7 + *
350.8 + * This code is free software; you can redistribute it and/or modify it
350.9 + * under the terms of the GNU General Public License version 2 only, as
350.10 + * published by the Free Software Foundation. Sun designates this
350.11 + * particular file as subject to the "Classpath" exception as provided
350.12 + * by Sun in the LICENSE file that accompanied this code.
350.13 + *
350.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
350.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
350.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
350.17 + * version 2 for more details (a copy is included in the LICENSE file that
350.18 + * accompanied this code).
350.19 + *
350.20 + * You should have received a copy of the GNU General Public License version
350.21 + * 2 along with this work; if not, write to the Free Software Foundation,
350.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
350.23 + *
350.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
350.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
350.26 + * have any questions.
350.27 + */
350.28 +
350.29 +package sun.net.www.protocol.http.spnego;
350.30 +
350.31 +import java.io.IOException;
350.32 +import java.net.Authenticator;
350.33 +import java.net.PasswordAuthentication;
350.34 +import java.util.Arrays;
350.35 +import javax.security.auth.callback.Callback;
350.36 +import javax.security.auth.callback.CallbackHandler;
350.37 +import javax.security.auth.callback.NameCallback;
350.38 +import javax.security.auth.callback.PasswordCallback;
350.39 +import javax.security.auth.callback.UnsupportedCallbackException;
350.40 +import sun.net.www.protocol.http.HttpCallerInfo;
350.41 +
350.42 +/**
350.43 + * @since 1.6
350.44 + * Special callback handler used in JGSS for the HttpCaller.
350.45 + */
350.46 +public class NegotiateCallbackHandler implements CallbackHandler {
350.47 +
350.48 + private String username;
350.49 + private char[] password;
350.50 +
350.51 + private final HttpCallerInfo hci;
350.52 +
350.53 + public NegotiateCallbackHandler(HttpCallerInfo hci) {
350.54 + this.hci = hci;
350.55 + }
350.56 +
350.57 + public void handle(Callback[] callbacks) throws
350.58 + UnsupportedCallbackException, IOException {
350.59 + for (int i=0; i<callbacks.length; i++) {
350.60 + Callback callBack = callbacks[i];
350.61 +
350.62 + if (callBack instanceof NameCallback) {
350.63 + if (username == null) {
350.64 + PasswordAuthentication passAuth =
350.65 + Authenticator.requestPasswordAuthentication(
350.66 + hci.host, hci.addr, hci.port, hci.protocol,
350.67 + hci.prompt, hci.scheme, hci.url, hci.authType);
350.68 + username = passAuth.getUserName();
350.69 + password = passAuth.getPassword();
350.70 + }
350.71 + NameCallback nameCallback =
350.72 + (NameCallback)callBack;
350.73 + nameCallback.setName(username);
350.74 +
350.75 + } else if (callBack instanceof PasswordCallback) {
350.76 + PasswordCallback passwordCallback =
350.77 + (PasswordCallback)callBack;
350.78 + if (password == null) {
350.79 + PasswordAuthentication passAuth =
350.80 + Authenticator.requestPasswordAuthentication(
350.81 + hci.host, hci.addr, hci.port, hci.protocol,
350.82 + hci.prompt, hci.scheme, hci.url, hci.authType);
350.83 + username = passAuth.getUserName();
350.84 + password = passAuth.getPassword();
350.85 + }
350.86 + passwordCallback.setPassword(password);
350.87 + Arrays.fill(password, ' ');
350.88 + } else {
350.89 + throw new UnsupportedCallbackException(callBack,
350.90 + "Call back not supported");
350.91 + }
350.92 + }
350.93 + }
350.94 +}
351.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
351.2 +++ b/src/share/classes/sun/net/www/protocol/http/spnego/NegotiatorImpl.java Wed Nov 25 11:08:25 2009 -0800
351.3 @@ -0,0 +1,163 @@
351.4 +/*
351.5 + * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved.
351.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
351.7 + *
351.8 + * This code is free software; you can redistribute it and/or modify it
351.9 + * under the terms of the GNU General Public License version 2 only, as
351.10 + * published by the Free Software Foundation. Sun designates this
351.11 + * particular file as subject to the "Classpath" exception as provided
351.12 + * by Sun in the LICENSE file that accompanied this code.
351.13 + *
351.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
351.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
351.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
351.17 + * version 2 for more details (a copy is included in the LICENSE file that
351.18 + * accompanied this code).
351.19 + *
351.20 + * You should have received a copy of the GNU General Public License version
351.21 + * 2 along with this work; if not, write to the Free Software Foundation,
351.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
351.23 + *
351.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
351.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
351.26 + * have any questions.
351.27 + */
351.28 +
351.29 +package sun.net.www.protocol.http.spnego;
351.30 +
351.31 +import java.io.IOException;
351.32 +
351.33 +import org.ietf.jgss.GSSContext;
351.34 +import org.ietf.jgss.GSSException;
351.35 +import org.ietf.jgss.GSSName;
351.36 +import org.ietf.jgss.Oid;
351.37 +
351.38 +import sun.net.www.protocol.http.HttpCallerInfo;
351.39 +import sun.net.www.protocol.http.Negotiator;
351.40 +import sun.security.jgss.GSSManagerImpl;
351.41 +import sun.security.jgss.GSSUtil;
351.42 +import sun.security.jgss.HttpCaller;
351.43 +
351.44 +/**
351.45 + * This class encapsulates all JAAS and JGSS API calls in a separate class
351.46 + * outside NegotiateAuthentication.java so that J2SE build can go smoothly
351.47 + * without the presence of it.
351.48 + *
351.49 + * @author weijun.wang@sun.com
351.50 + * @since 1.6
351.51 + */
351.52 +public class NegotiatorImpl extends Negotiator {
351.53 +
351.54 + private static final boolean DEBUG =
351.55 + java.security.AccessController.doPrivileged(
351.56 + new sun.security.action.GetBooleanAction("sun.security.krb5.debug"));
351.57 +
351.58 + private GSSContext context;
351.59 + private byte[] oneToken;
351.60 +
351.61 + /**
351.62 + * Initialize the object, which includes:<ul>
351.63 + * <li>Find out what GSS mechanism to use from the system property
351.64 + * <code>http.negotiate.mechanism.oid</code>, defaults SPNEGO
351.65 + * <li>Creating the GSSName for the target host, "HTTP/"+hostname
351.66 + * <li>Creating GSSContext
351.67 + * <li>A first call to initSecContext</ul>
351.68 + */
351.69 + private void init(HttpCallerInfo hci) throws GSSException {
351.70 + final Oid oid;
351.71 +
351.72 + if (hci.scheme.equalsIgnoreCase("Kerberos")) {
351.73 + // we can only use Kerberos mech when the scheme is kerberos
351.74 + oid = GSSUtil.GSS_KRB5_MECH_OID;
351.75 + } else {
351.76 + String pref = java.security.AccessController.doPrivileged(
351.77 + new java.security.PrivilegedAction<String>() {
351.78 + public String run() {
351.79 + return System.getProperty(
351.80 + "http.auth.preference",
351.81 + "spnego");
351.82 + }
351.83 + });
351.84 + if (pref.equalsIgnoreCase("kerberos")) {
351.85 + oid = GSSUtil.GSS_KRB5_MECH_OID;
351.86 + } else {
351.87 + // currently there is no 3rd mech we can use
351.88 + oid = GSSUtil.GSS_SPNEGO_MECH_OID;
351.89 + }
351.90 + }
351.91 +
351.92 + GSSManagerImpl manager = new GSSManagerImpl(
351.93 + new HttpCaller(hci));
351.94 +
351.95 + // RFC 4559 4.1 uses uppercase service name "HTTP".
351.96 + // RFC 4120 6.2.1 demands the host be lowercase
351.97 + String peerName = "HTTP@" + hci.host.toLowerCase();
351.98 +
351.99 + GSSName serverName = manager.createName(peerName,
351.100 + GSSName.NT_HOSTBASED_SERVICE);
351.101 + context = manager.createContext(serverName,
351.102 + oid,
351.103 + null,
351.104 + GSSContext.DEFAULT_LIFETIME);
351.105 +
351.106 + // In order to support credential delegation in HTTP/SPNEGO,
351.107 + // we always request it before initSecContext. The current
351.108 + // implementation will check the OK-AS-DELEGATE flag inside
351.109 + // the service ticket of the web server, and only enable
351.110 + // delegation when this flag is set. This check is only
351.111 + // performed when the GSS caller is CALLER_HTTP_NEGOTIATE,
351.112 + // so all other normal GSS-API calls are not affected.
351.113 +
351.114 + context.requestCredDeleg(true);
351.115 + oneToken = context.initSecContext(new byte[0], 0, 0);
351.116 + }
351.117 +
351.118 + /**
351.119 + * Constructor
351.120 + * @throws java.io.IOException If negotiator cannot be constructed
351.121 + */
351.122 + public NegotiatorImpl(HttpCallerInfo hci) throws IOException {
351.123 + try {
351.124 + init(hci);
351.125 + } catch (GSSException e) {
351.126 + if (DEBUG) {
351.127 + System.out.println("Negotiate support not initiated, will " +
351.128 + "fallback to other scheme if allowed. Reason:");
351.129 + e.printStackTrace();
351.130 + }
351.131 + IOException ioe = new IOException("Negotiate support not initiated");
351.132 + ioe.initCause(e);
351.133 + throw ioe;
351.134 + }
351.135 + }
351.136 +
351.137 + /**
351.138 + * Return the first token of GSS, in SPNEGO, it's called NegTokenInit
351.139 + * @return the first token
351.140 + */
351.141 + @Override
351.142 + public byte[] firstToken() {
351.143 + return oneToken;
351.144 + }
351.145 +
351.146 + /**
351.147 + * Return the rest tokens of GSS, in SPNEGO, it's called NegTokenTarg
351.148 + * @param token the token received from server
351.149 + * @return the next token
351.150 + * @throws java.io.IOException if the token cannot be created successfully
351.151 + */
351.152 + @Override
351.153 + public byte[] nextToken(byte[] token) throws IOException {
351.154 + try {
351.155 + return context.initSecContext(token, 0, token.length);
351.156 + } catch (GSSException e) {
351.157 + if (DEBUG) {
351.158 + System.out.println("Negotiate support cannot continue. Reason:");
351.159 + e.printStackTrace();
351.160 + }
351.161 + IOException ioe = new IOException("Negotiate support cannot continue");
351.162 + ioe.initCause(e);
351.163 + throw ioe;
351.164 + }
351.165 + }
351.166 +}
352.1 --- a/src/share/classes/sun/net/www/protocol/https/HttpsClient.java Mon Nov 23 10:04:47 2009 +0000
352.2 +++ b/src/share/classes/sun/net/www/protocol/https/HttpsClient.java Wed Nov 25 11:08:25 2009 -0800
352.3 @@ -54,7 +54,6 @@
352.4 import java.security.AccessController;
352.5
352.6 import javax.security.auth.x500.X500Principal;
352.7 -import javax.security.auth.kerberos.KerberosPrincipal;
352.8
352.9 import javax.net.ssl.*;
352.10 import sun.security.x509.X500Name;
352.11 @@ -466,16 +465,14 @@
352.12 HostnameChecker checker = HostnameChecker.getInstance(
352.13 HostnameChecker.TYPE_TLS);
352.14
352.15 - Principal principal = getPeerPrincipal();
352.16 - // X.500 principal or Kerberos principal.
352.17 - // (Use ciphersuite check to determine whether Kerberos is present.)
352.18 - if (cipher.startsWith("TLS_KRB5") &&
352.19 - principal instanceof KerberosPrincipal) {
352.20 - if (!checker.match(host, (KerberosPrincipal)principal)) {
352.21 + // Use ciphersuite to determine whether Kerberos is present.
352.22 + if (cipher.startsWith("TLS_KRB5")) {
352.23 + if (!checker.match(host, getPeerPrincipal())) {
352.24 throw new SSLPeerUnverifiedException("Hostname checker" +
352.25 " failed for Kerberos");
352.26 }
352.27 - } else {
352.28 + } else { // X.509
352.29 +
352.30 // get the subject's certificate
352.31 peerCerts = session.getPeerCertificates();
352.32
353.1 --- a/src/share/classes/sun/reflect/misc/MethodUtil.java Mon Nov 23 10:04:47 2009 +0000
353.2 +++ b/src/share/classes/sun/reflect/misc/MethodUtil.java Wed Nov 25 11:08:25 2009 -0800
353.3 @@ -1,5 +1,5 @@
353.4 /*
353.5 - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
353.6 + * Copyright 2005-2009 Sun Microsystems, Inc. All Rights Reserved.
353.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
353.8 *
353.9 * This code is free software; you can redistribute it and/or modify it
353.10 @@ -44,6 +44,7 @@
353.11 import java.util.Collection;
353.12 import java.util.HashMap;
353.13 import java.util.Map;
353.14 +import sun.misc.IOUtils;
353.15 import sun.net.www.ParseUtil;
353.16 import sun.security.util.SecurityConstants;
353.17
353.18 @@ -373,34 +374,7 @@
353.19
353.20 byte[] b;
353.21 try {
353.22 - if (len != -1) {
353.23 - // Read exactly len bytes from the input stream
353.24 - b = new byte[len];
353.25 - while (len > 0) {
353.26 - int n = in.read(b, b.length - len, len);
353.27 - if (n == -1) {
353.28 - throw new IOException("unexpected EOF");
353.29 - }
353.30 - len -= n;
353.31 - }
353.32 - } else {
353.33 - b = new byte[8192];
353.34 - int total = 0;
353.35 - while ((len = in.read(b, total, b.length - total)) != -1) {
353.36 - total += len;
353.37 - if (total >= b.length) {
353.38 - byte[] tmp = new byte[total * 2];
353.39 - System.arraycopy(b, 0, tmp, 0, total);
353.40 - b = tmp;
353.41 - }
353.42 - }
353.43 - // Trim array to correct size, if necessary
353.44 - if (total != b.length) {
353.45 - byte[] tmp = new byte[total];
353.46 - System.arraycopy(b, 0, tmp, 0, total);
353.47 - b = tmp;
353.48 - }
353.49 - }
353.50 + b = IOUtils.readFully(in, len, true);
353.51 } finally {
353.52 in.close();
353.53 }
354.1 --- a/src/share/classes/sun/security/jca/Providers.java Mon Nov 23 10:04:47 2009 +0000
354.2 +++ b/src/share/classes/sun/security/jca/Providers.java Wed Nov 25 11:08:25 2009 -0800
354.3 @@ -1,5 +1,5 @@
354.4 /*
354.5 - * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
354.6 + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
354.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
354.8 *
354.9 * This code is free software; you can redistribute it and/or modify it
354.10 @@ -86,6 +86,9 @@
354.11 private static final String[] jarVerificationProviders = {
354.12 "sun.security.provider.Sun",
354.13 "sun.security.rsa.SunRsaSign",
354.14 + // Note: SunEC *is* in a signed JAR file, but it's not signed
354.15 + // by EC itself. So it's still safe to be listed here.
354.16 + "sun.security.ec.SunEC",
354.17 BACKUP_PROVIDER_CLASSNAME,
354.18 };
354.19
355.1 --- a/src/share/classes/sun/security/jgss/GSSUtil.java Mon Nov 23 10:04:47 2009 +0000
355.2 +++ b/src/share/classes/sun/security/jgss/GSSUtil.java Wed Nov 25 11:08:25 2009 -0800
355.3 @@ -237,7 +237,7 @@
355.4
355.5 CallbackHandler cb = null;
355.6 if (caller instanceof HttpCaller) {
355.7 - cb = new sun.net.www.protocol.http.NegotiateCallbackHandler(
355.8 + cb = new sun.net.www.protocol.http.spnego.NegotiateCallbackHandler(
355.9 ((HttpCaller)caller).info());
355.10 } else {
355.11 String defaultHandler =
356.1 --- a/src/share/classes/sun/security/krb5/EncryptionKey.java Mon Nov 23 10:04:47 2009 +0000
356.2 +++ b/src/share/classes/sun/security/krb5/EncryptionKey.java Wed Nov 25 11:08:25 2009 -0800
356.3 @@ -1,5 +1,5 @@
356.4 /*
356.5 - * Portions Copyright 2000-2007 Sun Microsystems, Inc. All Rights Reserved.
356.6 + * Portions Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
356.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
356.8 *
356.9 * This code is free software; you can redistribute it and/or modify it
356.10 @@ -503,7 +503,19 @@
356.11 + '\n'));
356.12 }
356.13
356.14 + /**
356.15 + * Find a key with given etype
356.16 + */
356.17 public static EncryptionKey findKey(int etype, EncryptionKey[] keys)
356.18 + throws KrbException {
356.19 + return findKey(etype, null, keys);
356.20 + }
356.21 +
356.22 + /**
356.23 + * Find a key with given etype and kvno
356.24 + * @param kvno if null, return any (first?) key
356.25 + */
356.26 + public static EncryptionKey findKey(int etype, Integer kvno, EncryptionKey[] keys)
356.27 throws KrbException {
356.28
356.29 // check if encryption type is supported
356.30 @@ -516,7 +528,8 @@
356.31 for (int i = 0; i < keys.length; i++) {
356.32 ktype = keys[i].getEType();
356.33 if (EType.isSupported(ktype)) {
356.34 - if (etype == ktype) {
356.35 + Integer kv = keys[i].getKeyVersionNumber();
356.36 + if (etype == ktype && (kvno == null || kvno.equals(kv))) {
356.37 return keys[i];
356.38 }
356.39 }
356.40 @@ -528,8 +541,11 @@
356.41 for (int i = 0; i < keys.length; i++) {
356.42 ktype = keys[i].getEType();
356.43 if (ktype == EncryptedData.ETYPE_DES_CBC_CRC ||
356.44 - ktype == EncryptedData.ETYPE_DES_CBC_MD5) {
356.45 - return new EncryptionKey(etype, keys[i].getBytes());
356.46 + ktype == EncryptedData.ETYPE_DES_CBC_MD5) {
356.47 + Integer kv = keys[i].getKeyVersionNumber();
356.48 + if (kvno == null || kvno.equals(kv)) {
356.49 + return new EncryptionKey(etype, keys[i].getBytes());
356.50 + }
356.51 }
356.52 }
356.53 }
357.1 --- a/src/share/classes/sun/security/krb5/KrbApReq.java Mon Nov 23 10:04:47 2009 +0000
357.2 +++ b/src/share/classes/sun/security/krb5/KrbApReq.java Wed Nov 25 11:08:25 2009 -0800
357.3 @@ -268,7 +268,8 @@
357.4 private void authenticate(EncryptionKey[] keys, InetAddress initiator)
357.5 throws KrbException, IOException {
357.6 int encPartKeyType = apReqMessg.ticket.encPart.getEType();
357.7 - EncryptionKey dkey = EncryptionKey.findKey(encPartKeyType, keys);
357.8 + Integer kvno = apReqMessg.ticket.encPart.getKeyVersionNumber();
357.9 + EncryptionKey dkey = EncryptionKey.findKey(encPartKeyType, kvno, keys);
357.10
357.11 if (dkey == null) {
357.12 throw new KrbException(Krb5.API_INVALID_ARG,
358.1 --- a/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Mon Nov 23 10:04:47 2009 +0000
358.2 +++ b/src/share/classes/sun/security/krb5/internal/ktab/KeyTab.java Wed Nov 25 11:08:25 2009 -0800
358.3 @@ -395,6 +395,28 @@
358.4 }
358.5 }
358.6
358.7 + /**
358.8 + * Only used by KDC test. This method can specify kvno and does not
358.9 + * remove any old keys.
358.10 + */
358.11 + public void addEntry(PrincipalName service, char[] psswd, int kvno)
358.12 + throws KrbException {
358.13 +
358.14 + EncryptionKey[] encKeys = EncryptionKey.acquireSecretKeys(
358.15 + psswd, service.getSalt());
358.16 +
358.17 + for (int i = 0; encKeys != null && i < encKeys.length; i++) {
358.18 + int keyType = encKeys[i].getEType();
358.19 + byte[] keyValue = encKeys[i].getBytes();
358.20 + KeyTabEntry newEntry = new KeyTabEntry(service,
358.21 + service.getRealm(),
358.22 + new KerberosTime(System.currentTimeMillis()),
358.23 + kvno, keyType, keyValue);
358.24 + if (entries == null)
358.25 + entries = new Vector<KeyTabEntry> ();
358.26 + entries.addElement(newEntry);
358.27 + }
358.28 + }
358.29
358.30 /**
358.31 * Retrieves the key table entry with the specified service name.
359.1 --- a/src/share/classes/sun/security/pkcs/SignerInfo.java Mon Nov 23 10:04:47 2009 +0000
359.2 +++ b/src/share/classes/sun/security/pkcs/SignerInfo.java Wed Nov 25 11:08:25 2009 -0800
359.3 @@ -1,5 +1,5 @@
359.4 /*
359.5 - * Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved.
359.6 + * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
359.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
359.8 *
359.9 * This code is free software; you can redistribute it and/or modify it
359.10 @@ -286,8 +286,6 @@
359.11 }
359.12
359.13 String digestAlgname = getDigestAlgorithmId().getName();
359.14 - if (digestAlgname.equalsIgnoreCase("SHA"))
359.15 - digestAlgname = "SHA1";
359.16
359.17 byte[] dataSigned;
359.18
359.19 @@ -337,9 +335,12 @@
359.20 String encryptionAlgname =
359.21 getDigestEncryptionAlgorithmId().getName();
359.22
359.23 - if (encryptionAlgname.equalsIgnoreCase("SHA1withDSA"))
359.24 - encryptionAlgname = "DSA";
359.25 - String algname = digestAlgname + "with" + encryptionAlgname;
359.26 + // Workaround: sometimes the encryptionAlgname is actually
359.27 + // a signature name
359.28 + String tmp = AlgorithmId.getEncAlgFromSigAlg(encryptionAlgname);
359.29 + if (tmp != null) encryptionAlgname = tmp;
359.30 + String algname = AlgorithmId.makeSigAlg(
359.31 + digestAlgname, encryptionAlgname);
359.32
359.33 Signature sig = Signature.getInstance(algname);
359.34 X509Certificate cert = getCertificate(block);
360.1 --- a/src/share/classes/sun/security/provider/SeedGenerator.java Mon Nov 23 10:04:47 2009 +0000
360.2 +++ b/src/share/classes/sun/security/provider/SeedGenerator.java Wed Nov 25 11:08:25 2009 -0800
360.3 @@ -63,13 +63,13 @@
360.4 * @author Gadi Guy
360.5 */
360.6
360.7 +import java.lang.reflect.Method;
360.8 +import java.lang.reflect.InvocationTargetException;
360.9 import java.security.*;
360.10 import java.io.*;
360.11 import java.util.Properties;
360.12 import java.util.Enumeration;
360.13 import java.net.*;
360.14 -import java.nio.file.DirectoryStream;
360.15 -import java.nio.file.Path;
360.16 import java.util.Random;
360.17 import sun.security.util.Debug;
360.18
360.19 @@ -183,26 +183,38 @@
360.20
360.21 // The temporary dir
360.22 File f = new File(p.getProperty("java.io.tmpdir"));
360.23 - int count = 0;
360.24 - DirectoryStream<Path> ds
360.25 - = f.toPath().newDirectoryStream();
360.26 - try {
360.27 +
360.28 + // Go thru files in the tmp dir using NIO's
360.29 + // DirectoryStream. Fallback to File.list()
360.30 + // if NIO is not available.
360.31 + if (NIODirectoryStream.isAvailable()) {
360.32 + int count = 0;
360.33 + Iterable<?> stream =
360.34 + NIODirectoryStream.newDirectoryStream(f);
360.35 // We use a Random object to choose what file names
360.36 // should be used. Otherwise on a machine with too
360.37 // many files, the same first 1024 files always get
360.38 // used. Any, We make sure the first 512 files are
360.39 // always used.
360.40 Random r = new Random();
360.41 - for (Path path: ds) {
360.42 - if (count < 512 || r.nextBoolean()) {
360.43 - md.update(path.getName().toString().getBytes());
360.44 + try {
360.45 + for (Object entry: stream) {
360.46 + if (count < 512 || r.nextBoolean()) {
360.47 + md.update(NIODirectoryStream.getName(
360.48 + entry).getBytes());
360.49 + }
360.50 + if (count++ > 1024) {
360.51 + break;
360.52 + }
360.53 }
360.54 - if (count++ > 1024) {
360.55 - break;
360.56 - }
360.57 + } finally {
360.58 + ((Closeable)stream).close();
360.59 }
360.60 - } finally {
360.61 - ds.close();
360.62 + } else {
360.63 + String[] sa = f.list();
360.64 + for(int i = 0; i < sa.length; i++) {
360.65 + md.update(sa[i].getBytes());
360.66 + }
360.67 }
360.68 } catch (Exception ex) {
360.69 md.update((byte)ex.hashCode());
360.70 @@ -505,4 +517,76 @@
360.71
360.72 }
360.73
360.74 + /**
360.75 + * A wrapper of NIO DirectoryStream using reflection.
360.76 + */
360.77 + private static class NIODirectoryStream {
360.78 + private static final Class<?> pathClass =
360.79 + getClass("java.nio.file.Path");
360.80 +
360.81 + private static final Method toPathMethod =
360.82 + (pathClass == null) ? null : getMethod(File.class, "toPath");
360.83 + private static final Method getNameMethod =
360.84 + getMethod(pathClass, "getName");
360.85 + private static final Method newDirectoryStreamMethod =
360.86 + getMethod(pathClass, "newDirectoryStream");
360.87 +
360.88 + private static Class<?> getClass(String name) {
360.89 + try {
360.90 + return Class.forName(name, true, null);
360.91 + } catch (ClassNotFoundException e) {
360.92 + return null;
360.93 + }
360.94 + }
360.95 +
360.96 + private static Method getMethod(Class<?> clazz,
360.97 + String name,
360.98 + Class<?>... paramTypes) {
360.99 + if (clazz != null) {
360.100 + try {
360.101 + return clazz.getMethod(name, paramTypes);
360.102 + } catch (NoSuchMethodException e) {
360.103 + throw new AssertionError(e);
360.104 + }
360.105 + } else {
360.106 + return null;
360.107 + }
360.108 + }
360.109 +
360.110 + static boolean isAvailable() {
360.111 + return pathClass != null;
360.112 + }
360.113 +
360.114 + static Iterable<?> newDirectoryStream(File dir) throws IOException {
360.115 + assert pathClass != null;
360.116 + try {
360.117 + Object path = toPathMethod.invoke(dir);
360.118 + return (Iterable<?>)newDirectoryStreamMethod.invoke(path);
360.119 + } catch (InvocationTargetException e) {
360.120 + Throwable cause = e.getCause();
360.121 + if (cause instanceof IOException)
360.122 + throw (IOException)cause;
360.123 + if (cause instanceof RuntimeException)
360.124 + throw (RuntimeException)cause;
360.125 + if (cause instanceof Error)
360.126 + throw (Error)cause;
360.127 + throw new AssertionError(e);
360.128 + } catch (IllegalAccessException iae) {
360.129 + throw new AssertionError(iae);
360.130 + }
360.131 + }
360.132 +
360.133 + static String getName(Object path) {
360.134 + assert pathClass != null;
360.135 + try {
360.136 + Object name = getNameMethod.invoke(path);
360.137 + return name.toString();
360.138 + } catch (InvocationTargetException e) {
360.139 + throw new AssertionError(e);
360.140 + } catch (IllegalAccessException iae) {
360.141 + throw new AssertionError(iae);
360.142 + }
360.143 + }
360.144 + }
360.145 }
360.146 +
361.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
361.2 +++ b/src/share/classes/sun/security/provider/certpath/AlgorithmChecker.java Wed Nov 25 11:08:25 2009 -0800
361.3 @@ -0,0 +1,119 @@
361.4 +/*
361.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
361.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
361.7 + *
361.8 + * This code is free software; you can redistribute it and/or modify it
361.9 + * under the terms of the GNU General Public License version 2 only, as
361.10 + * published by the Free Software Foundation. Sun designates this
361.11 + * particular file as subject to the "Classpath" exception as provided
361.12 + * by Sun in the LICENSE file that accompanied this code.
361.13 + *
361.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
361.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
361.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
361.17 + * version 2 for more details (a copy is included in the LICENSE file that
361.18 + * accompanied this code).
361.19 + *
361.20 + * You should have received a copy of the GNU General Public License version
361.21 + * 2 along with this work; if not, write to the Free Software Foundation,
361.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
361.23 + *
361.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
361.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
361.26 + * have any questions.
361.27 + */
361.28 +
361.29 +package sun.security.provider.certpath;
361.30 +
361.31 +import java.util.Set;
361.32 +import java.util.Collection;
361.33 +import java.util.Locale;
361.34 +import java.security.cert.Certificate;
361.35 +import java.security.cert.X509Certificate;
361.36 +import java.security.cert.X509CRL;
361.37 +import java.security.cert.CertPathValidatorException;
361.38 +import java.security.cert.PKIXCertPathChecker;
361.39 +
361.40 +import sun.security.x509.AlgorithmId;
361.41 +
361.42 +/**
361.43 + * AlgorithmChecker is a <code>PKIXCertPathChecker</code> that checks that
361.44 + * the signature algorithm of the specified certificate is not disabled.
361.45 + *
361.46 + * @author Xuelei Fan
361.47 + */
361.48 +final public class AlgorithmChecker extends PKIXCertPathChecker {
361.49 +
361.50 + // the disabled algorithms
361.51 + private static final String[] disabledAlgorithms = new String[] {"md2"};
361.52 +
361.53 + // singleton instance
361.54 + static final AlgorithmChecker INSTANCE = new AlgorithmChecker();
361.55 +
361.56 + /**
361.57 + * Default Constructor
361.58 + */
361.59 + private AlgorithmChecker() {
361.60 + // do nothing
361.61 + }
361.62 +
361.63 + /**
361.64 + * Return a AlgorithmChecker instance.
361.65 + */
361.66 + static AlgorithmChecker getInstance() {
361.67 + return INSTANCE;
361.68 + }
361.69 +
361.70 + /**
361.71 + * Initializes the internal state of the checker from parameters
361.72 + * specified in the constructor.
361.73 + */
361.74 + public void init(boolean forward) throws CertPathValidatorException {
361.75 + // do nothing
361.76 + }
361.77 +
361.78 + public boolean isForwardCheckingSupported() {
361.79 + return false;
361.80 + }
361.81 +
361.82 + public Set<String> getSupportedExtensions() {
361.83 + return null;
361.84 + }
361.85 +
361.86 + /**
361.87 + * Checks the signature algorithm of the specified certificate.
361.88 + */
361.89 + public void check(Certificate cert, Collection<String> unresolvedCritExts)
361.90 + throws CertPathValidatorException {
361.91 + check(cert);
361.92 + }
361.93 +
361.94 + public static void check(Certificate cert)
361.95 + throws CertPathValidatorException {
361.96 + X509Certificate xcert = (X509Certificate)cert;
361.97 + check(xcert.getSigAlgName());
361.98 + }
361.99 +
361.100 + static void check(AlgorithmId aid) throws CertPathValidatorException {
361.101 + check(aid.getName());
361.102 + }
361.103 +
361.104 + static void check(X509CRL crl) throws CertPathValidatorException {
361.105 + check(crl.getSigAlgName());
361.106 + }
361.107 +
361.108 + private static void check(String algName)
361.109 + throws CertPathValidatorException {
361.110 +
361.111 + String lowerCaseAlgName = algName.toLowerCase(Locale.ENGLISH);
361.112 +
361.113 + for (String disabled : disabledAlgorithms) {
361.114 + // checking the signature algorithm name
361.115 + if (lowerCaseAlgName.indexOf(disabled) != -1) {
361.116 + throw new CertPathValidatorException(
361.117 + "algorithm check failed: " + algName + " is disabled");
361.118 + }
361.119 + }
361.120 + }
361.121 +
361.122 +}
362.1 --- a/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java Mon Nov 23 10:04:47 2009 +0000
362.2 +++ b/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java Wed Nov 25 11:08:25 2009 -0800
362.3 @@ -289,6 +289,16 @@
362.4 X500Name certIssuer = (X500Name) certImpl.getIssuerDN();
362.5 X500Name crlIssuer = (X500Name) crlImpl.getIssuerDN();
362.6
362.7 + // check the crl signature algorithm
362.8 + try {
362.9 + AlgorithmChecker.check(crl);
362.10 + } catch (CertPathValidatorException cpve) {
362.11 + if (debug != null) {
362.12 + debug.println("CRL signature algorithm check failed: " + cpve);
362.13 + }
362.14 + return false;
362.15 + }
362.16 +
362.17 // if crlIssuer is set, verify that it matches the issuer of the
362.18 // CRL and the CRL contains an IDP extension with the indirectCRL
362.19 // boolean asserted. Otherwise, verify that the CRL issuer matches the
363.1 --- a/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java Mon Nov 23 10:04:47 2009 +0000
363.2 +++ b/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java Wed Nov 25 11:08:25 2009 -0800
363.3 @@ -719,6 +719,11 @@
363.4 /* we don't perform any validation of the trusted cert */
363.5 if (!isTrustedCert) {
363.6 /*
363.7 + * check that the signature algorithm is not disabled.
363.8 + */
363.9 + AlgorithmChecker.check(cert);
363.10 +
363.11 + /*
363.12 * Check CRITICAL private extensions for user checkers that
363.13 * support forward checking (forwardCheckers) and remove
363.14 * ones we know how to check.
364.1 --- a/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java Mon Nov 23 10:04:47 2009 +0000
364.2 +++ b/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java Wed Nov 25 11:08:25 2009 -0800
364.3 @@ -275,6 +275,7 @@
364.4 int certPathLen = certList.size();
364.5
364.6 basicChecker = new BasicChecker(anchor, testDate, sigProvider, false);
364.7 + AlgorithmChecker algorithmChecker= AlgorithmChecker.getInstance();
364.8 KeyChecker keyChecker = new KeyChecker(certPathLen,
364.9 pkixParam.getTargetCertConstraints());
364.10 ConstraintsChecker constraintsChecker =
364.11 @@ -291,6 +292,7 @@
364.12 ArrayList<PKIXCertPathChecker> certPathCheckers =
364.13 new ArrayList<PKIXCertPathChecker>();
364.14 // add standard checkers that we will be using
364.15 + certPathCheckers.add(algorithmChecker);
364.16 certPathCheckers.add(keyChecker);
364.17 certPathCheckers.add(constraintsChecker);
364.18 certPathCheckers.add(policyChecker);
365.1 --- a/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java Mon Nov 23 10:04:47 2009 +0000
365.2 +++ b/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java Wed Nov 25 11:08:25 2009 -0800
365.3 @@ -1,5 +1,5 @@
365.4 /*
365.5 - * Copyright 2000-2008 Sun Microsystems, Inc. All Rights Reserved.
365.6 + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
365.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
365.8 *
365.9 * This code is free software; you can redistribute it and/or modify it
365.10 @@ -347,6 +347,9 @@
365.11 return;
365.12 }
365.13
365.14 + /* check that the signature algorithm is not disabled. */
365.15 + AlgorithmChecker.check(cert);
365.16 +
365.17 /*
365.18 * check for looping - abort a loop if
365.19 * ((we encounter the same certificate twice) AND
366.1 --- a/src/share/classes/sun/security/ssl/CipherSuite.java Mon Nov 23 10:04:47 2009 +0000
366.2 +++ b/src/share/classes/sun/security/ssl/CipherSuite.java Wed Nov 25 11:08:25 2009 -0800
366.3 @@ -74,7 +74,7 @@
366.4 // Flag indicating if CipherSuite availability can change dynamically.
366.5 // This is the case when we rely on a JCE cipher implementation that
366.6 // may not be available in the installed JCE providers.
366.7 - // It is true because we might not have an ECC or Kerberos implementation.
366.8 + // It is true because we might not have an ECC implementation.
366.9 final static boolean DYNAMIC_AVAILABILITY = true;
366.10
366.11 private final static boolean ALLOW_ECC = Debug.getBooleanProperty
367.1 --- a/src/share/classes/sun/security/ssl/ClientHandshaker.java Mon Nov 23 10:04:47 2009 +0000
367.2 +++ b/src/share/classes/sun/security/ssl/ClientHandshaker.java Wed Nov 25 11:08:25 2009 -0800
367.3 @@ -44,9 +44,6 @@
367.4 import javax.net.ssl.*;
367.5
367.6 import javax.security.auth.Subject;
367.7 -import javax.security.auth.kerberos.KerberosPrincipal;
367.8 -import sun.security.jgss.krb5.Krb5Util;
367.9 -import sun.security.jgss.GSSCaller;
367.10
367.11 import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
367.12
367.13 @@ -362,9 +359,7 @@
367.14 subject = AccessController.doPrivileged(
367.15 new PrivilegedExceptionAction<Subject>() {
367.16 public Subject run() throws Exception {
367.17 - return Krb5Util.getSubject(
367.18 - GSSCaller.CALLER_SSL_CLIENT,
367.19 - getAccSE());
367.20 + return Krb5Helper.getClientSubject(getAccSE());
367.21 }});
367.22 } catch (PrivilegedActionException e) {
367.23 subject = null;
367.24 @@ -375,8 +370,9 @@
367.25 }
367.26
367.27 if (subject != null) {
367.28 - Set<KerberosPrincipal> principals =
367.29 - subject.getPrincipals(KerberosPrincipal.class);
367.30 + // Eliminate dependency on KerberosPrincipal
367.31 + Set<Principal> principals =
367.32 + subject.getPrincipals(Principal.class);
367.33 if (!principals.contains(localPrincipal)) {
367.34 throw new SSLProtocolException("Server resumed" +
367.35 " session with wrong subject identity");
367.36 @@ -754,7 +750,7 @@
367.37 case K_KRB5:
367.38 case K_KRB5_EXPORT:
367.39 byte[] secretBytes =
367.40 - ((KerberosClientKeyExchange)m2).getPreMasterSecret().getUnencrypted();
367.41 + ((KerberosClientKeyExchange)m2).getUnencryptedPreMasterSecret();
367.42 preMasterSecret = new SecretKeySpec(secretBytes, "TlsPremasterSecret");
367.43 break;
367.44 case K_DHE_RSA:
368.1 --- a/src/share/classes/sun/security/ssl/Debug.java Mon Nov 23 10:04:47 2009 +0000
368.2 +++ b/src/share/classes/sun/security/ssl/Debug.java Wed Nov 25 11:08:25 2009 -0800
368.3 @@ -1,5 +1,5 @@
368.4 /*
368.5 - * Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
368.6 + * Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
368.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
368.8 *
368.9 * This code is free software; you can redistribute it and/or modify it
368.10 @@ -160,7 +160,7 @@
368.11 System.err.println(prefix + ": "+message);
368.12 }
368.13
368.14 - static void println(PrintStream s, String name, byte[] data) {
368.15 + public static void println(PrintStream s, String name, byte[] data) {
368.16 s.print(name + ": { ");
368.17 if (data == null) {
368.18 s.print("null");
369.1 --- a/src/share/classes/sun/security/ssl/HandshakeInStream.java Mon Nov 23 10:04:47 2009 +0000
369.2 +++ b/src/share/classes/sun/security/ssl/HandshakeInStream.java Wed Nov 25 11:08:25 2009 -0800
369.3 @@ -1,5 +1,5 @@
369.4 /*
369.5 - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved.
369.6 + * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
369.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
369.8 *
369.9 * This code is free software; you can redistribute it and/or modify it
369.10 @@ -52,7 +52,7 @@
369.11 *
369.12 * @author David Brownell
369.13 */
369.14 -class HandshakeInStream extends InputStream {
369.15 +public class HandshakeInStream extends InputStream {
369.16
369.17 InputRecord r;
369.18
369.19 @@ -196,7 +196,7 @@
369.20 return b;
369.21 }
369.22
369.23 - byte[] getBytes16() throws IOException {
369.24 + public byte[] getBytes16() throws IOException {
369.25 int len = getInt16();
369.26 byte b[] = new byte[len];
369.27
370.1 --- a/src/share/classes/sun/security/ssl/HandshakeMessage.java Mon Nov 23 10:04:47 2009 +0000
370.2 +++ b/src/share/classes/sun/security/ssl/HandshakeMessage.java Wed Nov 25 11:08:25 2009 -0800
370.3 @@ -1,5 +1,5 @@
370.4 /*
370.5 - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved.
370.6 + * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
370.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
370.8 *
370.9 * This code is free software; you can redistribute it and/or modify it
370.10 @@ -23,7 +23,6 @@
370.11 * have any questions.
370.12 */
370.13
370.14 -
370.15 package sun.security.ssl;
370.16
370.17 import java.io.*;
370.18 @@ -73,7 +72,7 @@
370.19 *
370.20 * @author David Brownell
370.21 */
370.22 -abstract class HandshakeMessage {
370.23 +public abstract class HandshakeMessage {
370.24
370.25 HandshakeMessage() { }
370.26
370.27 @@ -92,7 +91,7 @@
370.28 static final byte ht_finished = 20;
370.29
370.30 /* Class and subclass dynamic debugging support */
370.31 - static final Debug debug = Debug.getInstance("ssl");
370.32 + public static final Debug debug = Debug.getInstance("ssl");
370.33
370.34 /**
370.35 * Utility method to convert a BigInteger to a byte array in unsigned
370.36 @@ -468,7 +467,6 @@
370.37 }
370.38 }
370.39
370.40 -
370.41 /*
370.42 * ServerKeyExchange ... SERVER --> CLIENT
370.43 *
371.1 --- a/src/share/classes/sun/security/ssl/HandshakeOutStream.java Mon Nov 23 10:04:47 2009 +0000
371.2 +++ b/src/share/classes/sun/security/ssl/HandshakeOutStream.java Wed Nov 25 11:08:25 2009 -0800
371.3 @@ -1,5 +1,5 @@
371.4 /*
371.5 - * Copyright 1996-2007 Sun Microsystems, Inc. All Rights Reserved.
371.6 + * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
371.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
371.8 *
371.9 * This code is free software; you can redistribute it and/or modify it
371.10 @@ -41,7 +41,7 @@
371.11 *
371.12 * @author David Brownell
371.13 */
371.14 -class HandshakeOutStream extends OutputStream {
371.15 +public class HandshakeOutStream extends OutputStream {
371.16
371.17 private SSLSocketImpl socket;
371.18 private SSLEngineImpl engine;
371.19 @@ -196,7 +196,7 @@
371.20 write(b, 0, b.length);
371.21 }
371.22
371.23 - void putBytes16(byte b[]) throws IOException {
371.24 + public void putBytes16(byte b[]) throws IOException {
371.25 if (b == null) {
371.26 putInt16(0);
371.27 return;
372.1 --- a/src/share/classes/sun/security/ssl/KerberosClientKeyExchange.java Mon Nov 23 10:04:47 2009 +0000
372.2 +++ b/src/share/classes/sun/security/ssl/KerberosClientKeyExchange.java Wed Nov 25 11:08:25 2009 -0800
372.3 @@ -29,199 +29,67 @@
372.4 import java.io.PrintStream;
372.5 import java.security.AccessController;
372.6 import java.security.AccessControlContext;
372.7 -import java.security.PrivilegedExceptionAction;
372.8 -import java.security.PrivilegedActionException;
372.9 +import java.security.Principal;
372.10 +import java.security.PrivilegedAction;
372.11 import java.security.SecureRandom;
372.12 -import java.net.InetAddress;
372.13 -
372.14 -import javax.security.auth.kerberos.KerberosTicket;
372.15 -import javax.security.auth.kerberos.KerberosKey;
372.16 -import javax.security.auth.kerberos.KerberosPrincipal;
372.17 -import javax.security.auth.kerberos.ServicePermission;
372.18 -import sun.security.jgss.GSSCaller;
372.19 -
372.20 -import sun.security.krb5.EncryptionKey;
372.21 -import sun.security.krb5.EncryptedData;
372.22 -import sun.security.krb5.PrincipalName;
372.23 -import sun.security.krb5.Realm;
372.24 -import sun.security.krb5.internal.Ticket;
372.25 -import sun.security.krb5.internal.EncTicketPart;
372.26 -import sun.security.krb5.internal.crypto.KeyUsage;
372.27 -
372.28 -import sun.security.jgss.krb5.Krb5Util;
372.29 +import javax.crypto.SecretKey;
372.30
372.31 /**
372.32 - * This is Kerberos option in the client key exchange message
372.33 - * (CLIENT -> SERVER). It holds the Kerberos ticket and the encrypted
372.34 - * premaster secret encrypted with the session key sealed in the ticket.
372.35 - * From RFC 2712:
372.36 - * struct
372.37 - * {
372.38 - * opaque Ticket;
372.39 - * opaque authenticator; // optional
372.40 - * opaque EncryptedPreMasterSecret; // encrypted with the session key
372.41 - * // which is sealed in the ticket
372.42 - * } KerberosWrapper;
372.43 - *
372.44 - *
372.45 - * Ticket and authenticator are encrypted as per RFC 1510 (in ASN.1)
372.46 - * Encrypted pre-master secret has the same structure as it does for RSA
372.47 - * except for Kerberos, the encryption key is the session key instead of
372.48 - * the RSA public key.
372.49 - *
372.50 - * XXX authenticator currently ignored
372.51 - *
372.52 + * A helper class that calls the KerberosClientKeyExchange implementation.
372.53 */
372.54 -final class KerberosClientKeyExchange extends HandshakeMessage {
372.55 +public class KerberosClientKeyExchange extends HandshakeMessage {
372.56
372.57 - private KerberosPreMasterSecret preMaster;
372.58 - private byte[] encodedTicket;
372.59 - private KerberosPrincipal peerPrincipal;
372.60 - private KerberosPrincipal localPrincipal;
372.61 + private static final String IMPL_CLASS =
372.62 + "sun.security.ssl.krb5.KerberosClientKeyExchangeImpl";
372.63
372.64 - /**
372.65 - * Creates an instance of KerberosClientKeyExchange consisting of the
372.66 - * Kerberos service ticket, authenticator and encrypted premaster secret.
372.67 - * Called by client handshaker.
372.68 - *
372.69 - * @param serverName name of server with which to do handshake;
372.70 - * this is used to get the Kerberos service ticket
372.71 - * @param protocolVersion Maximum version supported by client (i.e,
372.72 - * version it requested in client hello)
372.73 - * @param rand random number generator to use for generating pre-master
372.74 - * secret
372.75 - */
372.76 - KerberosClientKeyExchange(String serverName, boolean isLoopback,
372.77 + private static final Class<?> implClass = AccessController.doPrivileged(
372.78 + new PrivilegedAction<Class<?>>() {
372.79 + public Class<?> run() {
372.80 + try {
372.81 + return Class.forName(IMPL_CLASS, true, null);
372.82 + } catch (ClassNotFoundException cnf) {
372.83 + return null;
372.84 + }
372.85 + }
372.86 + }
372.87 + );
372.88 + private final KerberosClientKeyExchange impl = createImpl();
372.89 +
372.90 + private KerberosClientKeyExchange createImpl() {
372.91 + if (getClass() == KerberosClientKeyExchange.class) {
372.92 + try {
372.93 + return (KerberosClientKeyExchange)implClass.newInstance();
372.94 + } catch (InstantiationException e) {
372.95 + throw new AssertionError(e);
372.96 + } catch (IllegalAccessException e) {
372.97 + throw new AssertionError(e);
372.98 + }
372.99 + }
372.100 + return null;
372.101 + }
372.102 +
372.103 + public KerberosClientKeyExchange() {
372.104 + }
372.105 +
372.106 + public KerberosClientKeyExchange(String serverName, boolean isLoopback,
372.107 AccessControlContext acc, ProtocolVersion protocolVersion,
372.108 SecureRandom rand) throws IOException {
372.109
372.110 - // Get service ticket
372.111 - KerberosTicket ticket = getServiceTicket(serverName, isLoopback, acc);
372.112 - encodedTicket = ticket.getEncoded();
372.113 -
372.114 - // Record the Kerberos principals
372.115 - peerPrincipal = ticket.getServer();
372.116 - localPrincipal = ticket.getClient();
372.117 -
372.118 - // Optional authenticator, encrypted using session key,
372.119 - // currently ignored
372.120 -
372.121 - // Generate premaster secret and encrypt it using session key
372.122 - EncryptionKey sessionKey = new EncryptionKey(
372.123 - ticket.getSessionKeyType(),
372.124 - ticket.getSessionKey().getEncoded());
372.125 -
372.126 - preMaster = new KerberosPreMasterSecret(protocolVersion,
372.127 - rand, sessionKey);
372.128 + if (impl != null) {
372.129 + init(serverName, isLoopback, acc, protocolVersion, rand);
372.130 + } else {
372.131 + throw new IllegalStateException("Kerberos is unavailable");
372.132 + }
372.133 }
372.134
372.135 - /**
372.136 - * Creates an instance of KerberosClientKeyExchange from its ASN.1 encoding.
372.137 - * Used by ServerHandshaker to verify and obtain premaster secret.
372.138 - *
372.139 - * @param protocolVersion current protocol version
372.140 - * @param clientVersion version requested by client in its ClientHello;
372.141 - * used by premaster secret version check
372.142 - * @param rand random number generator used for generating random
372.143 - * premaster secret if ticket and/or premaster verification fails
372.144 - * @param input inputstream from which to get ASN.1-encoded KerberosWrapper
372.145 - * @param serverKey server's master secret key
372.146 - */
372.147 - KerberosClientKeyExchange(ProtocolVersion protocolVersion,
372.148 - ProtocolVersion clientVersion,
372.149 - SecureRandom rand, HandshakeInStream input, KerberosKey[] serverKeys)
372.150 - throws IOException {
372.151 + public KerberosClientKeyExchange(ProtocolVersion protocolVersion,
372.152 + ProtocolVersion clientVersion, SecureRandom rand,
372.153 + HandshakeInStream input, SecretKey[] serverKeys) throws IOException {
372.154
372.155 - // Read ticket
372.156 - encodedTicket = input.getBytes16();
372.157 -
372.158 - if (debug != null && Debug.isOn("verbose")) {
372.159 - Debug.println(System.out,
372.160 - "encoded Kerberos service ticket", encodedTicket);
372.161 - }
372.162 -
372.163 - EncryptionKey sessionKey = null;
372.164 -
372.165 - try {
372.166 - Ticket t = new Ticket(encodedTicket);
372.167 -
372.168 - EncryptedData encPart = t.encPart;
372.169 - PrincipalName ticketSname = t.sname;
372.170 - Realm ticketRealm = t.realm;
372.171 -
372.172 - String serverPrincipal = serverKeys[0].getPrincipal().getName();
372.173 -
372.174 - /*
372.175 - * permission to access and use the secret key of the Kerberized
372.176 - * "host" service is done in ServerHandshaker.getKerberosKeys()
372.177 - * to ensure server has the permission to use the secret key
372.178 - * before promising the client
372.179 - */
372.180 -
372.181 - // Check that ticket Sname matches serverPrincipal
372.182 - String ticketPrinc = ticketSname.toString().concat("@" +
372.183 - ticketRealm.toString());
372.184 - if (!ticketPrinc.equals(serverPrincipal)) {
372.185 - if (debug != null && Debug.isOn("handshake"))
372.186 - System.out.println("Service principal in Ticket does not"
372.187 - + " match associated principal in KerberosKey");
372.188 - throw new IOException("Server principal is " +
372.189 - serverPrincipal + " but ticket is for " +
372.190 - ticketPrinc);
372.191 - }
372.192 -
372.193 - // See if we have the right key to decrypt the ticket to get
372.194 - // the session key.
372.195 - int encPartKeyType = encPart.getEType();
372.196 - KerberosKey dkey = findKey(encPartKeyType, serverKeys);
372.197 - if (dkey == null) {
372.198 - // %%% Should print string repr of etype
372.199 - throw new IOException(
372.200 - "Cannot find key of appropriate type to decrypt ticket - need etype " +
372.201 - encPartKeyType);
372.202 - }
372.203 -
372.204 - EncryptionKey secretKey = new EncryptionKey(
372.205 - encPartKeyType,
372.206 - dkey.getEncoded());
372.207 -
372.208 - // Decrypt encPart using server's secret key
372.209 - byte[] bytes = encPart.decrypt(secretKey, KeyUsage.KU_TICKET);
372.210 -
372.211 - // Reset data stream after decryption, remove redundant bytes
372.212 - byte[] temp = encPart.reset(bytes, true);
372.213 - EncTicketPart encTicketPart = new EncTicketPart(temp);
372.214 -
372.215 - // Record the Kerberos Principals
372.216 - peerPrincipal =
372.217 - new KerberosPrincipal(encTicketPart.cname.getName());
372.218 - localPrincipal = new KerberosPrincipal(ticketSname.getName());
372.219 -
372.220 - sessionKey = encTicketPart.key;
372.221 -
372.222 - if (debug != null && Debug.isOn("handshake")) {
372.223 - System.out.println("server principal: " + serverPrincipal);
372.224 - System.out.println("realm: " + encTicketPart.crealm.toString());
372.225 - System.out.println("cname: " + encTicketPart.cname.toString());
372.226 - }
372.227 - } catch (IOException e) {
372.228 - throw e;
372.229 - } catch (Exception e) {
372.230 - if (debug != null && Debug.isOn("handshake")) {
372.231 - System.out.println("KerberosWrapper error getting session key,"
372.232 - + " generating random secret (" + e.getMessage() + ")");
372.233 - }
372.234 - sessionKey = null;
372.235 - }
372.236 -
372.237 - input.getBytes16(); // XXX Read and ignore authenticator
372.238 -
372.239 - if (sessionKey != null) {
372.240 - preMaster = new KerberosPreMasterSecret(protocolVersion,
372.241 - clientVersion, rand, input, sessionKey);
372.242 + if (impl != null) {
372.243 + init(protocolVersion, clientVersion, rand, input, serverKeys);
372.244 } else {
372.245 - // Generate bogus premaster secret
372.246 - preMaster = new KerberosPreMasterSecret(protocolVersion, rand);
372.247 + throw new IllegalStateException("Kerberos is unavailable");
372.248 }
372.249 }
372.250
372.251 @@ -229,138 +97,46 @@
372.252 return ht_client_key_exchange;
372.253 }
372.254
372.255 - int messageLength() {
372.256 - return (6 + encodedTicket.length + preMaster.getEncrypted().length);
372.257 + public int messageLength() {
372.258 + return impl.messageLength();
372.259 }
372.260
372.261 - void send(HandshakeOutStream s) throws IOException {
372.262 - s.putBytes16(encodedTicket);
372.263 - s.putBytes16(null); // XXX no authenticator
372.264 - s.putBytes16(preMaster.getEncrypted());
372.265 + public void send(HandshakeOutStream s) throws IOException {
372.266 + impl.send(s);
372.267 }
372.268
372.269 - void print(PrintStream s) throws IOException {
372.270 - s.println("*** ClientKeyExchange, Kerberos");
372.271 + @Override
372.272 + public void print(PrintStream p) throws IOException {
372.273 + impl.print(p);
372.274 + }
372.275
372.276 - if (debug != null && Debug.isOn("verbose")) {
372.277 - Debug.println(s, "Kerberos service ticket", encodedTicket);
372.278 - Debug.println(s, "Random Secret", preMaster.getUnencrypted());
372.279 - Debug.println(s, "Encrypted random Secret",
372.280 - preMaster.getEncrypted());
372.281 + public void init(String serverName, boolean isLoopback,
372.282 + AccessControlContext acc, ProtocolVersion protocolVersion,
372.283 + SecureRandom rand) throws IOException {
372.284 +
372.285 + if (impl != null) {
372.286 + impl.init(serverName, isLoopback, acc, protocolVersion, rand);
372.287 }
372.288 }
372.289
372.290 - // Similar to sun.security.jgss.krb5.Krb5InitCredenetial/Krb5Context
372.291 - private static KerberosTicket getServiceTicket(String srvName,
372.292 - boolean isLoopback, final AccessControlContext acc) throws IOException {
372.293 + public void init(ProtocolVersion protocolVersion,
372.294 + ProtocolVersion clientVersion, SecureRandom rand,
372.295 + HandshakeInStream input, SecretKey[] serverKeys) throws IOException {
372.296
372.297 - // get the local hostname if srvName is loopback address
372.298 - String serverName = srvName;
372.299 - if (isLoopback) {
372.300 - String localHost = java.security.AccessController.doPrivileged(
372.301 - new java.security.PrivilegedAction<String>() {
372.302 - public String run() {
372.303 - String hostname;
372.304 - try {
372.305 - hostname = InetAddress.getLocalHost().getHostName();
372.306 - } catch (java.net.UnknownHostException e) {
372.307 - hostname = "localhost";
372.308 - }
372.309 - return hostname;
372.310 - }
372.311 - });
372.312 - serverName = localHost;
372.313 - }
372.314 -
372.315 - // Resolve serverName (possibly in IP addr form) to Kerberos principal
372.316 - // name for service with hostname
372.317 - String serviceName = "host/" + serverName;
372.318 - PrincipalName principal;
372.319 - try {
372.320 - principal = new PrincipalName(serviceName,
372.321 - PrincipalName.KRB_NT_SRV_HST);
372.322 - } catch (SecurityException se) {
372.323 - throw se;
372.324 - } catch (Exception e) {
372.325 - IOException ioe = new IOException("Invalid service principal" +
372.326 - " name: " + serviceName);
372.327 - ioe.initCause(e);
372.328 - throw ioe;
372.329 - }
372.330 - String realm = principal.getRealmAsString();
372.331 -
372.332 - final String serverPrincipal = principal.toString();
372.333 - final String tgsPrincipal = "krbtgt/" + realm + "@" + realm;
372.334 - final String clientPrincipal = null; // use default
372.335 -
372.336 -
372.337 - // check permission to obtain a service ticket to initiate a
372.338 - // context with the "host" service
372.339 - SecurityManager sm = System.getSecurityManager();
372.340 - if (sm != null) {
372.341 - sm.checkPermission(new ServicePermission(serverPrincipal,
372.342 - "initiate"), acc);
372.343 - }
372.344 -
372.345 - try {
372.346 - KerberosTicket ticket = AccessController.doPrivileged(
372.347 - new PrivilegedExceptionAction<KerberosTicket>() {
372.348 - public KerberosTicket run() throws Exception {
372.349 - return Krb5Util.getTicketFromSubjectAndTgs(
372.350 - GSSCaller.CALLER_SSL_CLIENT,
372.351 - clientPrincipal, serverPrincipal,
372.352 - tgsPrincipal, acc);
372.353 - }});
372.354 -
372.355 - if (ticket == null) {
372.356 - throw new IOException("Failed to find any kerberos service" +
372.357 - " ticket for " + serverPrincipal);
372.358 - }
372.359 - return ticket;
372.360 - } catch (PrivilegedActionException e) {
372.361 - IOException ioe = new IOException(
372.362 - "Attempt to obtain kerberos service ticket for " +
372.363 - serverPrincipal + " failed!");
372.364 - ioe.initCause(e);
372.365 - throw ioe;
372.366 + if (impl != null) {
372.367 + impl.init(protocolVersion, clientVersion, rand, input, serverKeys);
372.368 }
372.369 }
372.370
372.371 - KerberosPreMasterSecret getPreMasterSecret() {
372.372 - return preMaster;
372.373 + public byte[] getUnencryptedPreMasterSecret() {
372.374 + return impl.getUnencryptedPreMasterSecret();
372.375 }
372.376
372.377 - KerberosPrincipal getPeerPrincipal() {
372.378 - return peerPrincipal;
372.379 + public Principal getPeerPrincipal(){
372.380 + return impl.getPeerPrincipal();
372.381 }
372.382
372.383 - KerberosPrincipal getLocalPrincipal() {
372.384 - return localPrincipal;
372.385 - }
372.386 -
372.387 - private static KerberosKey findKey(int etype, KerberosKey[] keys) {
372.388 - int ktype;
372.389 - for (int i = 0; i < keys.length; i++) {
372.390 - ktype = keys[i].getKeyType();
372.391 - if (etype == ktype) {
372.392 - return keys[i];
372.393 - }
372.394 - }
372.395 - // Key not found.
372.396 - // %%% kludge to allow DES keys to be used for diff etypes
372.397 - if ((etype == EncryptedData.ETYPE_DES_CBC_CRC ||
372.398 - etype == EncryptedData.ETYPE_DES_CBC_MD5)) {
372.399 - for (int i = 0; i < keys.length; i++) {
372.400 - ktype = keys[i].getKeyType();
372.401 - if (ktype == EncryptedData.ETYPE_DES_CBC_CRC ||
372.402 - ktype == EncryptedData.ETYPE_DES_CBC_MD5) {
372.403 - return new KerberosKey(keys[i].getPrincipal(),
372.404 - keys[i].getEncoded(),
372.405 - etype,
372.406 - keys[i].getVersionNumber());
372.407 - }
372.408 - }
372.409 - }
372.410 - return null;
372.411 + public Principal getLocalPrincipal(){
372.412 + return impl.getLocalPrincipal();
372.413 }
372.414 }
373.1 --- a/src/share/classes/sun/security/ssl/KerberosPreMasterSecret.java Mon Nov 23 10:04:47 2009 +0000
373.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
373.3 @@ -1,223 +0,0 @@
373.4 -/*
373.5 - * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
373.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
373.7 - *
373.8 - * This code is free software; you can redistribute it and/or modify it
373.9 - * under the terms of the GNU General Public License version 2 only, as
373.10 - * published by the Free Software Foundation. Sun designates this
373.11 - * particular file as subject to the "Classpath" exception as provided
373.12 - * by Sun in the LICENSE file that accompanied this code.
373.13 - *
373.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
373.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
373.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
373.17 - * version 2 for more details (a copy is included in the LICENSE file that
373.18 - * accompanied this code).
373.19 - *
373.20 - * You should have received a copy of the GNU General Public License version
373.21 - * 2 along with this work; if not, write to the Free Software Foundation,
373.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
373.23 - *
373.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
373.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
373.26 - * have any questions.
373.27 - */
373.28 -
373.29 -package sun.security.ssl;
373.30 -
373.31 -import java.io.*;
373.32 -import java.security.*;
373.33 -import java.security.interfaces.*;
373.34 -
373.35 -import javax.net.ssl.*;
373.36 -
373.37 -import sun.security.krb5.EncryptionKey;
373.38 -import sun.security.krb5.EncryptedData;
373.39 -import sun.security.krb5.KrbException;
373.40 -import sun.security.krb5.internal.crypto.KeyUsage;
373.41 -
373.42 -/**
373.43 - * This is the Kerberos premaster secret in the Kerberos client key
373.44 - * exchange message (CLIENT --> SERVER); it holds the
373.45 - * Kerberos-encrypted pre-master secret. The secret is encrypted using the
373.46 - * Kerberos session key. The padding and size of the resulting message
373.47 - * depends on the session key type, but the pre-master secret is
373.48 - * always exactly 48 bytes.
373.49 - *
373.50 - */
373.51 -final class KerberosPreMasterSecret {
373.52 -
373.53 - private ProtocolVersion protocolVersion; // preMaster [0,1]
373.54 - private byte preMaster[]; // 48 bytes
373.55 - private byte encrypted[];
373.56 -
373.57 - /**
373.58 - * Constructor used by client to generate premaster secret.
373.59 - *
373.60 - * Client randomly creates a pre-master secret and encrypts it
373.61 - * using the Kerberos session key; only the server can decrypt
373.62 - * it, using the session key available in the service ticket.
373.63 - *
373.64 - * @param protocolVersion used to set preMaster[0,1]
373.65 - * @param generator random number generator for generating premaster secret
373.66 - * @param sessionKey Kerberos session key for encrypting premaster secret
373.67 - */
373.68 - KerberosPreMasterSecret(ProtocolVersion protocolVersion,
373.69 - SecureRandom generator, EncryptionKey sessionKey) throws IOException {
373.70 -
373.71 - if (sessionKey.getEType() ==
373.72 - EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD) {
373.73 - throw new IOException(
373.74 - "session keys with des3-cbc-hmac-sha1-kd encryption type " +
373.75 - "are not supported for TLS Kerberos cipher suites");
373.76 - }
373.77 -
373.78 - this.protocolVersion = protocolVersion;
373.79 - preMaster = generatePreMaster(generator, protocolVersion);
373.80 -
373.81 - // Encrypt premaster secret
373.82 - try {
373.83 - EncryptedData eData = new EncryptedData(sessionKey, preMaster,
373.84 - KeyUsage.KU_UNKNOWN);
373.85 - encrypted = eData.getBytes(); // not ASN.1 encoded.
373.86 -
373.87 - } catch (KrbException e) {
373.88 - throw (SSLKeyException)new SSLKeyException
373.89 - ("Kerberos premaster secret error").initCause(e);
373.90 - }
373.91 - }
373.92 -
373.93 - /*
373.94 - * Constructor used by server to decrypt encrypted premaster secret.
373.95 - * The protocol version in preMaster[0,1] must match either currentVersion
373.96 - * or clientVersion, otherwise, the premaster secret is set to
373.97 - * a random one to foil possible attack.
373.98 - *
373.99 - * @param currentVersion version of protocol being used
373.100 - * @param clientVersion version requested by client
373.101 - * @param generator random number generator used to generate
373.102 - * bogus premaster secret if premaster secret verification fails
373.103 - * @param input input stream from which to read the encrypted
373.104 - * premaster secret
373.105 - * @param sessionKey Kerberos session key to be used for decryption
373.106 - */
373.107 - KerberosPreMasterSecret(ProtocolVersion currentVersion,
373.108 - ProtocolVersion clientVersion,
373.109 - SecureRandom generator, HandshakeInStream input,
373.110 - EncryptionKey sessionKey) throws IOException {
373.111 -
373.112 - // Extract encrypted premaster secret from message
373.113 - encrypted = input.getBytes16();
373.114 -
373.115 - if (HandshakeMessage.debug != null && Debug.isOn("handshake")) {
373.116 - if (encrypted != null) {
373.117 - Debug.println(System.out,
373.118 - "encrypted premaster secret", encrypted);
373.119 - }
373.120 - }
373.121 -
373.122 - if (sessionKey.getEType() ==
373.123 - EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD) {
373.124 - throw new IOException(
373.125 - "session keys with des3-cbc-hmac-sha1-kd encryption type " +
373.126 - "are not supported for TLS Kerberos cipher suites");
373.127 - }
373.128 -
373.129 - // Decrypt premaster secret
373.130 - try {
373.131 - EncryptedData data = new EncryptedData(sessionKey.getEType(),
373.132 - null /* optional kvno */, encrypted);
373.133 -
373.134 - byte[] temp = data.decrypt(sessionKey, KeyUsage.KU_UNKNOWN);
373.135 - if (HandshakeMessage.debug != null && Debug.isOn("handshake")) {
373.136 - if (encrypted != null) {
373.137 - Debug.println(System.out,
373.138 - "decrypted premaster secret", temp);
373.139 - }
373.140 - }
373.141 -
373.142 - // Reset data stream after decryption, remove redundant bytes
373.143 - preMaster = data.reset(temp, false);
373.144 -
373.145 - protocolVersion = ProtocolVersion.valueOf(preMaster[0],
373.146 - preMaster[1]);
373.147 - if (HandshakeMessage.debug != null && Debug.isOn("handshake")) {
373.148 - System.out.println("Kerberos PreMasterSecret version: "
373.149 - + protocolVersion);
373.150 - }
373.151 - } catch (Exception e) {
373.152 - // catch exception & process below
373.153 - preMaster = null;
373.154 - protocolVersion = currentVersion;
373.155 - }
373.156 -
373.157 - // check if the premaster secret version is ok
373.158 - // the specification says that it must be the maximum version supported
373.159 - // by the client from its ClientHello message. However, many
373.160 - // implementations send the negotiated version, so accept both
373.161 - // NOTE that we may be comparing two unsupported version numbers in
373.162 - // the second case, which is why we cannot use object references
373.163 - // equality in this special case
373.164 - boolean versionMismatch = (protocolVersion != currentVersion) &&
373.165 - (protocolVersion.v != clientVersion.v);
373.166 -
373.167 -
373.168 - /*
373.169 - * Bogus decrypted ClientKeyExchange? If so, conjure a
373.170 - * a random preMaster secret that will fail later during
373.171 - * Finished message processing. This is a countermeasure against
373.172 - * the "interactive RSA PKCS#1 encryption envelop attack" reported
373.173 - * in June 1998. Preserving the executation path will
373.174 - * mitigate timing attacks and force consistent error handling
373.175 - * that will prevent an attacking client from differentiating
373.176 - * different kinds of decrypted ClientKeyExchange bogosities.
373.177 - */
373.178 - if ((preMaster == null) || (preMaster.length != 48)
373.179 - || versionMismatch) {
373.180 - if (HandshakeMessage.debug != null && Debug.isOn("handshake")) {
373.181 - System.out.println("Kerberos PreMasterSecret error, "
373.182 - + "generating random secret");
373.183 - if (preMaster != null) {
373.184 - Debug.println(System.out, "Invalid secret", preMaster);
373.185 - }
373.186 - }
373.187 - preMaster = generatePreMaster(generator, currentVersion);
373.188 - protocolVersion = currentVersion;
373.189 - }
373.190 - }
373.191 -
373.192 - /*
373.193 - * Used by server to generate premaster secret in case of
373.194 - * problem decoding ticket.
373.195 - *
373.196 - * @param protocolVersion used for preMaster[0,1]
373.197 - * @param generator random number generator to use for generating secret.
373.198 - */
373.199 - KerberosPreMasterSecret(ProtocolVersion protocolVersion,
373.200 - SecureRandom generator) {
373.201 -
373.202 - this.protocolVersion = protocolVersion;
373.203 - preMaster = generatePreMaster(generator, protocolVersion);
373.204 - }
373.205 -
373.206 - private static byte[] generatePreMaster(SecureRandom rand,
373.207 - ProtocolVersion ver) {
373.208 -
373.209 - byte[] pm = new byte[48];
373.210 - rand.nextBytes(pm);
373.211 - pm[0] = ver.major;
373.212 - pm[1] = ver.minor;
373.213 -
373.214 - return pm;
373.215 - }
373.216 -
373.217 - // Clone not needed; package internal use only
373.218 - byte[] getUnencrypted() {
373.219 - return preMaster;
373.220 - }
373.221 -
373.222 - // Clone not needed; package internal use only
373.223 - byte[] getEncrypted() {
373.224 - return encrypted;
373.225 - }
373.226 -}
374.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
374.2 +++ b/src/share/classes/sun/security/ssl/Krb5Helper.java Wed Nov 25 11:08:25 2009 -0800
374.3 @@ -0,0 +1,126 @@
374.4 +/*
374.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
374.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
374.7 + *
374.8 + * This code is free software; you can redistribute it and/or modify it
374.9 + * under the terms of the GNU General Public License version 2 only, as
374.10 + * published by the Free Software Foundation. Sun designates this
374.11 + * particular file as subject to the "Classpath" exception as provided
374.12 + * by Sun in the LICENSE file that accompanied this code.
374.13 + *
374.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
374.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
374.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
374.17 + * version 2 for more details (a copy is included in the LICENSE file that
374.18 + * accompanied this code).
374.19 + *
374.20 + * You should have received a copy of the GNU General Public License version
374.21 + * 2 along with this work; if not, write to the Free Software Foundation,
374.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
374.23 + *
374.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
374.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
374.26 + * have any questions.
374.27 + */
374.28 +
374.29 +package sun.security.ssl;
374.30 +
374.31 +import java.security.AccessControlContext;
374.32 +import java.security.AccessController;
374.33 +import java.security.Permission;
374.34 +import java.security.Principal;
374.35 +import java.security.PrivilegedAction;
374.36 +import javax.crypto.SecretKey;
374.37 +import javax.security.auth.Subject;
374.38 +import javax.security.auth.login.LoginException;
374.39 +
374.40 +/**
374.41 + * A helper class for Kerberos APIs.
374.42 + */
374.43 +public final class Krb5Helper {
374.44 +
374.45 + private Krb5Helper() { }
374.46 +
374.47 + // loads Krb5Proxy implementation class if available
374.48 + private static final String IMPL_CLASS =
374.49 + "sun.security.ssl.krb5.Krb5ProxyImpl";
374.50 +
374.51 + private static final Krb5Proxy proxy =
374.52 + AccessController.doPrivileged(new PrivilegedAction<Krb5Proxy>() {
374.53 + public Krb5Proxy run() {
374.54 + try {
374.55 + Class<?> c = Class.forName(IMPL_CLASS, true, null);
374.56 + return (Krb5Proxy)c.newInstance();
374.57 + } catch (ClassNotFoundException cnf) {
374.58 + return null;
374.59 + } catch (InstantiationException e) {
374.60 + throw new AssertionError(e);
374.61 + } catch (IllegalAccessException e) {
374.62 + throw new AssertionError(e);
374.63 + }
374.64 + }});
374.65 +
374.66 + /**
374.67 + * Returns true if Kerberos is available.
374.68 + */
374.69 + public static boolean isAvailable() {
374.70 + return proxy != null;
374.71 + }
374.72 +
374.73 + private static void ensureAvailable() {
374.74 + if (proxy == null)
374.75 + throw new AssertionError("Kerberos should have been available");
374.76 + }
374.77 +
374.78 + /**
374.79 + * Returns the Subject associated with client-side of the SSL socket.
374.80 + */
374.81 + public static Subject getClientSubject(AccessControlContext acc)
374.82 + throws LoginException {
374.83 + ensureAvailable();
374.84 + return proxy.getClientSubject(acc);
374.85 + }
374.86 +
374.87 + /**
374.88 + * Returns the Subject associated with server-side of the SSL socket.
374.89 + */
374.90 + public static Subject getServerSubject(AccessControlContext acc)
374.91 + throws LoginException {
374.92 + ensureAvailable();
374.93 + return proxy.getServerSubject(acc);
374.94 + }
374.95 +
374.96 + /**
374.97 + * Returns the KerberosKeys for the default server-side principal.
374.98 + */
374.99 + public static SecretKey[] getServerKeys(AccessControlContext acc)
374.100 + throws LoginException {
374.101 + ensureAvailable();
374.102 + return proxy.getServerKeys(acc);
374.103 + }
374.104 +
374.105 + /**
374.106 + * Returns the server-side principal name associated with the KerberosKey.
374.107 + */
374.108 + public static String getServerPrincipalName(SecretKey kerberosKey) {
374.109 + ensureAvailable();
374.110 + return proxy.getServerPrincipalName(kerberosKey);
374.111 + }
374.112 +
374.113 + /**
374.114 + * Returns the hostname embedded in the principal name.
374.115 + */
374.116 + public static String getPrincipalHostName(Principal principal) {
374.117 + ensureAvailable();
374.118 + return proxy.getPrincipalHostName(principal);
374.119 + }
374.120 +
374.121 + /**
374.122 + * Returns a ServicePermission for the principal name and action.
374.123 + */
374.124 + public static Permission getServicePermission(String principalName,
374.125 + String action) {
374.126 + ensureAvailable();
374.127 + return proxy.getServicePermission(principalName, action);
374.128 + }
374.129 +}
375.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
375.2 +++ b/src/share/classes/sun/security/ssl/Krb5Proxy.java Wed Nov 25 11:08:25 2009 -0800
375.3 @@ -0,0 +1,71 @@
375.4 +/*
375.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
375.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
375.7 + *
375.8 + * This code is free software; you can redistribute it and/or modify it
375.9 + * under the terms of the GNU General Public License version 2 only, as
375.10 + * published by the Free Software Foundation. Sun designates this
375.11 + * particular file as subject to the "Classpath" exception as provided
375.12 + * by Sun in the LICENSE file that accompanied this code.
375.13 + *
375.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
375.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
375.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
375.17 + * version 2 for more details (a copy is included in the LICENSE file that
375.18 + * accompanied this code).
375.19 + *
375.20 + * You should have received a copy of the GNU General Public License version
375.21 + * 2 along with this work; if not, write to the Free Software Foundation,
375.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
375.23 + *
375.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
375.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
375.26 + * have any questions.
375.27 + */
375.28 +
375.29 +package sun.security.ssl;
375.30 +
375.31 +import java.security.AccessControlContext;
375.32 +import java.security.Permission;
375.33 +import java.security.Principal;
375.34 +import javax.crypto.SecretKey;
375.35 +import javax.security.auth.Subject;
375.36 +import javax.security.auth.login.LoginException;
375.37 +
375.38 +/**
375.39 + * An interface to a subset of the Kerberos APIs to avoid a static dependency
375.40 + * on the types defined by these APIs.
375.41 + */
375.42 +public interface Krb5Proxy {
375.43 +
375.44 + /**
375.45 + * Returns the Subject associated with the client-side of the SSL socket.
375.46 + */
375.47 + Subject getClientSubject(AccessControlContext acc) throws LoginException;
375.48 +
375.49 + /**
375.50 + * Returns the Subject associated with the server-side of the SSL socket.
375.51 + */
375.52 + Subject getServerSubject(AccessControlContext acc) throws LoginException;
375.53 +
375.54 +
375.55 + /**
375.56 + * Returns the KerberosKeys for the default server-side principal.
375.57 + */
375.58 + SecretKey[] getServerKeys(AccessControlContext acc) throws LoginException;
375.59 +
375.60 + /**
375.61 + * Returns the server-side principal name associated with the KerberosKey.
375.62 + */
375.63 + String getServerPrincipalName(SecretKey kerberosKey);
375.64 +
375.65 + /**
375.66 + * Returns the hostname embedded in the principal name.
375.67 + */
375.68 + String getPrincipalHostName(Principal principal);
375.69 +
375.70 + /**
375.71 + * Returns a ServicePermission for the principal name and action.
375.72 + */
375.73 + Permission getServicePermission(String principalName, String action);
375.74 +}
376.1 --- a/src/share/classes/sun/security/ssl/ProtocolVersion.java Mon Nov 23 10:04:47 2009 +0000
376.2 +++ b/src/share/classes/sun/security/ssl/ProtocolVersion.java Wed Nov 25 11:08:25 2009 -0800
376.3 @@ -1,5 +1,5 @@
376.4 /*
376.5 - * Copyright 2002-2007 Sun Microsystems, Inc. All Rights Reserved.
376.6 + * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved.
376.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
376.8 *
376.9 * This code is free software; you can redistribute it and/or modify it
376.10 @@ -45,7 +45,7 @@
376.11 * @author Andreas Sterbenz
376.12 * @since 1.4.1
376.13 */
376.14 -final class ProtocolVersion {
376.15 +public final class ProtocolVersion {
376.16
376.17 // dummy protocol version value for invalid SSLSession
376.18 final static ProtocolVersion NONE = new ProtocolVersion(-1, "NONE");
376.19 @@ -80,10 +80,10 @@
376.20
376.21 // version in 16 bit MSB format as it appears in records and
376.22 // messages, i.e. 0x0301 for TLS 1.0
376.23 - final int v;
376.24 + public final int v;
376.25
376.26 // major and minor version
376.27 - final byte major, minor;
376.28 + public final byte major, minor;
376.29
376.30 // name used in JSSE (e.g. TLSv1 for TLS 1.0)
376.31 final String name;
376.32 @@ -117,7 +117,7 @@
376.33 * Return a ProtocolVersion with the specified major and minor version
376.34 * numbers. Never throws exceptions.
376.35 */
376.36 - static ProtocolVersion valueOf(int major, int minor) {
376.37 + public static ProtocolVersion valueOf(int major, int minor) {
376.38 major &= 0xff;
376.39 minor &= 0xff;
376.40 int v = (major << 8) | minor;
377.1 --- a/src/share/classes/sun/security/ssl/SSLSessionImpl.java Mon Nov 23 10:04:47 2009 +0000
377.2 +++ b/src/share/classes/sun/security/ssl/SSLSessionImpl.java Wed Nov 25 11:08:25 2009 -0800
377.3 @@ -48,7 +48,6 @@
377.4 import javax.net.ssl.SSLSession;
377.5 import javax.net.ssl.SSLPermission;
377.6
377.7 -import javax.security.auth.kerberos.KerberosPrincipal;
377.8 import javax.security.auth.x500.X500Principal;
377.9
377.10 import static sun.security.ssl.CipherSuite.*;
377.11 @@ -469,8 +468,8 @@
377.12 * defining the session.
377.13 *
377.14 * @return the peer's principal. Returns an X500Principal of the
377.15 - * end-entity certiticate for X509-based cipher suites, and
377.16 - * KerberosPrincipal for Kerberos cipher suites.
377.17 + * end-entity certificate for X509-based cipher suites, and
377.18 + * Principal for Kerberos cipher suites.
377.19 *
377.20 * @throws SSLPeerUnverifiedException if the peer's identity has not
377.21 * been verified
377.22 @@ -483,7 +482,8 @@
377.23 if (peerPrincipal == null) {
377.24 throw new SSLPeerUnverifiedException("peer not authenticated");
377.25 } else {
377.26 - return (KerberosPrincipal)peerPrincipal;
377.27 + // Eliminate dependency on KerberosPrincipal
377.28 + return peerPrincipal;
377.29 }
377.30 }
377.31 if (peerCerts == null) {
377.32 @@ -497,15 +497,15 @@
377.33 *
377.34 * @return the principal sent to the peer. Returns an X500Principal
377.35 * of the end-entity certificate for X509-based cipher suites, and
377.36 - * KerberosPrincipal for Kerberos cipher suites. If no principal was
377.37 + * Principal for Kerberos cipher suites. If no principal was
377.38 * sent, then null is returned.
377.39 */
377.40 public Principal getLocalPrincipal() {
377.41
377.42 if ((cipherSuite.keyExchange == K_KRB5) ||
377.43 (cipherSuite.keyExchange == K_KRB5_EXPORT)) {
377.44 - return (localPrincipal == null ? null :
377.45 - (KerberosPrincipal)localPrincipal);
377.46 + // Eliminate dependency on KerberosPrincipal
377.47 + return (localPrincipal == null ? null : localPrincipal);
377.48 }
377.49 return (localCerts == null ? null :
377.50 localCerts[0].getSubjectX500Principal());
378.1 --- a/src/share/classes/sun/security/ssl/ServerHandshaker.java Mon Nov 23 10:04:47 2009 +0000
378.2 +++ b/src/share/classes/sun/security/ssl/ServerHandshaker.java Wed Nov 25 11:08:25 2009 -0800
378.3 @@ -39,11 +39,6 @@
378.4 import javax.net.ssl.*;
378.5
378.6 import javax.security.auth.Subject;
378.7 -import javax.security.auth.kerberos.KerberosKey;
378.8 -import javax.security.auth.kerberos.KerberosPrincipal;
378.9 -import javax.security.auth.kerberos.ServicePermission;
378.10 -import sun.security.jgss.krb5.Krb5Util;
378.11 -import sun.security.jgss.GSSCaller;
378.12
378.13 import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
378.14
378.15 @@ -69,7 +64,7 @@
378.16 private X509Certificate[] certs;
378.17 private PrivateKey privateKey;
378.18
378.19 - private KerberosKey[] kerberosKeys;
378.20 + private SecretKey[] kerberosKeys;
378.21
378.22 // flag to check for clientCertificateVerify message
378.23 private boolean needClientVerify = false;
378.24 @@ -366,9 +361,8 @@
378.25 subject = AccessController.doPrivileged(
378.26 new PrivilegedExceptionAction<Subject>() {
378.27 public Subject run() throws Exception {
378.28 - return Krb5Util.getSubject(
378.29 - GSSCaller.CALLER_SSL_SERVER,
378.30 - getAccSE());
378.31 + return
378.32 + Krb5Helper.getServerSubject(getAccSE());
378.33 }});
378.34 } catch (PrivilegedActionException e) {
378.35 subject = null;
378.36 @@ -379,8 +373,9 @@
378.37 }
378.38
378.39 if (subject != null) {
378.40 - Set<KerberosPrincipal> principals =
378.41 - subject.getPrincipals(KerberosPrincipal.class);
378.42 + // Eliminate dependency on KerberosPrincipal
378.43 + Set<Principal> principals =
378.44 + subject.getPrincipals(Principal.class);
378.45 if (!principals.contains(localPrincipal)) {
378.46 resumingSession = false;
378.47 if (debug != null && Debug.isOn("session")) {
378.48 @@ -914,11 +909,11 @@
378.49 try {
378.50 final AccessControlContext acc = getAccSE();
378.51 kerberosKeys = AccessController.doPrivileged(
378.52 - new PrivilegedExceptionAction<KerberosKey[]>() {
378.53 - public KerberosKey[] run() throws Exception {
378.54 + // Eliminate dependency on KerberosKey
378.55 + new PrivilegedExceptionAction<SecretKey[]>() {
378.56 + public SecretKey[] run() throws Exception {
378.57 // get kerberos key for the default principal
378.58 - return Krb5Util.getKeys(
378.59 - GSSCaller.CALLER_SSL_SERVER, null, acc);
378.60 + return Krb5Helper.getServerKeys(acc);
378.61 }});
378.62
378.63 // check permission to access and use the secret key of the
378.64 @@ -931,12 +926,13 @@
378.65 }
378.66
378.67 String serverPrincipal =
378.68 - kerberosKeys[0].getPrincipal().getName();
378.69 + Krb5Helper.getServerPrincipalName(kerberosKeys[0]);
378.70 SecurityManager sm = System.getSecurityManager();
378.71 try {
378.72 if (sm != null) {
378.73 - sm.checkPermission(new ServicePermission(serverPrincipal,
378.74 - "accept"), acc);
378.75 + // Eliminate dependency on ServicePermission
378.76 + sm.checkPermission(Krb5Helper.getServicePermission(
378.77 + serverPrincipal, "accept"), acc);
378.78 }
378.79 } catch (SecurityException se) {
378.80 kerberosKeys = null;
378.81 @@ -973,7 +969,7 @@
378.82 session.setPeerPrincipal(mesg.getPeerPrincipal());
378.83 session.setLocalPrincipal(mesg.getLocalPrincipal());
378.84
378.85 - byte[] b = mesg.getPreMasterSecret().getUnencrypted();
378.86 + byte[] b = mesg.getUnencryptedPreMasterSecret();
378.87 return new SecretKeySpec(b, "TlsPremasterSecret");
378.88 }
378.89
379.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
379.2 +++ b/src/share/classes/sun/security/ssl/krb5/KerberosClientKeyExchangeImpl.java Wed Nov 25 11:08:25 2009 -0800
379.3 @@ -0,0 +1,383 @@
379.4 +/*
379.5 + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
379.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
379.7 + *
379.8 + * This code is free software; you can redistribute it and/or modify it
379.9 + * under the terms of the GNU General Public License version 2 only, as
379.10 + * published by the Free Software Foundation. Sun designates this
379.11 + * particular file as subject to the "Classpath" exception as provided
379.12 + * by Sun in the LICENSE file that accompanied this code.
379.13 + *
379.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
379.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
379.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
379.17 + * version 2 for more details (a copy is included in the LICENSE file that
379.18 + * accompanied this code).
379.19 + *
379.20 + * You should have received a copy of the GNU General Public License version
379.21 + * 2 along with this work; if not, write to the Free Software Foundation,
379.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
379.23 + *
379.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
379.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
379.26 + * have any questions.
379.27 + */
379.28 +
379.29 +package sun.security.ssl.krb5;
379.30 +
379.31 +import java.io.IOException;
379.32 +import java.io.PrintStream;
379.33 +import java.security.AccessController;
379.34 +import java.security.AccessControlContext;
379.35 +import java.security.PrivilegedExceptionAction;
379.36 +import java.security.PrivilegedActionException;
379.37 +import java.security.SecureRandom;
379.38 +import java.net.InetAddress;
379.39 +
379.40 +import javax.crypto.SecretKey;
379.41 +import javax.security.auth.kerberos.KerberosTicket;
379.42 +import javax.security.auth.kerberos.KerberosKey;
379.43 +import javax.security.auth.kerberos.KerberosPrincipal;
379.44 +import javax.security.auth.kerberos.ServicePermission;
379.45 +import sun.security.jgss.GSSCaller;
379.46 +
379.47 +import sun.security.krb5.EncryptionKey;
379.48 +import sun.security.krb5.EncryptedData;
379.49 +import sun.security.krb5.PrincipalName;
379.50 +import sun.security.krb5.Realm;
379.51 +import sun.security.krb5.internal.Ticket;
379.52 +import sun.security.krb5.internal.EncTicketPart;
379.53 +import sun.security.krb5.internal.crypto.KeyUsage;
379.54 +
379.55 +import sun.security.jgss.krb5.Krb5Util;
379.56 +
379.57 +import sun.security.ssl.Debug;
379.58 +import sun.security.ssl.HandshakeInStream;
379.59 +import sun.security.ssl.HandshakeOutStream;
379.60 +import sun.security.ssl.KerberosClientKeyExchange;
379.61 +import sun.security.ssl.ProtocolVersion;
379.62 +
379.63 +/**
379.64 + * This is Kerberos option in the client key exchange message
379.65 + * (CLIENT -> SERVER). It holds the Kerberos ticket and the encrypted
379.66 + * premaster secret encrypted with the session key sealed in the ticket.
379.67 + * From RFC 2712:
379.68 + * struct
379.69 + * {
379.70 + * opaque Ticket;
379.71 + * opaque authenticator; // optional
379.72 + * opaque EncryptedPreMasterSecret; // encrypted with the session key
379.73 + * // which is sealed in the ticket
379.74 + * } KerberosWrapper;
379.75 + *
379.76 + *
379.77 + * Ticket and authenticator are encrypted as per RFC 1510 (in ASN.1)
379.78 + * Encrypted pre-master secret has the same structure as it does for RSA
379.79 + * except for Kerberos, the encryption key is the session key instead of
379.80 + * the RSA public key.
379.81 + *
379.82 + * XXX authenticator currently ignored
379.83 + *
379.84 + */
379.85 +public final class KerberosClientKeyExchangeImpl
379.86 + extends sun.security.ssl.KerberosClientKeyExchange {
379.87 +
379.88 + private KerberosPreMasterSecret preMaster;
379.89 + private byte[] encodedTicket;
379.90 + private KerberosPrincipal peerPrincipal;
379.91 + private KerberosPrincipal localPrincipal;
379.92 +
379.93 + public KerberosClientKeyExchangeImpl() {
379.94 + }
379.95 +
379.96 + /**
379.97 + * Creates an instance of KerberosClientKeyExchange consisting of the
379.98 + * Kerberos service ticket, authenticator and encrypted premaster secret.
379.99 + * Called by client handshaker.
379.100 + *
379.101 + * @param serverName name of server with which to do handshake;
379.102 + * this is used to get the Kerberos service ticket
379.103 + * @param protocolVersion Maximum version supported by client (i.e,
379.104 + * version it requested in client hello)
379.105 + * @param rand random number generator to use for generating pre-master
379.106 + * secret
379.107 + */
379.108 + @Override
379.109 + public void init(String serverName, boolean isLoopback,
379.110 + AccessControlContext acc, ProtocolVersion protocolVersion,
379.111 + SecureRandom rand) throws IOException {
379.112 +
379.113 + // Get service ticket
379.114 + KerberosTicket ticket = getServiceTicket(serverName, isLoopback, acc);
379.115 + encodedTicket = ticket.getEncoded();
379.116 +
379.117 + // Record the Kerberos principals
379.118 + peerPrincipal = ticket.getServer();
379.119 + localPrincipal = ticket.getClient();
379.120 +
379.121 + // Optional authenticator, encrypted using session key,
379.122 + // currently ignored
379.123 +
379.124 + // Generate premaster secret and encrypt it using session key
379.125 + EncryptionKey sessionKey = new EncryptionKey(
379.126 + ticket.getSessionKeyType(),
379.127 + ticket.getSessionKey().getEncoded());
379.128 +
379.129 + preMaster = new KerberosPreMasterSecret(protocolVersion,
379.130 + rand, sessionKey);
379.131 + }
379.132 +
379.133 + /**
379.134 + * Creates an instance of KerberosClientKeyExchange from its ASN.1 encoding.
379.135 + * Used by ServerHandshaker to verify and obtain premaster secret.
379.136 + *
379.137 + * @param protocolVersion current protocol version
379.138 + * @param clientVersion version requested by client in its ClientHello;
379.139 + * used by premaster secret version check
379.140 + * @param rand random number generator used for generating random
379.141 + * premaster secret if ticket and/or premaster verification fails
379.142 + * @param input inputstream from which to get ASN.1-encoded KerberosWrapper
379.143 + * @param serverKey server's master secret key
379.144 + */
379.145 + @Override
379.146 + public void init(ProtocolVersion protocolVersion,
379.147 + ProtocolVersion clientVersion,
379.148 + SecureRandom rand, HandshakeInStream input, SecretKey[] secretKeys)
379.149 + throws IOException {
379.150 +
379.151 + KerberosKey[] serverKeys = (KerberosKey[])secretKeys;
379.152 +
379.153 + // Read ticket
379.154 + encodedTicket = input.getBytes16();
379.155 +
379.156 + if (debug != null && Debug.isOn("verbose")) {
379.157 + Debug.println(System.out,
379.158 + "encoded Kerberos service ticket", encodedTicket);
379.159 + }
379.160 +
379.161 + EncryptionKey sessionKey = null;
379.162 +
379.163 + try {
379.164 + Ticket t = new Ticket(encodedTicket);
379.165 +
379.166 + EncryptedData encPart = t.encPart;
379.167 + PrincipalName ticketSname = t.sname;
379.168 + Realm ticketRealm = t.realm;
379.169 +
379.170 + String serverPrincipal = serverKeys[0].getPrincipal().getName();
379.171 +
379.172 + /*
379.173 + * permission to access and use the secret key of the Kerberized
379.174 + * "host" service is done in ServerHandshaker.getKerberosKeys()
379.175 + * to ensure server has the permission to use the secret key
379.176 + * before promising the client
379.177 + */
379.178 +
379.179 + // Check that ticket Sname matches serverPrincipal
379.180 + String ticketPrinc = ticketSname.toString().concat("@" +
379.181 + ticketRealm.toString());
379.182 + if (!ticketPrinc.equals(serverPrincipal)) {
379.183 + if (debug != null && Debug.isOn("handshake"))
379.184 + System.out.println("Service principal in Ticket does not"
379.185 + + " match associated principal in KerberosKey");
379.186 + throw new IOException("Server principal is " +
379.187 + serverPrincipal + " but ticket is for " +
379.188 + ticketPrinc);
379.189 + }
379.190 +
379.191 + // See if we have the right key to decrypt the ticket to get
379.192 + // the session key.
379.193 + int encPartKeyType = encPart.getEType();
379.194 + KerberosKey dkey = findKey(encPartKeyType, serverKeys);
379.195 + if (dkey == null) {
379.196 + // %%% Should print string repr of etype
379.197 + throw new IOException(
379.198 + "Cannot find key of appropriate type to decrypt ticket - need etype " +
379.199 + encPartKeyType);
379.200 + }
379.201 +
379.202 + EncryptionKey secretKey = new EncryptionKey(
379.203 + encPartKeyType,
379.204 + dkey.getEncoded());
379.205 +
379.206 + // Decrypt encPart using server's secret key
379.207 + byte[] bytes = encPart.decrypt(secretKey, KeyUsage.KU_TICKET);
379.208 +
379.209 + // Reset data stream after decryption, remove redundant bytes
379.210 + byte[] temp = encPart.reset(bytes, true);
379.211 + EncTicketPart encTicketPart = new EncTicketPart(temp);
379.212 +
379.213 + // Record the Kerberos Principals
379.214 + peerPrincipal =
379.215 + new KerberosPrincipal(encTicketPart.cname.getName());
379.216 + localPrincipal = new KerberosPrincipal(ticketSname.getName());
379.217 +
379.218 + sessionKey = encTicketPart.key;
379.219 +
379.220 + if (debug != null && Debug.isOn("handshake")) {
379.221 + System.out.println("server principal: " + serverPrincipal);
379.222 + System.out.println("realm: " + encTicketPart.crealm.toString());
379.223 + System.out.println("cname: " + encTicketPart.cname.toString());
379.224 + }
379.225 + } catch (IOException e) {
379.226 + throw e;
379.227 + } catch (Exception e) {
379.228 + if (debug != null && Debug.isOn("handshake")) {
379.229 + System.out.println("KerberosWrapper error getting session key,"
379.230 + + " generating random secret (" + e.getMessage() + ")");
379.231 + }
379.232 + sessionKey = null;
379.233 + }
379.234 +
379.235 + input.getBytes16(); // XXX Read and ignore authenticator
379.236 +
379.237 + if (sessionKey != null) {
379.238 + preMaster = new KerberosPreMasterSecret(protocolVersion,
379.239 + clientVersion, rand, input, sessionKey);
379.240 + } else {
379.241 + // Generate bogus premaster secret
379.242 + preMaster = new KerberosPreMasterSecret(protocolVersion, rand);
379.243 + }
379.244 + }
379.245 +
379.246 + @Override
379.247 + public int messageLength() {
379.248 + return (6 + encodedTicket.length + preMaster.getEncrypted().length);
379.249 + }
379.250 +
379.251 + @Override
379.252 + public void send(HandshakeOutStream s) throws IOException {
379.253 + s.putBytes16(encodedTicket);
379.254 + s.putBytes16(null); // XXX no authenticator
379.255 + s.putBytes16(preMaster.getEncrypted());
379.256 + }
379.257 +
379.258 + @Override
379.259 + public void print(PrintStream s) throws IOException {
379.260 + s.println("*** ClientKeyExchange, Kerberos");
379.261 +
379.262 + if (debug != null && Debug.isOn("verbose")) {
379.263 + Debug.println(s, "Kerberos service ticket", encodedTicket);
379.264 + Debug.println(s, "Random Secret", preMaster.getUnencrypted());
379.265 + Debug.println(s, "Encrypted random Secret",
379.266 + preMaster.getEncrypted());
379.267 + }
379.268 + }
379.269 +
379.270 + // Similar to sun.security.jgss.krb5.Krb5InitCredenetial/Krb5Context
379.271 + private static KerberosTicket getServiceTicket(String srvName,
379.272 + boolean isLoopback, final AccessControlContext acc) throws IOException {
379.273 +
379.274 + // get the local hostname if srvName is loopback address
379.275 + String serverName = srvName;
379.276 + if (isLoopback) {
379.277 + String localHost = java.security.AccessController.doPrivileged(
379.278 + new java.security.PrivilegedAction<String>() {
379.279 + public String run() {
379.280 + String hostname;
379.281 + try {
379.282 + hostname = InetAddress.getLocalHost().getHostName();
379.283 + } catch (java.net.UnknownHostException e) {
379.284 + hostname = "localhost";
379.285 + }
379.286 + return hostname;
379.287 + }
379.288 + });
379.289 + serverName = localHost;
379.290 + }
379.291 +
379.292 + // Resolve serverName (possibly in IP addr form) to Kerberos principal
379.293 + // name for service with hostname
379.294 + String serviceName = "host/" + serverName;
379.295 + PrincipalName principal;
379.296 + try {
379.297 + principal = new PrincipalName(serviceName,
379.298 + PrincipalName.KRB_NT_SRV_HST);
379.299 + } catch (SecurityException se) {
379.300 + throw se;
379.301 + } catch (Exception e) {
379.302 + IOException ioe = new IOException("Invalid service principal" +
379.303 + " name: " + serviceName);
379.304 + ioe.initCause(e);
379.305 + throw ioe;
379.306 + }
379.307 + String realm = principal.getRealmAsString();
379.308 +
379.309 + final String serverPrincipal = principal.toString();
379.310 + final String tgsPrincipal = "krbtgt/" + realm + "@" + realm;
379.311 + final String clientPrincipal = null; // use default
379.312 +
379.313 +
379.314 + // check permission to obtain a service ticket to initiate a
379.315 + // context with the "host" service
379.316 + SecurityManager sm = System.getSecurityManager();
379.317 + if (sm != null) {
379.318 + sm.checkPermission(new ServicePermission(serverPrincipal,
379.319 + "initiate"), acc);
379.320 + }
379.321 +
379.322 + try {
379.323 + KerberosTicket ticket = AccessController.doPrivileged(
379.324 + new PrivilegedExceptionAction<KerberosTicket>() {
379.325 + public KerberosTicket run() throws Exception {
379.326 + return Krb5Util.getTicketFromSubjectAndTgs(
379.327 + GSSCaller.CALLER_SSL_CLIENT,
379.328 + clientPrincipal, serverPrincipal,
379.329 + tgsPrincipal, acc);
379.330 + }});
379.331 +
379.332 + if (ticket == null) {
379.333 + throw new IOException("Failed to find any kerberos service" +
379.334 + " ticket for " + serverPrincipal);
379.335 + }
379.336 + return ticket;
379.337 + } catch (PrivilegedActionException e) {
379.338 + IOException ioe = new IOException(
379.339 + "Attempt to obtain kerberos service ticket for " +
379.340 + serverPrincipal + " failed!");
379.341 + ioe.initCause(e);
379.342 + throw ioe;
379.343 + }
379.344 + }
379.345 +
379.346 + @Override
379.347 + public byte[] getUnencryptedPreMasterSecret() {
379.348 + return preMaster.getUnencrypted();
379.349 + }
379.350 +
379.351 + @Override
379.352 + public KerberosPrincipal getPeerPrincipal() {
379.353 + return peerPrincipal;
379.354 + }
379.355 +
379.356 + @Override
379.357 + public KerberosPrincipal getLocalPrincipal() {
379.358 + return localPrincipal;
379.359 + }
379.360 +
379.361 + private static KerberosKey findKey(int etype, KerberosKey[] keys) {
379.362 + int ktype;
379.363 + for (int i = 0; i < keys.length; i++) {
379.364 + ktype = keys[i].getKeyType();
379.365 + if (etype == ktype) {
379.366 + return keys[i];
379.367 + }
379.368 + }
379.369 + // Key not found.
379.370 + // %%% kludge to allow DES keys to be used for diff etypes
379.371 + if ((etype == EncryptedData.ETYPE_DES_CBC_CRC ||
379.372 + etype == EncryptedData.ETYPE_DES_CBC_MD5)) {
379.373 + for (int i = 0; i < keys.length; i++) {
379.374 + ktype = keys[i].getKeyType();
379.375 + if (ktype == EncryptedData.ETYPE_DES_CBC_CRC ||
379.376 + ktype == EncryptedData.ETYPE_DES_CBC_MD5) {
379.377 + return new KerberosKey(keys[i].getPrincipal(),
379.378 + keys[i].getEncoded(),
379.379 + etype,
379.380 + keys[i].getVersionNumber());
379.381 + }
379.382 + }
379.383 + }
379.384 + return null;
379.385 + }
379.386 +}
380.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
380.2 +++ b/src/share/classes/sun/security/ssl/krb5/KerberosPreMasterSecret.java Wed Nov 25 11:08:25 2009 -0800
380.3 @@ -0,0 +1,228 @@
380.4 +/*
380.5 + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
380.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
380.7 + *
380.8 + * This code is free software; you can redistribute it and/or modify it
380.9 + * under the terms of the GNU General Public License version 2 only, as
380.10 + * published by the Free Software Foundation. Sun designates this
380.11 + * particular file as subject to the "Classpath" exception as provided
380.12 + * by Sun in the LICENSE file that accompanied this code.
380.13 + *
380.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
380.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
380.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
380.17 + * version 2 for more details (a copy is included in the LICENSE file that
380.18 + * accompanied this code).
380.19 + *
380.20 + * You should have received a copy of the GNU General Public License version
380.21 + * 2 along with this work; if not, write to the Free Software Foundation,
380.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
380.23 + *
380.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
380.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
380.26 + * have any questions.
380.27 + */
380.28 +
380.29 +package sun.security.ssl.krb5;
380.30 +
380.31 +import java.io.*;
380.32 +import java.security.*;
380.33 +import java.security.interfaces.*;
380.34 +
380.35 +import javax.net.ssl.*;
380.36 +
380.37 +import sun.security.krb5.EncryptionKey;
380.38 +import sun.security.krb5.EncryptedData;
380.39 +import sun.security.krb5.KrbException;
380.40 +import sun.security.krb5.internal.crypto.KeyUsage;
380.41 +
380.42 +import sun.security.ssl.Debug;
380.43 +import sun.security.ssl.HandshakeInStream;
380.44 +import sun.security.ssl.HandshakeMessage;
380.45 +import sun.security.ssl.ProtocolVersion;
380.46 +
380.47 +/**
380.48 + * This is the Kerberos premaster secret in the Kerberos client key
380.49 + * exchange message (CLIENT --> SERVER); it holds the
380.50 + * Kerberos-encrypted pre-master secret. The secret is encrypted using the
380.51 + * Kerberos session key. The padding and size of the resulting message
380.52 + * depends on the session key type, but the pre-master secret is
380.53 + * always exactly 48 bytes.
380.54 + *
380.55 + */
380.56 +final class KerberosPreMasterSecret {
380.57 +
380.58 + private ProtocolVersion protocolVersion; // preMaster [0,1]
380.59 + private byte preMaster[]; // 48 bytes
380.60 + private byte encrypted[];
380.61 +
380.62 + /**
380.63 + * Constructor used by client to generate premaster secret.
380.64 + *
380.65 + * Client randomly creates a pre-master secret and encrypts it
380.66 + * using the Kerberos session key; only the server can decrypt
380.67 + * it, using the session key available in the service ticket.
380.68 + *
380.69 + * @param protocolVersion used to set preMaster[0,1]
380.70 + * @param generator random number generator for generating premaster secret
380.71 + * @param sessionKey Kerberos session key for encrypting premaster secret
380.72 + */
380.73 + KerberosPreMasterSecret(ProtocolVersion protocolVersion,
380.74 + SecureRandom generator, EncryptionKey sessionKey) throws IOException {
380.75 +
380.76 + if (sessionKey.getEType() ==
380.77 + EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD) {
380.78 + throw new IOException(
380.79 + "session keys with des3-cbc-hmac-sha1-kd encryption type " +
380.80 + "are not supported for TLS Kerberos cipher suites");
380.81 + }
380.82 +
380.83 + this.protocolVersion = protocolVersion;
380.84 + preMaster = generatePreMaster(generator, protocolVersion);
380.85 +
380.86 + // Encrypt premaster secret
380.87 + try {
380.88 + EncryptedData eData = new EncryptedData(sessionKey, preMaster,
380.89 + KeyUsage.KU_UNKNOWN);
380.90 + encrypted = eData.getBytes(); // not ASN.1 encoded.
380.91 +
380.92 + } catch (KrbException e) {
380.93 + throw (SSLKeyException)new SSLKeyException
380.94 + ("Kerberos premaster secret error").initCause(e);
380.95 + }
380.96 + }
380.97 +
380.98 + /*
380.99 + * Constructor used by server to decrypt encrypted premaster secret.
380.100 + * The protocol version in preMaster[0,1] must match either currentVersion
380.101 + * or clientVersion, otherwise, the premaster secret is set to
380.102 + * a random one to foil possible attack.
380.103 + *
380.104 + * @param currentVersion version of protocol being used
380.105 + * @param clientVersion version requested by client
380.106 + * @param generator random number generator used to generate
380.107 + * bogus premaster secret if premaster secret verification fails
380.108 + * @param input input stream from which to read the encrypted
380.109 + * premaster secret
380.110 + * @param sessionKey Kerberos session key to be used for decryption
380.111 + */
380.112 + KerberosPreMasterSecret(ProtocolVersion currentVersion,
380.113 + ProtocolVersion clientVersion,
380.114 + SecureRandom generator, HandshakeInStream input,
380.115 + EncryptionKey sessionKey) throws IOException {
380.116 +
380.117 + // Extract encrypted premaster secret from message
380.118 + encrypted = input.getBytes16();
380.119 +
380.120 + if (HandshakeMessage.debug != null && Debug.isOn("handshake")) {
380.121 + if (encrypted != null) {
380.122 + Debug.println(System.out,
380.123 + "encrypted premaster secret", encrypted);
380.124 + }
380.125 + }
380.126 +
380.127 + if (sessionKey.getEType() ==
380.128 + EncryptedData.ETYPE_DES3_CBC_HMAC_SHA1_KD) {
380.129 + throw new IOException(
380.130 + "session keys with des3-cbc-hmac-sha1-kd encryption type " +
380.131 + "are not supported for TLS Kerberos cipher suites");
380.132 + }
380.133 +
380.134 + // Decrypt premaster secret
380.135 + try {
380.136 + EncryptedData data = new EncryptedData(sessionKey.getEType(),
380.137 + null /* optional kvno */, encrypted);
380.138 +
380.139 + byte[] temp = data.decrypt(sessionKey, KeyUsage.KU_UNKNOWN);
380.140 + if (HandshakeMessage.debug != null && Debug.isOn("handshake")) {
380.141 + if (encrypted != null) {
380.142 + Debug.println(System.out,
380.143 + "decrypted premaster secret", temp);
380.144 + }
380.145 + }
380.146 +
380.147 + // Reset data stream after decryption, remove redundant bytes
380.148 + preMaster = data.reset(temp, false);
380.149 +
380.150 + protocolVersion = ProtocolVersion.valueOf(preMaster[0],
380.151 + preMaster[1]);
380.152 + if (HandshakeMessage.debug != null && Debug.isOn("handshake")) {
380.153 + System.out.println("Kerberos PreMasterSecret version: "
380.154 + + protocolVersion);
380.155 + }
380.156 + } catch (Exception e) {
380.157 + // catch exception & process below
380.158 + preMaster = null;
380.159 + protocolVersion = currentVersion;
380.160 + }
380.161 +
380.162 + // check if the premaster secret version is ok
380.163 + // the specification says that it must be the maximum version supported
380.164 + // by the client from its ClientHello message. However, many
380.165 + // implementations send the negotiated version, so accept both
380.166 + // NOTE that we may be comparing two unsupported version numbers in
380.167 + // the second case, which is why we cannot use object references
380.168 + // equality in this special case
380.169 + boolean versionMismatch = (protocolVersion != currentVersion) &&
380.170 + (protocolVersion.v != clientVersion.v);
380.171 +
380.172 +
380.173 + /*
380.174 + * Bogus decrypted ClientKeyExchange? If so, conjure a
380.175 + * a random preMaster secret that will fail later during
380.176 + * Finished message processing. This is a countermeasure against
380.177 + * the "interactive RSA PKCS#1 encryption envelop attack" reported
380.178 + * in June 1998. Preserving the executation path will
380.179 + * mitigate timing attacks and force consistent error handling
380.180 + * that will prevent an attacking client from differentiating
380.181 + * different kinds of decrypted ClientKeyExchange bogosities.
380.182 + */
380.183 + if ((preMaster == null) || (preMaster.length != 48)
380.184 + || versionMismatch) {
380.185 + if (HandshakeMessage.debug != null && Debug.isOn("handshake")) {
380.186 + System.out.println("Kerberos PreMasterSecret error, "
380.187 + + "generating random secret");
380.188 + if (preMaster != null) {
380.189 + Debug.println(System.out, "Invalid secret", preMaster);
380.190 + }
380.191 + }
380.192 + preMaster = generatePreMaster(generator, currentVersion);
380.193 + protocolVersion = currentVersion;
380.194 + }
380.195 + }
380.196 +
380.197 + /*
380.198 + * Used by server to generate premaster secret in case of
380.199 + * problem decoding ticket.
380.200 + *
380.201 + * @param protocolVersion used for preMaster[0,1]
380.202 + * @param generator random number generator to use for generating secret.
380.203 + */
380.204 + KerberosPreMasterSecret(ProtocolVersion protocolVersion,
380.205 + SecureRandom generator) {
380.206 +
380.207 + this.protocolVersion = protocolVersion;
380.208 + preMaster = generatePreMaster(generator, protocolVersion);
380.209 + }
380.210 +
380.211 + private static byte[] generatePreMaster(SecureRandom rand,
380.212 + ProtocolVersion ver) {
380.213 +
380.214 + byte[] pm = new byte[48];
380.215 + rand.nextBytes(pm);
380.216 + pm[0] = ver.major;
380.217 + pm[1] = ver.minor;
380.218 +
380.219 + return pm;
380.220 + }
380.221 +
380.222 + // Clone not needed; internal use only
380.223 + byte[] getUnencrypted() {
380.224 + return preMaster;
380.225 + }
380.226 +
380.227 + // Clone not needed; internal use only
380.228 + byte[] getEncrypted() {
380.229 + return encrypted;
380.230 + }
380.231 +}
381.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
381.2 +++ b/src/share/classes/sun/security/ssl/krb5/Krb5ProxyImpl.java Wed Nov 25 11:08:25 2009 -0800
381.3 @@ -0,0 +1,99 @@
381.4 +/*
381.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
381.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
381.7 + *
381.8 + * This code is free software; you can redistribute it and/or modify it
381.9 + * under the terms of the GNU General Public License version 2 only, as
381.10 + * published by the Free Software Foundation. Sun designates this
381.11 + * particular file as subject to the "Classpath" exception as provided
381.12 + * by Sun in the LICENSE file that accompanied this code.
381.13 + *
381.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
381.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
381.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
381.17 + * version 2 for more details (a copy is included in the LICENSE file that
381.18 + * accompanied this code).
381.19 + *
381.20 + * You should have received a copy of the GNU General Public License version
381.21 + * 2 along with this work; if not, write to the Free Software Foundation,
381.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
381.23 + *
381.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
381.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
381.26 + * have any questions.
381.27 + */
381.28 +
381.29 +package sun.security.ssl.krb5;
381.30 +
381.31 +import java.security.AccessControlContext;
381.32 +import java.security.Permission;
381.33 +import java.security.Principal;
381.34 +import javax.crypto.SecretKey;
381.35 +import javax.security.auth.Subject;
381.36 +import javax.security.auth.kerberos.KerberosKey;
381.37 +import javax.security.auth.kerberos.ServicePermission;
381.38 +import javax.security.auth.login.LoginException;
381.39 +
381.40 +import sun.security.jgss.GSSCaller;
381.41 +import sun.security.jgss.krb5.Krb5Util;
381.42 +import sun.security.krb5.PrincipalName;
381.43 +import sun.security.ssl.Krb5Proxy;
381.44 +
381.45 +/**
381.46 + * An implementatin of Krb5Proxy that simply delegates to the appropriate
381.47 + * Kerberos APIs.
381.48 + */
381.49 +public class Krb5ProxyImpl implements Krb5Proxy {
381.50 +
381.51 + public Krb5ProxyImpl() { }
381.52 +
381.53 + @Override
381.54 + public Subject getClientSubject(AccessControlContext acc)
381.55 + throws LoginException {
381.56 + return Krb5Util.getSubject(GSSCaller.CALLER_SSL_CLIENT, acc);
381.57 + }
381.58 +
381.59 + @Override
381.60 + public Subject getServerSubject(AccessControlContext acc)
381.61 + throws LoginException {
381.62 + return Krb5Util.getSubject(GSSCaller.CALLER_SSL_SERVER, acc);
381.63 + }
381.64 +
381.65 + @Override
381.66 + public SecretKey[] getServerKeys(AccessControlContext acc)
381.67 + throws LoginException {
381.68 + return Krb5Util.getKeys(GSSCaller.CALLER_SSL_SERVER, null, acc);
381.69 + }
381.70 +
381.71 + @Override
381.72 + public String getServerPrincipalName(SecretKey kerberosKey) {
381.73 + return ((KerberosKey)kerberosKey).getPrincipal().getName();
381.74 + }
381.75 +
381.76 + @Override
381.77 + public String getPrincipalHostName(Principal principal) {
381.78 + if (principal == null) {
381.79 + return null;
381.80 + }
381.81 + String hostName = null;
381.82 + try {
381.83 + PrincipalName princName =
381.84 + new PrincipalName(principal.getName(),
381.85 + PrincipalName.KRB_NT_SRV_HST);
381.86 + String[] nameParts = princName.getNameStrings();
381.87 + if (nameParts.length >= 2) {
381.88 + hostName = nameParts[1];
381.89 + }
381.90 + } catch (Exception e) {
381.91 + // ignore
381.92 + }
381.93 + return hostName;
381.94 + }
381.95 +
381.96 +
381.97 + @Override
381.98 + public Permission getServicePermission(String principalName,
381.99 + String action) {
381.100 + return new ServicePermission(principalName, action);
381.101 + }
381.102 +}
382.1 --- a/src/share/classes/sun/security/timestamp/HttpTimestamper.java Mon Nov 23 10:04:47 2009 +0000
382.2 +++ b/src/share/classes/sun/security/timestamp/HttpTimestamper.java Wed Nov 25 11:08:25 2009 -0800
382.3 @@ -34,6 +34,7 @@
382.4 import java.util.Set;
382.5 import java.util.Arrays;
382.6
382.7 +import sun.misc.IOUtils;
382.8 import sun.security.pkcs.*;
382.9
382.10 /**
382.11 @@ -142,25 +143,7 @@
382.12
382.13 int total = 0;
382.14 int contentLength = connection.getContentLength();
382.15 - if (contentLength != -1) {
382.16 - replyBuffer = new byte[contentLength];
382.17 - } else {
382.18 - replyBuffer = new byte[2048];
382.19 - contentLength = Integer.MAX_VALUE;
382.20 - }
382.21 -
382.22 - while (total < contentLength) {
382.23 - int count = input.read(replyBuffer, total,
382.24 - replyBuffer.length - total);
382.25 - if (count < 0)
382.26 - break;
382.27 -
382.28 - total += count;
382.29 - if (total >= replyBuffer.length && total < contentLength) {
382.30 - replyBuffer = Arrays.copyOf(replyBuffer, total * 2);
382.31 - }
382.32 - }
382.33 - replyBuffer = Arrays.copyOf(replyBuffer, total);
382.34 + replyBuffer = IOUtils.readFully(input, contentLength, false);
382.35
382.36 if (DEBUG) {
382.37 System.out.println("received timestamp response (length=" +
383.1 --- a/src/share/classes/sun/security/tools/JarSigner.java Mon Nov 23 10:04:47 2009 +0000
383.2 +++ b/src/share/classes/sun/security/tools/JarSigner.java Wed Nov 25 11:08:25 2009 -0800
383.3 @@ -1031,9 +1031,9 @@
383.4 }
383.5
383.6 if (sigfile.length() > 8) {
383.7 - sigfile = sigfile.substring(0, 8).toUpperCase();
383.8 + sigfile = sigfile.substring(0, 8).toUpperCase(Locale.ENGLISH);
383.9 } else {
383.10 - sigfile = sigfile.toUpperCase();
383.11 + sigfile = sigfile.toUpperCase(Locale.ENGLISH);
383.12 }
383.13
383.14 StringBuilder tmpSigFile = new StringBuilder(sigfile.length());
383.15 @@ -1083,8 +1083,8 @@
383.16 ZipOutputStream zos = new ZipOutputStream(ps);
383.17
383.18 /* First guess at what they might be - we don't xclude RSA ones. */
383.19 - String sfFilename = (META_INF + sigfile + ".SF").toUpperCase();
383.20 - String bkFilename = (META_INF + sigfile + ".DSA").toUpperCase();
383.21 + String sfFilename = (META_INF + sigfile + ".SF").toUpperCase(Locale.ENGLISH);
383.22 + String bkFilename = (META_INF + sigfile + ".DSA").toUpperCase(Locale.ENGLISH);
383.23
383.24 Manifest manifest = new Manifest();
383.25 Map<String,Attributes> mfEntries = manifest.getEntries();
383.26 @@ -1447,9 +1447,10 @@
383.27 * . META-INF/*.SF
383.28 * . META-INF/*.DSA
383.29 * . META-INF/*.RSA
383.30 + * . META-INF/*.EC
383.31 */
383.32 private boolean signatureRelated(String name) {
383.33 - String ucName = name.toUpperCase();
383.34 + String ucName = name.toUpperCase(Locale.ENGLISH);
383.35 if (ucName.equals(JarFile.MANIFEST_NAME) ||
383.36 ucName.equals(META_INF) ||
383.37 (ucName.startsWith(SIG_PREFIX) &&
383.38 @@ -1459,7 +1460,7 @@
383.39
383.40 if (ucName.startsWith(META_INF) &&
383.41 SignatureFileVerifier.isBlockOrSF(ucName)) {
383.42 - // .SF/.DSA/.RSA files in META-INF subdirs
383.43 + // .SF/.DSA/.RSA/.EC files in META-INF subdirs
383.44 // are not considered signature-related
383.45 return (ucName.indexOf("/") == ucName.lastIndexOf("/"));
383.46 }
383.47 @@ -1482,6 +1483,7 @@
383.48 Timestamp timestamp = signer.getTimestamp();
383.49 if (timestamp != null) {
383.50 s.append(printTimestamp(tab, timestamp));
383.51 + s.append('\n');
383.52 }
383.53 // display the certificate(s)
383.54 for (Certificate c : certs) {
383.55 @@ -2227,7 +2229,6 @@
383.56 }
383.57 BigInteger serial = certChain[0].getSerialNumber();
383.58
383.59 - String digestAlgorithm;
383.60 String signatureAlgorithm;
383.61 String keyAlgorithm = privateKey.getAlgorithm();
383.62 /*
383.63 @@ -2237,22 +2238,24 @@
383.64 if (sigalg == null) {
383.65
383.66 if (keyAlgorithm.equalsIgnoreCase("DSA"))
383.67 - digestAlgorithm = "SHA1";
383.68 + signatureAlgorithm = "SHA1withDSA";
383.69 else if (keyAlgorithm.equalsIgnoreCase("RSA"))
383.70 - digestAlgorithm = "SHA256";
383.71 - else {
383.72 + signatureAlgorithm = "SHA256withRSA";
383.73 + else if (keyAlgorithm.equalsIgnoreCase("EC"))
383.74 + signatureAlgorithm = "SHA256withECDSA";
383.75 + else
383.76 throw new RuntimeException("private key is not a DSA or "
383.77 + "RSA key");
383.78 - }
383.79 - signatureAlgorithm = digestAlgorithm + "with" + keyAlgorithm;
383.80 } else {
383.81 signatureAlgorithm = sigalg;
383.82 }
383.83
383.84 // check common invalid key/signature algorithm combinations
383.85 - String sigAlgUpperCase = signatureAlgorithm.toUpperCase();
383.86 + String sigAlgUpperCase = signatureAlgorithm.toUpperCase(Locale.ENGLISH);
383.87 if ((sigAlgUpperCase.endsWith("WITHRSA") &&
383.88 !keyAlgorithm.equalsIgnoreCase("RSA")) ||
383.89 + (sigAlgUpperCase.endsWith("WITHECDSA") &&
383.90 + !keyAlgorithm.equalsIgnoreCase("EC")) ||
383.91 (sigAlgUpperCase.endsWith("WITHDSA") &&
383.92 !keyAlgorithm.equalsIgnoreCase("DSA"))) {
383.93 throw new SignatureException
384.1 --- a/src/share/classes/sun/security/tools/KeyTool.java Mon Nov 23 10:04:47 2009 +0000
384.2 +++ b/src/share/classes/sun/security/tools/KeyTool.java Wed Nov 25 11:08:25 2009 -0800
384.3 @@ -26,6 +26,7 @@
384.4 package sun.security.tools;
384.5
384.6 import java.io.*;
384.7 +import java.security.CodeSigner;
384.8 import java.security.KeyStore;
384.9 import java.security.KeyStoreException;
384.10 import java.security.MessageDigest;
384.11 @@ -34,6 +35,7 @@
384.12 import java.security.PrivateKey;
384.13 import java.security.Security;
384.14 import java.security.Signature;
384.15 +import java.security.Timestamp;
384.16 import java.security.UnrecoverableEntryException;
384.17 import java.security.UnrecoverableKeyException;
384.18 import java.security.Principal;
384.19 @@ -46,6 +48,8 @@
384.20 import java.text.Collator;
384.21 import java.text.MessageFormat;
384.22 import java.util.*;
384.23 +import java.util.jar.JarEntry;
384.24 +import java.util.jar.JarFile;
384.25 import java.lang.reflect.Constructor;
384.26 import java.net.URL;
384.27 import java.net.URLClassLoader;
384.28 @@ -130,6 +134,7 @@
384.29 private File ksfile = null;
384.30 private InputStream ksStream = null; // keystore stream
384.31 private String sslserver = null;
384.32 + private String jarfile = null;
384.33 private KeyStore keyStore = null;
384.34 private boolean token = false;
384.35 private boolean nullStream = false;
384.36 @@ -206,7 +211,7 @@
384.37 "-providername", "-providerclass", "-providerarg",
384.38 "-providerpath", "-v", "-protected"),
384.39 PRINTCERT("Prints the content of a certificate",
384.40 - "-rfc", "-file", "-sslserver", "-v"),
384.41 + "-rfc", "-file", "-sslserver", "-jarfile", "-v"),
384.42 PRINTCERTREQ("Prints the content of a certificate request",
384.43 "-file", "-v"),
384.44 SELFCERT("Generates a self-signed certificate",
384.45 @@ -266,6 +271,7 @@
384.46 {"-srcstorepass", "<arg>", "source keystore password"},
384.47 {"-srcstoretype", "<srcstoretype>", "source keystore type"},
384.48 {"-sslserver", "<server[:port]>", "SSL server host and port"},
384.49 + {"-jarfile", "<filename>", "signed jar file"},
384.50 {"-startdate", "<startdate>", "certificate validity start date/time"},
384.51 {"-storepass", "<arg>", "keystore password"},
384.52 {"-storetype", "<storetype>", "keystore type"},
384.53 @@ -453,6 +459,8 @@
384.54 outfilename = args[++i];
384.55 } else if (collator.compare(flags, "-sslserver") == 0) {
384.56 sslserver = args[++i];
384.57 + } else if (collator.compare(flags, "-jarfile") == 0) {
384.58 + jarfile = args[++i];
384.59 } else if (collator.compare(flags, "-srckeystore") == 0) {
384.60 srcksfname = args[++i];
384.61 } else if ((collator.compare(flags, "-provider") == 0) ||
384.62 @@ -1407,7 +1415,7 @@
384.63 } else if ("RSA".equalsIgnoreCase(keyAlgName)) {
384.64 return "SHA256WithRSA";
384.65 } else if ("EC".equalsIgnoreCase(keyAlgName)) {
384.66 - return "SHA1withECDSA";
384.67 + return "SHA256withECDSA";
384.68 } else {
384.69 throw new Exception(rb.getString
384.70 ("Cannot derive signature algorithm"));
384.71 @@ -2065,7 +2073,71 @@
384.72 }
384.73
384.74 private void doPrintCert(final PrintStream out) throws Exception {
384.75 - if (sslserver != null) {
384.76 + if (jarfile != null) {
384.77 + JarFile jf = new JarFile(jarfile, true);
384.78 + Enumeration<JarEntry> entries = jf.entries();
384.79 + Set<CodeSigner> ss = new HashSet<CodeSigner>();
384.80 + byte[] buffer = new byte[8192];
384.81 + int pos = 0;
384.82 + while (entries.hasMoreElements()) {
384.83 + JarEntry je = entries.nextElement();
384.84 + InputStream is = null;
384.85 + try {
384.86 + is = jf.getInputStream(je);
384.87 + while (is.read(buffer) != -1) {
384.88 + // we just read. this will throw a SecurityException
384.89 + // if a signature/digest check fails. This also
384.90 + // populate the signers
384.91 + }
384.92 + } finally {
384.93 + if (is != null) {
384.94 + is.close();
384.95 + }
384.96 + }
384.97 + CodeSigner[] signers = je.getCodeSigners();
384.98 + if (signers != null) {
384.99 + for (CodeSigner signer: signers) {
384.100 + if (!ss.contains(signer)) {
384.101 + ss.add(signer);
384.102 + out.printf(rb.getString("Signer #%d:"), ++pos);
384.103 + out.println();
384.104 + out.println();
384.105 + out.println(rb.getString("Signature:"));
384.106 + out.println();
384.107 + for (Certificate cert: signer.getSignerCertPath().getCertificates()) {
384.108 + X509Certificate x = (X509Certificate)cert;
384.109 + if (rfc) {
384.110 + out.println(rb.getString("Certificate owner: ") + x.getSubjectDN() + "\n");
384.111 + dumpCert(x, out);
384.112 + } else {
384.113 + printX509Cert(x, out);
384.114 + }
384.115 + out.println();
384.116 + }
384.117 + Timestamp ts = signer.getTimestamp();
384.118 + if (ts != null) {
384.119 + out.println(rb.getString("Timestamp:"));
384.120 + out.println();
384.121 + for (Certificate cert: ts.getSignerCertPath().getCertificates()) {
384.122 + X509Certificate x = (X509Certificate)cert;
384.123 + if (rfc) {
384.124 + out.println(rb.getString("Certificate owner: ") + x.getSubjectDN() + "\n");
384.125 + dumpCert(x, out);
384.126 + } else {
384.127 + printX509Cert(x, out);
384.128 + }
384.129 + out.println();
384.130 + }
384.131 + }
384.132 + }
384.133 + }
384.134 + }
384.135 + }
384.136 + jf.close();
384.137 + if (ss.size() == 0) {
384.138 + out.println(rb.getString("Not a signed jar file"));
384.139 + }
384.140 + } else if (sslserver != null) {
384.141 SSLContext sc = SSLContext.getInstance("SSL");
384.142 final boolean[] certPrinted = new boolean[1];
384.143 sc.init(null, new TrustManager[] {
385.1 --- a/src/share/classes/sun/security/tools/TimestampedSigner.java Mon Nov 23 10:04:47 2009 +0000
385.2 +++ b/src/share/classes/sun/security/tools/TimestampedSigner.java Wed Nov 25 11:08:25 2009 -0800
385.3 @@ -1,5 +1,5 @@
385.4 /*
385.5 - * Copyright (c) 2007 Sun Microsystems, Inc. All Rights Reserved.
385.6 + * Copyright (c) 2007-2009 Sun Microsystems, Inc. All Rights Reserved.
385.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
385.8 *
385.9 * This code is free software; you can redistribute it and/or modify it
385.10 @@ -159,18 +159,10 @@
385.11 // "<digest>with<encryption>"
385.12 // or "<digest>with<encryption>and<mgf>"
385.13 String signatureAlgorithm = parameters.getSignatureAlgorithm();
385.14 - String digestAlgorithm = null;
385.15 - String keyAlgorithm = null;
385.16 - int with = signatureAlgorithm.indexOf("with");
385.17 - if (with > 0) {
385.18 - digestAlgorithm = signatureAlgorithm.substring(0, with);
385.19 - int and = signatureAlgorithm.indexOf("and", with + 4);
385.20 - if (and > 0) {
385.21 - keyAlgorithm = signatureAlgorithm.substring(with + 4, and);
385.22 - } else {
385.23 - keyAlgorithm = signatureAlgorithm.substring(with + 4);
385.24 - }
385.25 - }
385.26 + String keyAlgorithm =
385.27 + AlgorithmId.getEncAlgFromSigAlg(signatureAlgorithm);
385.28 + String digestAlgorithm =
385.29 + AlgorithmId.getDigAlgFromSigAlg(signatureAlgorithm);
385.30 AlgorithmId digestAlgorithmId = AlgorithmId.get(digestAlgorithm);
385.31
385.32 // Examine signer's certificate
386.1 --- a/src/share/classes/sun/security/util/DerValue.java Mon Nov 23 10:04:47 2009 +0000
386.2 +++ b/src/share/classes/sun/security/util/DerValue.java Wed Nov 25 11:08:25 2009 -0800
386.3 @@ -28,6 +28,7 @@
386.4 import java.io.*;
386.5 import java.math.BigInteger;
386.6 import java.util.Date;
386.7 +import sun.misc.IOUtils;
386.8
386.9 /**
386.10 * Represents a single DER-encoded value. DER encoding rules are a subset
386.11 @@ -382,12 +383,8 @@
386.12 if (fullyBuffered && in.available() != length)
386.13 throw new IOException("extra data given to DerValue constructor");
386.14
386.15 - byte[] bytes = new byte[length];
386.16 + byte[] bytes = IOUtils.readFully(in, length, true);
386.17
386.18 - // n.b. readFully not needed in normal fullyBuffered case
386.19 - DataInputStream dis = new DataInputStream(in);
386.20 -
386.21 - dis.readFully(bytes);
386.22 buffer = new DerInputBuffer(bytes);
386.23 return new DerInputStream(buffer);
386.24 }
387.1 --- a/src/share/classes/sun/security/util/HostnameChecker.java Mon Nov 23 10:04:47 2009 +0000
387.2 +++ b/src/share/classes/sun/security/util/HostnameChecker.java Wed Nov 25 11:08:25 2009 -0800
387.3 @@ -32,10 +32,9 @@
387.4 import java.security.cert.*;
387.5
387.6 import javax.security.auth.x500.X500Principal;
387.7 -import javax.security.auth.kerberos.KerberosPrincipal;
387.8
387.9 +import sun.security.ssl.Krb5Helper;
387.10 import sun.security.x509.X500Name;
387.11 -import sun.security.krb5.PrincipalName;
387.12
387.13 import sun.net.util.IPAddressUtil;
387.14
387.15 @@ -98,8 +97,7 @@
387.16 /**
387.17 * Perform the check for Kerberos.
387.18 */
387.19 - public static boolean match(String expectedName,
387.20 - KerberosPrincipal principal) {
387.21 + public static boolean match(String expectedName, Principal principal) {
387.22 String hostName = getServerName(principal);
387.23 return (expectedName.equalsIgnoreCase(hostName));
387.24 }
387.25 @@ -107,23 +105,8 @@
387.26 /**
387.27 * Return the Server name from Kerberos principal.
387.28 */
387.29 - public static String getServerName(KerberosPrincipal principal) {
387.30 - if (principal == null) {
387.31 - return null;
387.32 - }
387.33 - String hostName = null;
387.34 - try {
387.35 - PrincipalName princName =
387.36 - new PrincipalName(principal.getName(),
387.37 - PrincipalName.KRB_NT_SRV_HST);
387.38 - String[] nameParts = princName.getNameStrings();
387.39 - if (nameParts.length >= 2) {
387.40 - hostName = nameParts[1];
387.41 - }
387.42 - } catch (Exception e) {
387.43 - // ignore
387.44 - }
387.45 - return hostName;
387.46 + public static String getServerName(Principal principal) {
387.47 + return Krb5Helper.getPrincipalHostName(principal);
387.48 }
387.49
387.50 /**
388.1 --- a/src/share/classes/sun/security/util/Resources.java Mon Nov 23 10:04:47 2009 +0000
388.2 +++ b/src/share/classes/sun/security/util/Resources.java Wed Nov 25 11:08:25 2009 -0800
388.3 @@ -162,6 +162,8 @@
388.4 "source keystore type"}, //-srcstoretype
388.5 {"SSL server host and port",
388.6 "SSL server host and port"}, //-sslserver
388.7 + {"signed jar file",
388.8 + "signed jar file"}, //=jarfile
388.9 {"certificate validity start date/time",
388.10 "certificate validity start date/time"}, //-startdate
388.11 {"keystore password",
388.12 @@ -370,6 +372,13 @@
388.13
388.14 {"***************** WARNING WARNING WARNING *****************",
388.15 "***************** WARNING WARNING WARNING *****************"},
388.16 + {"Signer #%d:", "Signer #%d:"},
388.17 + {"Timestamp:", "Timestamp:"},
388.18 + {"Signature:", "Signature:"},
388.19 + {"Certificate owner: ", "Certificate owner: "},
388.20 + {"Not a signed jar file", "Not a signed jar file"},
388.21 + {"No certificate from the SSL server",
388.22 + "No certificate from the SSL server"},
388.23
388.24 // Translators of the following 5 pairs, ATTENTION:
388.25 // the next 5 string pairs are meant to be combined into 2 paragraphs,
389.1 --- a/src/share/classes/sun/security/util/SignatureFileVerifier.java Mon Nov 23 10:04:47 2009 +0000
389.2 +++ b/src/share/classes/sun/security/util/SignatureFileVerifier.java Wed Nov 25 11:08:25 2009 -0800
389.3 @@ -1,5 +1,5 @@
389.4 /*
389.5 - * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
389.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
389.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
389.8 *
389.9 * This code is free software; you can redistribute it and/or modify it
389.10 @@ -54,14 +54,14 @@
389.11 ("-DIGEST-" + ManifestDigester.MF_MAIN_ATTRS).toUpperCase
389.12 (Locale.ENGLISH);
389.13
389.14 - /** the PKCS7 block for this .DSA/.RSA file */
389.15 + /** the PKCS7 block for this .DSA/.RSA/.EC file */
389.16 private PKCS7 block;
389.17
389.18 /** the raw bytes of the .SF file */
389.19 private byte sfBytes[];
389.20
389.21 /** the name of the signature block file, uppercased and without
389.22 - * the extension (.DSA/.RSA)
389.23 + * the extension (.DSA/.RSA/.EC)
389.24 */
389.25 private String name;
389.26
389.27 @@ -80,7 +80,7 @@
389.28 /**
389.29 * Create the named SignatureFileVerifier.
389.30 *
389.31 - * @param name the name of the signature block file (.DSA/.RSA)
389.32 + * @param name the name of the signature block file (.DSA/.RSA/.EC)
389.33 *
389.34 * @param rawBytes the raw bytes of the signature block file
389.35 */
389.36 @@ -148,7 +148,8 @@
389.37 */
389.38 public static boolean isBlockOrSF(String s) {
389.39 // we currently only support DSA and RSA PKCS7 blocks
389.40 - if (s.endsWith(".SF") || s.endsWith(".DSA") || s.endsWith(".RSA")) {
389.41 + if (s.endsWith(".SF") || s.endsWith(".DSA") ||
389.42 + s.endsWith(".RSA") || s.endsWith(".EC")) {
389.43 return true;
389.44 }
389.45 return false;
390.1 --- a/src/share/classes/sun/security/validator/SimpleValidator.java Mon Nov 23 10:04:47 2009 +0000
390.2 +++ b/src/share/classes/sun/security/validator/SimpleValidator.java Wed Nov 25 11:08:25 2009 -0800
390.3 @@ -40,6 +40,8 @@
390.4 import sun.security.util.DerOutputStream;
390.5 import sun.security.util.ObjectIdentifier;
390.6
390.7 +import sun.security.provider.certpath.AlgorithmChecker;
390.8 +
390.9 /**
390.10 * A simple validator implementation. It is based on code from the JSSE
390.11 * X509TrustManagerImpl. This implementation is designed for compatibility with
390.12 @@ -134,6 +136,13 @@
390.13 X509Certificate issuerCert = chain[i + 1];
390.14 X509Certificate cert = chain[i];
390.15
390.16 + // check certificate algorithm
390.17 + try {
390.18 + AlgorithmChecker.check(cert);
390.19 + } catch (CertPathValidatorException cpve) {
390.20 + throw new ValidatorException
390.21 + (ValidatorException.T_ALGORITHM_DISABLED, cert, cpve);
390.22 + }
390.23
390.24 // no validity check for code signing certs
390.25 if ((variant.equals(VAR_CODE_SIGNING) == false)
391.1 --- a/src/share/classes/sun/security/validator/ValidatorException.java Mon Nov 23 10:04:47 2009 +0000
391.2 +++ b/src/share/classes/sun/security/validator/ValidatorException.java Wed Nov 25 11:08:25 2009 -0800
391.3 @@ -1,5 +1,5 @@
391.4 /*
391.5 - * Copyright 2002-2003 Sun Microsystems, Inc. All Rights Reserved.
391.6 + * Copyright 2002-2009 Sun Microsystems, Inc. All Rights Reserved.
391.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
391.8 *
391.9 * This code is free software; you can redistribute it and/or modify it
391.10 @@ -55,6 +55,9 @@
391.11 public final static Object T_NAME_CHAINING =
391.12 "Certificate chaining error";
391.13
391.14 + public final static Object T_ALGORITHM_DISABLED =
391.15 + "Certificate signature algorithm disabled";
391.16 +
391.17 private Object type;
391.18 private X509Certificate cert;
391.19
392.1 --- a/src/share/classes/sun/security/x509/AlgorithmId.java Mon Nov 23 10:04:47 2009 +0000
392.2 +++ b/src/share/classes/sun/security/x509/AlgorithmId.java Wed Nov 25 11:08:25 2009 -0800
392.3 @@ -883,4 +883,53 @@
392.4 nameTable.put(pbeWithSHA1AndDESede_oid, "PBEWithSHA1AndDESede");
392.5 nameTable.put(pbeWithSHA1AndRC2_40_oid, "PBEWithSHA1AndRC2_40");
392.6 }
392.7 +
392.8 + /**
392.9 + * Creates a signature algorithm name from a digest algorithm
392.10 + * name and a encryption algorithm name.
392.11 + */
392.12 + public static String makeSigAlg(String digAlg, String encAlg) {
392.13 + digAlg = digAlg.replace("-", "").toUpperCase(Locale.ENGLISH);
392.14 + if (digAlg.equalsIgnoreCase("SHA")) digAlg = "SHA1";
392.15 +
392.16 + encAlg = encAlg.toUpperCase(Locale.ENGLISH);
392.17 + if (encAlg.equals("EC")) encAlg = "ECDSA";
392.18 +
392.19 + return digAlg + "with" + encAlg;
392.20 + }
392.21 +
392.22 + /**
392.23 + * Extracts the encryption algorithm name from a signature
392.24 + * algorithm name.
392.25 + */
392.26 + public static String getEncAlgFromSigAlg(String signatureAlgorithm) {
392.27 + signatureAlgorithm = signatureAlgorithm.toUpperCase(Locale.ENGLISH);
392.28 + int with = signatureAlgorithm.indexOf("WITH");
392.29 + String keyAlgorithm = null;
392.30 + if (with > 0) {
392.31 + int and = signatureAlgorithm.indexOf("AND", with + 4);
392.32 + if (and > 0) {
392.33 + keyAlgorithm = signatureAlgorithm.substring(with + 4, and);
392.34 + } else {
392.35 + keyAlgorithm = signatureAlgorithm.substring(with + 4);
392.36 + }
392.37 + if (keyAlgorithm.equalsIgnoreCase("ECDSA")) {
392.38 + keyAlgorithm = "EC";
392.39 + }
392.40 + }
392.41 + return keyAlgorithm;
392.42 + }
392.43 +
392.44 + /**
392.45 + * Extracts the digest algorithm name from a signature
392.46 + * algorithm name.
392.47 + */
392.48 + public static String getDigAlgFromSigAlg(String signatureAlgorithm) {
392.49 + signatureAlgorithm = signatureAlgorithm.toUpperCase(Locale.ENGLISH);
392.50 + int with = signatureAlgorithm.indexOf("WITH");
392.51 + if (with > 0) {
392.52 + return signatureAlgorithm.substring(0, with);
392.53 + }
392.54 + return null;
392.55 + }
392.56 }
393.1 --- a/src/share/classes/sun/swing/SwingLazyValue.java Mon Nov 23 10:04:47 2009 +0000
393.2 +++ b/src/share/classes/sun/swing/SwingLazyValue.java Wed Nov 25 11:08:25 2009 -0800
393.3 @@ -26,6 +26,9 @@
393.4
393.5 import java.lang.reflect.Constructor;
393.6 import java.lang.reflect.Method;
393.7 +import java.lang.reflect.AccessibleObject;
393.8 +import java.security.AccessController;
393.9 +import java.security.PrivilegedAction;
393.10 import javax.swing.UIDefaults;
393.11
393.12 /**
393.13 @@ -65,13 +68,15 @@
393.14 if (methodName != null) {
393.15 Class[] types = getClassArray(args);
393.16 Method m = c.getMethod(methodName, types);
393.17 + makeAccessible(m);
393.18 return m.invoke(c, args);
393.19 } else {
393.20 Class[] types = getClassArray(args);
393.21 Constructor constructor = c.getConstructor(types);
393.22 + makeAccessible(constructor);
393.23 return constructor.newInstance(args);
393.24 }
393.25 - } catch(Exception e) {
393.26 + } catch (Exception e) {
393.27 // Ideally we would throw an exception, unfortunately
393.28 // often times there are errors as an initial look and
393.29 // feel is loaded before one can be switched. Perhaps a
393.30 @@ -81,6 +86,15 @@
393.31 return null;
393.32 }
393.33
393.34 + private void makeAccessible(final AccessibleObject object) {
393.35 + AccessController.doPrivileged(new PrivilegedAction<Void>() {
393.36 + public Void run() {
393.37 + object.setAccessible(true);
393.38 + return null;
393.39 + }
393.40 + });
393.41 + }
393.42 +
393.43 private Class[] getClassArray(Object[] args) {
393.44 Class[] types = null;
393.45 if (args!=null) {
394.1 --- a/src/share/classes/sun/swing/SwingUtilities2.java Mon Nov 23 10:04:47 2009 +0000
394.2 +++ b/src/share/classes/sun/swing/SwingUtilities2.java Wed Nov 25 11:08:25 2009 -0800
394.3 @@ -1807,22 +1807,4 @@
394.4 boolean three) {
394.5 return liesIn(rect, p, false, false, three);
394.6 }
394.7 -
394.8 - /**
394.9 - * Returns the {@code JViewport} instance for the {@code component}
394.10 - * or {@code null}.
394.11 - *
394.12 - * @return the {@code JViewport} instance for the {@code component}
394.13 - * or {@code null}
394.14 - * @throws NullPointerException if {@code component} is {@code null}
394.15 - */
394.16 - public static JViewport getViewport(Component component) {
394.17 - do {
394.18 - component = component.getParent();
394.19 - if (component instanceof JViewport) {
394.20 - return (JViewport) component;
394.21 - }
394.22 - } while(component instanceof JLayer);
394.23 - return null;
394.24 - }
394.25 }
395.1 --- a/src/share/classes/sun/text/bidi/BidiBase.java Mon Nov 23 10:04:47 2009 +0000
395.2 +++ b/src/share/classes/sun/text/bidi/BidiBase.java Wed Nov 25 11:08:25 2009 -0800
395.3 @@ -52,10 +52,11 @@
395.4
395.5 package sun.text.bidi;
395.6
395.7 -import java.awt.font.TextAttribute;
395.8 -import java.awt.font.NumericShaper;
395.9 import java.io.IOException;
395.10 import java.lang.reflect.Array;
395.11 +import java.lang.reflect.Field;
395.12 +import java.lang.reflect.Method;
395.13 +import java.lang.reflect.InvocationTargetException;
395.14 import java.text.AttributedCharacterIterator;
395.15 import java.text.Bidi;
395.16 import java.util.Arrays;
395.17 @@ -2689,12 +2690,13 @@
395.18 public void setPara(AttributedCharacterIterator paragraph)
395.19 {
395.20 byte paraLvl;
395.21 - Boolean runDirection = (Boolean) paragraph.getAttribute(TextAttribute.RUN_DIRECTION);
395.22 - NumericShaper shaper = (NumericShaper) paragraph.getAttribute(TextAttribute.NUMERIC_SHAPING);
395.23 + Boolean runDirection =
395.24 + (Boolean) paragraph.getAttribute(TextAttributeConstants.RUN_DIRECTION);
395.25 + Object shaper = paragraph.getAttribute(TextAttributeConstants.NUMERIC_SHAPING);
395.26 if (runDirection == null) {
395.27 paraLvl = INTERNAL_LEVEL_DEFAULT_LTR;
395.28 } else {
395.29 - paraLvl = (runDirection.equals(TextAttribute.RUN_DIRECTION_LTR)) ?
395.30 + paraLvl = (runDirection.equals(TextAttributeConstants.RUN_DIRECTION_LTR)) ?
395.31 (byte)Bidi.DIRECTION_LEFT_TO_RIGHT : (byte)Bidi.DIRECTION_RIGHT_TO_LEFT;
395.32 }
395.33
395.34 @@ -2706,7 +2708,8 @@
395.35 char ch = paragraph.first();
395.36 while (ch != AttributedCharacterIterator.DONE) {
395.37 txt[i] = ch;
395.38 - Integer embedding = (Integer) paragraph.getAttribute(TextAttribute.BIDI_EMBEDDING);
395.39 + Integer embedding =
395.40 + (Integer) paragraph.getAttribute(TextAttributeConstants.BIDI_EMBEDDING);
395.41 if (embedding != null) {
395.42 byte level = embedding.byteValue();
395.43 if (level == 0) {
395.44 @@ -2724,7 +2727,7 @@
395.45 }
395.46
395.47 if (shaper != null) {
395.48 - shaper.shape(txt, 0, len);
395.49 + NumericShapings.shape(shaper, txt, 0, len);
395.50 }
395.51 setPara(txt, paraLvl, lvls);
395.52 }
395.53 @@ -3441,4 +3444,106 @@
395.54 return buf.toString();
395.55 }
395.56
395.57 + /**
395.58 + * A class that provides access to constants defined by
395.59 + * java.awt.font.TextAttribute without creating a static dependency.
395.60 + */
395.61 + private static class TextAttributeConstants {
395.62 + private static final Class<?> clazz = getClass("java.awt.font.TextAttribute");
395.63 +
395.64 + /**
395.65 + * TextAttribute instances (or a fake Attribute type if
395.66 + * java.awt.font.TextAttribute is not present)
395.67 + */
395.68 + static final AttributedCharacterIterator.Attribute RUN_DIRECTION =
395.69 + getTextAttribute("RUN_DIRECTION");
395.70 + static final Boolean RUN_DIRECTION_LTR =
395.71 + (Boolean)getStaticField(clazz, "RUN_DIRECTION_LTR");
395.72 + static final AttributedCharacterIterator.Attribute NUMERIC_SHAPING =
395.73 + getTextAttribute("NUMERIC_SHAPING");
395.74 + static final AttributedCharacterIterator.Attribute BIDI_EMBEDDING =
395.75 + getTextAttribute("BIDI_EMBEDDING");
395.76 +
395.77 + private static Class<?> getClass(String name) {
395.78 + try {
395.79 + return Class.forName(name, true, null);
395.80 + } catch (ClassNotFoundException e) {
395.81 + return null;
395.82 + }
395.83 + }
395.84 +
395.85 + private static Object getStaticField(Class<?> clazz, String name) {
395.86 + if (clazz == null) {
395.87 + // fake attribute
395.88 + return new AttributedCharacterIterator.Attribute(name) { };
395.89 + } else {
395.90 + try {
395.91 + Field f = clazz.getField(name);
395.92 + return f.get(null);
395.93 + } catch (NoSuchFieldException x) {
395.94 + throw new AssertionError(x);
395.95 + } catch (IllegalAccessException x) {
395.96 + throw new AssertionError(x);
395.97 + }
395.98 + }
395.99 + }
395.100 +
395.101 + private static AttributedCharacterIterator.Attribute
395.102 + getTextAttribute(String name)
395.103 + {
395.104 + return (AttributedCharacterIterator.Attribute)getStaticField(clazz, name);
395.105 + }
395.106 + }
395.107 +
395.108 + /**
395.109 + * A class that provides access to java.awt.font.NumericShaping without
395.110 + * creating a static dependency.
395.111 + */
395.112 + private static class NumericShapings {
395.113 + private static final Class<?> clazz =
395.114 + getClass("java.awt.font.NumericShaper");
395.115 + private static final Method shapeMethod =
395.116 + getMethod(clazz, "shape", char[].class, int.class, int.class);
395.117 +
395.118 + private static Class<?> getClass(String name) {
395.119 + try {
395.120 + return Class.forName(name, true, null);
395.121 + } catch (ClassNotFoundException e) {
395.122 + return null;
395.123 + }
395.124 + }
395.125 +
395.126 + private static Method getMethod(Class<?> clazz,
395.127 + String name,
395.128 + Class<?>... paramTypes)
395.129 + {
395.130 + if (clazz != null) {
395.131 + try {
395.132 + return clazz.getMethod(name, paramTypes);
395.133 + } catch (NoSuchMethodException e) {
395.134 + throw new AssertionError(e);
395.135 + }
395.136 + } else {
395.137 + return null;
395.138 + }
395.139 + }
395.140 +
395.141 + /**
395.142 + * Invokes NumericShaping shape(text,start,count) method.
395.143 + */
395.144 + static void shape(Object shaper, char[] text, int start, int count) {
395.145 + if (shapeMethod == null)
395.146 + throw new AssertionError("Should not get here");
395.147 + try {
395.148 + shapeMethod.invoke(shaper, text, start, count);
395.149 + } catch (InvocationTargetException e) {
395.150 + Throwable cause = e.getCause();
395.151 + if (cause instanceof RuntimeException)
395.152 + throw (RuntimeException)cause;
395.153 + throw new AssertionError(e);
395.154 + } catch (IllegalAccessException iae) {
395.155 + throw new AssertionError(iae);
395.156 + }
395.157 + }
395.158 + }
395.159 }
396.1 --- a/src/share/classes/sun/tools/jar/SignatureFile.java Mon Nov 23 10:04:47 2009 +0000
396.2 +++ b/src/share/classes/sun/tools/jar/SignatureFile.java Wed Nov 25 11:08:25 2009 -0800
396.3 @@ -1,5 +1,5 @@
396.4 /*
396.5 - * Copyright 1996-2003 Sun Microsystems, Inc. All Rights Reserved.
396.6 + * Copyright 1996-2009 Sun Microsystems, Inc. All Rights Reserved.
396.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
396.8 *
396.9 * This code is free software; you can redistribute it and/or modify it
396.10 @@ -34,6 +34,7 @@
396.11 import sun.misc.BASE64Decoder;
396.12
396.13 import sun.security.pkcs.*;
396.14 +import sun.security.x509.AlgorithmId;
396.15
396.16 /**
396.17 * <p>A signature file as defined in the <a
396.18 @@ -103,7 +104,7 @@
396.19 if (name.length() > 8 || name.indexOf('.') != -1) {
396.20 throw new JarException("invalid file name");
396.21 }
396.22 - rawName = name.toUpperCase();
396.23 + rawName = name.toUpperCase(Locale.ENGLISH);
396.24 }
396.25 }
396.26
396.27 @@ -217,7 +218,8 @@
396.28 if (signatureBlock != null) {
396.29 SignerInfo info = signatureBlock.getSignerInfos()[0];
396.30 suffix = info.getDigestEncryptionAlgorithmId().getName();
396.31 - suffix = suffix.substring(suffix.length() - 3);
396.32 + String temp = AlgorithmId.getEncAlgFromSigAlg(suffix);
396.33 + if (temp != null) suffix = temp;
396.34 }
396.35 return "META-INF/" + rawName + "." + suffix;
396.36 }
397.1 --- a/src/share/classes/sun/util/calendar/ZoneInfoFile.java Mon Nov 23 10:04:47 2009 +0000
397.2 +++ b/src/share/classes/sun/util/calendar/ZoneInfoFile.java Wed Nov 25 11:08:25 2009 -0800
397.3 @@ -1,5 +1,5 @@
397.4 /*
397.5 - * Copyright 2000-2006 Sun Microsystems, Inc. All Rights Reserved.
397.6 + * Copyright 2000-2009 Sun Microsystems, Inc. All Rights Reserved.
397.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
397.8 *
397.9 * This code is free software; you can redistribute it and/or modify it
397.10 @@ -472,6 +472,18 @@
397.11
397.12 private static Map<String, ZoneInfo> zoneInfoObjects = null;
397.13
397.14 + private static final String ziDir;
397.15 + static {
397.16 + String zi = (String) AccessController.doPrivileged(
397.17 + new sun.security.action.GetPropertyAction("java.home"))
397.18 + + File.separator + "lib" + File.separator + "zi";
397.19 + try {
397.20 + zi = new File(zi).getCanonicalPath();
397.21 + } catch (Exception e) {
397.22 + }
397.23 + ziDir = zi;
397.24 + }
397.25 +
397.26 /**
397.27 * Converts the given time zone ID to a platform dependent path
397.28 * name. For example, "America/Los_Angeles" is converted to
397.29 @@ -576,20 +588,7 @@
397.30 return null;
397.31 }
397.32
397.33 - int index;
397.34 - for (index = 0; index < JAVAZI_LABEL.length; index++) {
397.35 - if (buf[index] != JAVAZI_LABEL[index]) {
397.36 - System.err.println("ZoneInfo: wrong magic number: " + id);
397.37 - return null;
397.38 - }
397.39 - }
397.40 -
397.41 - if (buf[index++] > JAVAZI_VERSION) {
397.42 - System.err.println("ZoneInfo: incompatible version ("
397.43 - + buf[index - 1] + "): " + id);
397.44 - return null;
397.45 - }
397.46 -
397.47 + int index = 0;
397.48 int filesize = buf.length;
397.49 int rawOffset = 0;
397.50 int dstSavings = 0;
397.51 @@ -600,6 +599,18 @@
397.52 int[] simpleTimeZoneParams = null;
397.53
397.54 try {
397.55 + for (index = 0; index < JAVAZI_LABEL.length; index++) {
397.56 + if (buf[index] != JAVAZI_LABEL[index]) {
397.57 + System.err.println("ZoneInfo: wrong magic number: " + id);
397.58 + return null;
397.59 + }
397.60 + }
397.61 + if (buf[index++] > JAVAZI_VERSION) {
397.62 + System.err.println("ZoneInfo: incompatible version ("
397.63 + + buf[index - 1] + "): " + id);
397.64 + return null;
397.65 + }
397.66 +
397.67 while (index < filesize) {
397.68 byte tag = buf[index++];
397.69 int len = ((buf[index++] & 0xFF) << 8) + (buf[index++] & 0xFF);
397.70 @@ -1017,30 +1028,33 @@
397.71 * Reads the specified file under <java.home>/lib/zi into a buffer.
397.72 * @return the buffer, or null if any I/O error occurred.
397.73 */
397.74 - private static byte[] readZoneInfoFile(String fileName) {
397.75 + private static byte[] readZoneInfoFile(final String fileName) {
397.76 byte[] buffer = null;
397.77
397.78 try {
397.79 - String homeDir = AccessController.doPrivileged(
397.80 - new sun.security.action.GetPropertyAction("java.home"));
397.81 - final String fname = homeDir + File.separator + "lib" + File.separator
397.82 - + "zi" + File.separator + fileName;
397.83 buffer = (byte[]) AccessController.doPrivileged(new PrivilegedExceptionAction() {
397.84 public Object run() throws IOException {
397.85 - File file = new File(fname);
397.86 - if (!file.canRead()) {
397.87 + File file = new File(ziDir, fileName);
397.88 + if (!file.exists() || !file.isFile()) {
397.89 return null;
397.90 }
397.91 - int filesize = (int)file.length();
397.92 - byte[] buf = new byte[filesize];
397.93 -
397.94 - FileInputStream fis = new FileInputStream(file);
397.95 -
397.96 - if (fis.read(buf) != filesize) {
397.97 - fis.close();
397.98 - throw new IOException("read error on " + fname);
397.99 + file = file.getCanonicalFile();
397.100 + String path = file.getCanonicalPath();
397.101 + byte[] buf = null;
397.102 + if (path != null && path.startsWith(ziDir)) {
397.103 + int filesize = (int)file.length();
397.104 + if (filesize > 0) {
397.105 + FileInputStream fis = new FileInputStream(file);
397.106 + buf = new byte[filesize];
397.107 + try {
397.108 + if (fis.read(buf) != filesize) {
397.109 + throw new IOException("read error on " + fileName);
397.110 + }
397.111 + } finally {
397.112 + fis.close();
397.113 + }
397.114 + }
397.115 }
397.116 - fis.close();
397.117 return buf;
397.118 }
397.119 });
398.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
398.2 +++ b/src/share/classes/sun/util/logging/LoggingProxy.java Wed Nov 25 11:08:25 2009 -0800
398.3 @@ -0,0 +1,63 @@
398.4 +/*
398.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
398.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
398.7 + *
398.8 + * This code is free software; you can redistribute it and/or modify it
398.9 + * under the terms of the GNU General Public License version 2 only, as
398.10 + * published by the Free Software Foundation. Sun designates this
398.11 + * particular file as subject to the "Classpath" exception as provided
398.12 + * by Sun in the LICENSE file that accompanied this code.
398.13 + *
398.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
398.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
398.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
398.17 + * version 2 for more details (a copy is included in the LICENSE file that
398.18 + * accompanied this code).
398.19 + *
398.20 + * You should have received a copy of the GNU General Public License version
398.21 + * 2 along with this work; if not, write to the Free Software Foundation,
398.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
398.23 + *
398.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
398.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
398.26 + * have any questions.
398.27 + */
398.28 +
398.29 +
398.30 +package sun.util.logging;
398.31 +
398.32 +/**
398.33 + * A proxy interface for the java.util.logging support.
398.34 + *
398.35 + * @see sun.util.logging.LoggingSupport
398.36 + */
398.37 +public interface LoggingProxy {
398.38 + // Methods to bridge java.util.logging.Logger methods
398.39 + public Object getLogger(String name);
398.40 +
398.41 + public Object getLevel(Object logger);
398.42 +
398.43 + public void setLevel(Object logger, Object newLevel);
398.44 +
398.45 + public boolean isLoggable(Object logger, Object level);
398.46 +
398.47 + public void log(Object logger, Object level, String msg);
398.48 +
398.49 + public void log(Object logger, Object level, String msg, Throwable t);
398.50 +
398.51 + public void log(Object logger, Object level, String msg, Object... params);
398.52 +
398.53 + // Methods to bridge java.util.logging.LoggingMXBean methods
398.54 + public java.util.List<String> getLoggerNames();
398.55 +
398.56 + public String getLoggerLevel(String loggerName);
398.57 +
398.58 + public void setLoggerLevel(String loggerName, String levelName);
398.59 +
398.60 + public String getParentLoggerName(String loggerName);
398.61 +
398.62 + // Methods to bridge Level.parse() and Level.getName() method
398.63 + public Object parseLevel(String levelName);
398.64 +
398.65 + public String getLevelName(Object level);
398.66 +}
399.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
399.2 +++ b/src/share/classes/sun/util/logging/LoggingSupport.java Wed Nov 25 11:08:25 2009 -0800
399.3 @@ -0,0 +1,141 @@
399.4 +/*
399.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
399.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
399.7 + *
399.8 + * This code is free software; you can redistribute it and/or modify it
399.9 + * under the terms of the GNU General Public License version 2 only, as
399.10 + * published by the Free Software Foundation. Sun designates this
399.11 + * particular file as subject to the "Classpath" exception as provided
399.12 + * by Sun in the LICENSE file that accompanied this code.
399.13 + *
399.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
399.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
399.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
399.17 + * version 2 for more details (a copy is included in the LICENSE file that
399.18 + * accompanied this code).
399.19 + *
399.20 + * You should have received a copy of the GNU General Public License version
399.21 + * 2 along with this work; if not, write to the Free Software Foundation,
399.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
399.23 + *
399.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
399.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
399.26 + * have any questions.
399.27 + */
399.28 +
399.29 +
399.30 +package sun.util.logging;
399.31 +
399.32 +import java.lang.reflect.Field;
399.33 +import java.security.AccessController;
399.34 +import java.security.PrivilegedAction;
399.35 +
399.36 +/**
399.37 + * Internal API to support JRE implementation to detect if the java.util.logging
399.38 + * support is available but with no dependency on the java.util.logging
399.39 + * classes. This LoggingSupport class provides several static methods to
399.40 + * access the java.util.logging functionality that requires the caller
399.41 + * to ensure that the logging support is {@linkplain #isAvailable available}
399.42 + * before invoking it.
399.43 + *
399.44 + * @see sun.util.logging.PlatformLogger if you want to log messages even
399.45 + * if the logging support is not available
399.46 + */
399.47 +public class LoggingSupport {
399.48 + private LoggingSupport() { }
399.49 +
399.50 + private static final LoggingProxy proxy =
399.51 + AccessController.doPrivileged(new PrivilegedAction<LoggingProxy>() {
399.52 + public LoggingProxy run() {
399.53 + try {
399.54 + // create a LoggingProxyImpl instance when
399.55 + // java.util.logging classes exist
399.56 + Class<?> c = Class.forName("java.util.logging.LoggingProxyImpl", true, null);
399.57 + Field f = c.getDeclaredField("INSTANCE");
399.58 + f.setAccessible(true);
399.59 + return (LoggingProxy) f.get(null);
399.60 + } catch (ClassNotFoundException cnf) {
399.61 + return null;
399.62 + } catch (NoSuchFieldException e) {
399.63 + throw new AssertionError(e);
399.64 + } catch (IllegalAccessException e) {
399.65 + throw new AssertionError(e);
399.66 + }
399.67 + }});
399.68 +
399.69 + /**
399.70 + * Returns true if java.util.logging support is available.
399.71 + */
399.72 + public static boolean isAvailable() {
399.73 + return proxy != null;
399.74 + }
399.75 +
399.76 + private static void ensureAvailable() {
399.77 + if (proxy == null)
399.78 + throw new AssertionError("Should not here");
399.79 + }
399.80 +
399.81 + public static java.util.List<String> getLoggerNames() {
399.82 + ensureAvailable();
399.83 + return proxy.getLoggerNames();
399.84 + }
399.85 + public static String getLoggerLevel(String loggerName) {
399.86 + ensureAvailable();
399.87 + return proxy.getLoggerLevel(loggerName);
399.88 + }
399.89 +
399.90 + public static void setLoggerLevel(String loggerName, String levelName) {
399.91 + ensureAvailable();
399.92 + proxy.setLoggerLevel(loggerName, levelName);
399.93 + }
399.94 +
399.95 + public static String getParentLoggerName(String loggerName) {
399.96 + ensureAvailable();
399.97 + return proxy.getParentLoggerName(loggerName);
399.98 + }
399.99 +
399.100 + public static Object getLogger(String name) {
399.101 + ensureAvailable();
399.102 + return proxy.getLogger(name);
399.103 + }
399.104 +
399.105 + public static Object getLevel(Object logger) {
399.106 + ensureAvailable();
399.107 + return proxy.getLevel(logger);
399.108 + }
399.109 +
399.110 + public static void setLevel(Object logger, Object newLevel) {
399.111 + ensureAvailable();
399.112 + proxy.setLevel(logger, newLevel);
399.113 + }
399.114 +
399.115 + public static boolean isLoggable(Object logger, Object level) {
399.116 + ensureAvailable();
399.117 + return proxy.isLoggable(logger,level);
399.118 + }
399.119 +
399.120 + public static void log(Object logger, Object level, String msg) {
399.121 + ensureAvailable();
399.122 + proxy.log(logger, level, msg);
399.123 + }
399.124 +
399.125 + public static void log(Object logger, Object level, String msg, Throwable t) {
399.126 + ensureAvailable();
399.127 + proxy.log(logger, level, msg, t);
399.128 + }
399.129 +
399.130 + public static void log(Object logger, Object level, String msg, Object... params) {
399.131 + ensureAvailable();
399.132 + proxy.log(logger, level, msg, params);
399.133 + }
399.134 +
399.135 + public static Object parseLevel(String levelName) {
399.136 + ensureAvailable();
399.137 + return proxy.parseLevel(levelName);
399.138 + }
399.139 +
399.140 + public static String getLevelName(Object level) {
399.141 + ensureAvailable();
399.142 + return proxy.getLevelName(level);
399.143 + }
399.144 +}
400.1 --- a/src/share/classes/sun/util/logging/PlatformLogger.java Mon Nov 23 10:04:47 2009 +0000
400.2 +++ b/src/share/classes/sun/util/logging/PlatformLogger.java Wed Nov 25 11:08:25 2009 -0800
400.3 @@ -136,7 +136,7 @@
400.4 * This method is called from LogManager.readPrimordialConfiguration().
400.5 */
400.6 public static synchronized void redirectPlatformLoggers() {
400.7 - if (loggingEnabled || !JavaLogger.supported) return;
400.8 + if (loggingEnabled || !LoggingSupport.isAvailable()) return;
400.9
400.10 loggingEnabled = true;
400.11 for (Map.Entry<String, WeakReference<PlatformLogger>> entry : loggers.entrySet()) {
400.12 @@ -487,73 +487,22 @@
400.13 * java.util.logging.Logger object.
400.14 */
400.15 static class JavaLogger extends LoggerProxy {
400.16 - private static final boolean supported;
400.17 - private static final Class<?> loggerClass;
400.18 - private static final Class<?> levelClass;
400.19 - private static final Method getLoggerMethod;
400.20 - private static final Method setLevelMethod;
400.21 - private static final Method getLevelMethod;
400.22 - private static final Method isLoggableMethod;
400.23 - private static final Method logMethod;
400.24 - private static final Method logThrowMethod;
400.25 - private static final Method logParamsMethod;
400.26 private static final Map<Integer, Object> levelObjects =
400.27 new HashMap<Integer, Object>();
400.28
400.29 static {
400.30 - loggerClass = getClass("java.util.logging.Logger");
400.31 - levelClass = getClass("java.util.logging.Level");
400.32 - getLoggerMethod = getMethod(loggerClass, "getLogger", String.class);
400.33 - setLevelMethod = getMethod(loggerClass, "setLevel", levelClass);
400.34 - getLevelMethod = getMethod(loggerClass, "getLevel");
400.35 - isLoggableMethod = getMethod(loggerClass, "isLoggable", levelClass);
400.36 - logMethod = getMethod(loggerClass, "log", levelClass, String.class);
400.37 - logThrowMethod = getMethod(loggerClass, "log", levelClass, String.class, Throwable.class);
400.38 - logParamsMethod = getMethod(loggerClass, "log", levelClass, String.class, Object[].class);
400.39 - supported = (loggerClass != null && levelClass != null && getLoggerMethod != null &&
400.40 - getLevelMethod != null && setLevelMethod != null &&
400.41 - logMethod != null && logThrowMethod != null && logParamsMethod != null);
400.42 - if (supported) {
400.43 + if (LoggingSupport.isAvailable()) {
400.44 // initialize the map to Level objects
400.45 getLevelObjects();
400.46 }
400.47 }
400.48
400.49 - private static Class<?> getClass(String name) {
400.50 - try {
400.51 - return Class.forName(name, true, null);
400.52 - } catch (ClassNotFoundException e) {
400.53 - return null;
400.54 - }
400.55 - }
400.56 -
400.57 - private static Method getMethod(Class<?> cls, String name, Class<?>... parameterTypes) {
400.58 - if (cls == null) return null;
400.59 -
400.60 - try {
400.61 - return cls.getMethod(name, parameterTypes);
400.62 - } catch (NoSuchMethodException e) {
400.63 - throw new AssertionError(e);
400.64 - }
400.65 - }
400.66 -
400.67 - private static Object invoke(Method m, Object obj, Object... params) {
400.68 - try {
400.69 - return m.invoke(obj, params);
400.70 - } catch (IllegalAccessException e) {
400.71 - throw new AssertionError(e);
400.72 - } catch (InvocationTargetException e) {
400.73 - throw new AssertionError(e);
400.74 - }
400.75 - }
400.76 -
400.77 private static void getLevelObjects() {
400.78 // get all java.util.logging.Level objects
400.79 - Method parseLevelMethod = getMethod(levelClass, "parse", String.class);
400.80 int[] levelArray = new int[] {OFF, SEVERE, WARNING, INFO, CONFIG, FINE, FINER, FINEST, ALL};
400.81 for (int l : levelArray) {
400.82 - Object o = invoke(parseLevelMethod, null, getLevelName(l));
400.83 - levelObjects.put(l, o);
400.84 + Object level = LoggingSupport.parseLevel(getLevelName(l));
400.85 + levelObjects.put(l, level);
400.86 }
400.87 }
400.88
400.89 @@ -564,10 +513,10 @@
400.90
400.91 JavaLogger(String name, int level) {
400.92 super(name, level);
400.93 - this.javaLogger = invoke(getLoggerMethod, null, name);
400.94 + this.javaLogger = LoggingSupport.getLogger(name);
400.95 if (level != 0) {
400.96 // level has been updated and so set the Logger's level
400.97 - invoke(setLevelMethod, javaLogger, levelObjects.get(level));
400.98 + LoggingSupport.setLevel(javaLogger, levelObjects.get(level));
400.99 }
400.100 }
400.101
400.102 @@ -578,24 +527,24 @@
400.103 * not be updated.
400.104 */
400.105 void doLog(int level, String msg) {
400.106 - invoke(logMethod, javaLogger, levelObjects.get(level), msg);
400.107 + LoggingSupport.log(javaLogger, levelObjects.get(level), msg);
400.108 }
400.109
400.110 void doLog(int level, String msg, Throwable t) {
400.111 - invoke(logThrowMethod, javaLogger, levelObjects.get(level), msg, t);
400.112 + LoggingSupport.log(javaLogger, levelObjects.get(level), msg, t);
400.113 }
400.114
400.115 void doLog(int level, String msg, Object... params) {
400.116 - invoke(logParamsMethod, javaLogger, levelObjects.get(level), msg, params);
400.117 + LoggingSupport.log(javaLogger, levelObjects.get(level), msg, params);
400.118 }
400.119
400.120 boolean isEnabled() {
400.121 - Object level = invoke(getLevelMethod, javaLogger);
400.122 + Object level = LoggingSupport.getLevel(javaLogger);
400.123 return level == null || level.equals(levelObjects.get(OFF)) == false;
400.124 }
400.125
400.126 int getLevel() {
400.127 - Object level = invoke(getLevelMethod, javaLogger);
400.128 + Object level = LoggingSupport.getLevel(javaLogger);
400.129 if (level != null) {
400.130 for (Map.Entry<Integer, Object> l : levelObjects.entrySet()) {
400.131 if (level == l.getValue()) {
400.132 @@ -608,15 +557,14 @@
400.133
400.134 void setLevel(int newLevel) {
400.135 levelValue = newLevel;
400.136 - invoke(setLevelMethod, javaLogger, levelObjects.get(newLevel));
400.137 + LoggingSupport.setLevel(javaLogger, levelObjects.get(newLevel));
400.138 }
400.139
400.140 public boolean isLoggable(int level) {
400.141 - return (Boolean) invoke(isLoggableMethod, javaLogger, levelObjects.get(level));
400.142 + return LoggingSupport.isLoggable(javaLogger, levelObjects.get(level));
400.143 }
400.144 }
400.145
400.146 -
400.147 private static String getLevelName(int level) {
400.148 switch (level) {
400.149 case OFF : return "OFF";
401.1 --- a/src/share/classes/sun/util/resources/TimeZoneNames.java Mon Nov 23 10:04:47 2009 +0000
401.2 +++ b/src/share/classes/sun/util/resources/TimeZoneNames.java Wed Nov 25 11:08:25 2009 -0800
401.3 @@ -141,6 +141,8 @@
401.4 "Malaysia Summer Time", "MYST"};
401.5 String NORONHA[] = new String[] {"Fernando de Noronha Time", "FNT",
401.6 "Fernando de Noronha Summer Time", "FNST"};
401.7 + String NOVT[] = new String[] {"Novosibirsk Time", "NOVT",
401.8 + "Novosibirsk Summer Time", "NOVST"};
401.9 String NPT[] = new String[] {"Nepal Time", "NPT",
401.10 "Nepal Summer Time", "NPST"};
401.11 String NST[] = new String[] {"Newfoundland Standard Time", "NST",
401.12 @@ -441,7 +443,8 @@
401.13 {"America/Winnipeg", CST},
401.14 {"America/Yakutat", AKST},
401.15 {"America/Yellowknife", MST},
401.16 - {"Antarctica/Casey", WST_AUS},
401.17 + {"Antarctica/Casey", new String[] {"Casey Time", "CAST",
401.18 + "Casey Summer Time", "CAST"}},
401.19 {"Antarctica/Davis", new String[] {"Davis Time", "DAVT",
401.20 "Davis Summer Time", "DAVST"}},
401.21 {"Antarctica/DumontDUrville", new String[] {"Dumont-d'Urville Time", "DDUT",
401.22 @@ -529,8 +532,8 @@
401.23 "Philippines Summer Time", "PHST"}},
401.24 {"Asia/Muscat", GST},
401.25 {"Asia/Nicosia", EET},
401.26 - {"Asia/Novosibirsk", new String[] {"Novosibirsk Time", "NOVT",
401.27 - "Novosibirsk Summer Time", "NOVST"}},
401.28 + {"Asia/Novokuznetsk", NOVT},
401.29 + {"Asia/Novosibirsk", NOVT},
401.30 {"Asia/Oral", new String[] {"Oral Time", "ORAT",
401.31 "Oral Summer Time", "ORAST"}},
401.32 {"Asia/Omsk", new String[] {"Omsk Time", "OMST",
402.1 --- a/src/share/classes/sun/util/resources/TimeZoneNames_de.java Mon Nov 23 10:04:47 2009 +0000
402.2 +++ b/src/share/classes/sun/util/resources/TimeZoneNames_de.java Wed Nov 25 11:08:25 2009 -0800
402.3 @@ -141,6 +141,8 @@
402.4 "Malaysische Sommerzeit", "MYST"};
402.5 String NORONHA[] = new String[] {"Fernando de Noronha Zeit", "FNT",
402.6 "Fernando de Noronha Sommerzeit", "FNST"};
402.7 + String NOVT[] = new String[] {"Nowosibirsker Zeit", "NOVT",
402.8 + "Nowosibirsker Sommerzeit", "NOVST"};
402.9 String NPT[] = new String[] {"Nepalesische Zeit", "NPT",
402.10 "Nepalesische Sommerzeit", "NPST"};
402.11 String NST[] = new String[] {"Neufundland Normalzeit", "NST",
402.12 @@ -441,7 +443,6 @@
402.13 {"America/Winnipeg", CST},
402.14 {"America/Yakutat", AKST},
402.15 {"America/Yellowknife", MST},
402.16 - {"Antarctica/Casey", WST_AUS},
402.17 {"Antarctica/Davis", new String[] {"Davis Zeit", "DAVT",
402.18 "Davis Sommerzeit", "DAVST"}},
402.19 {"Antarctica/DumontDUrville", new String[] {"Dumont-d'Urville Zeit", "DDUT",
402.20 @@ -529,8 +530,8 @@
402.21 "Philippinische Sommerzeit", "PHST"}},
402.22 {"Asia/Muscat", GST},
402.23 {"Asia/Nicosia", EET},
402.24 - {"Asia/Novosibirsk", new String[] {"Nowosibirsker Zeit", "NOVT",
402.25 - "Nowosibirsker Sommerzeit", "NOVST"}},
402.26 + {"Asia/Novokuznetsk", NOVT},
402.27 + {"Asia/Novosibirsk", NOVT},
402.28 {"Asia/Oral", new String[] {"Oral Zeit", "ORAT",
402.29 "Oral Sommerzeit", "ORAST"}},
402.30 {"Asia/Omsk", new String[] {"Omsk Zeit", "OMST",
403.1 --- a/src/share/classes/sun/util/resources/TimeZoneNames_es.java Mon Nov 23 10:04:47 2009 +0000
403.2 +++ b/src/share/classes/sun/util/resources/TimeZoneNames_es.java Wed Nov 25 11:08:25 2009 -0800
403.3 @@ -141,6 +141,8 @@
403.4 "Hora de verano de Malasia", "MYST"};
403.5 String NORONHA[] = new String[] {"Hora de Fernando de Noronha", "FNT",
403.6 "Hora de verano de Fernando de Noronha", "FNST"};
403.7 + String NOVT[] = new String[] {"Hora de Novosibirsk", "NOVT",
403.8 + "Hora de verano de Novosibirsk", "NOVST"};
403.9 String NPT[] = new String[] {"Hora de Nepal", "NPT",
403.10 "Hora de verano de Nepal", "NPST"};
403.11 String NST[] = new String[] {"Hora est\u00e1ndar de Terranova", "NST",
403.12 @@ -441,7 +443,6 @@
403.13 {"America/Winnipeg", CST},
403.14 {"America/Yakutat", AKST},
403.15 {"America/Yellowknife", MST},
403.16 - {"Antarctica/Casey", WST_AUS},
403.17 {"Antarctica/Davis", new String[] {"Hora de Davis", "DAVT",
403.18 "Hora de verano de Davis", "DAVST"}},
403.19 {"Antarctica/DumontDUrville", new String[] {"Hora de Dumont-d'Urville", "DDUT",
403.20 @@ -529,8 +530,9 @@
403.21 "Hora de verano de Filipinas", "PHST"}},
403.22 {"Asia/Muscat", GST},
403.23 {"Asia/Nicosia", EET},
403.24 - {"Asia/Novosibirsk", new String[] {"Hora de Novosibirsk", "NOVT",
403.25 - "Hora de verano de Novosibirsk", "NOVST"}},
403.26 +
403.27 + {"Asia/Novokuznetsk", NOVT},
403.28 + {"Asia/Novosibirsk", NOVT},
403.29 {"Asia/Oral", new String[] {"Hora de Uralsk", "ORAT",
403.30 "Hora de verano de Uralsk", "ORAST"}},
403.31 {"Asia/Omsk", new String[] {"Hora de Omsk", "OMST",
404.1 --- a/src/share/classes/sun/util/resources/TimeZoneNames_fr.java Mon Nov 23 10:04:47 2009 +0000
404.2 +++ b/src/share/classes/sun/util/resources/TimeZoneNames_fr.java Wed Nov 25 11:08:25 2009 -0800
404.3 @@ -141,6 +141,8 @@
404.4 "Heure d'\u00e9t\u00e9 de Malaisie", "MYST"};
404.5 String NORONHA[] = new String[] {"Heure de Fernando de Noronha", "FNT",
404.6 "Heure d'\u00e9t\u00e9 de Fernando de Noronha", "FNST"};
404.7 + String NOVT[] = new String[] {"Heure de Novossibirsk", "NOVT",
404.8 + "Heure d'\u00e9t\u00e9 de Novossibirsk", "NOVST"};
404.9 String NPT[] = new String[] {"Heure du N\u00e9pal", "NPT",
404.10 "Heure d'\u00e9t\u00e9 du N\u00e9pal", "NPST"};
404.11 String NST[] = new String[] {"Heure normale de Terre-Neuve", "NST",
404.12 @@ -441,7 +443,6 @@
404.13 {"America/Winnipeg", CST},
404.14 {"America/Yakutat", AKST},
404.15 {"America/Yellowknife", MST},
404.16 - {"Antarctica/Casey", WST_AUS},
404.17 {"Antarctica/Davis", new String[] {"Heure de Davis", "DAVT",
404.18 "Heure d'\u00e9t\u00e9 de Davis", "DAVST"}},
404.19 {"Antarctica/DumontDUrville", new String[] {"Heure de Dumont-d'Urville", "DDUT",
404.20 @@ -529,8 +530,8 @@
404.21 "Heure d'\u00e9t\u00e9 des Philippines", "PHST"}},
404.22 {"Asia/Muscat", GST},
404.23 {"Asia/Nicosia", EET},
404.24 - {"Asia/Novosibirsk", new String[] {"Heure de Novossibirsk", "NOVT",
404.25 - "Heure d'\u00e9t\u00e9 de Novossibirsk", "NOVST"}},
404.26 + {"Asia/Novokuznetsk", NOVT},
404.27 + {"Asia/Novosibirsk", NOVT},
404.28 {"Asia/Oral", new String[] {"Heure d'Oral", "ORAT",
404.29 "Heure d'\u00e9t\u00e9 d'Oral", "ORAST"}},
404.30 {"Asia/Omsk", new String[] {"Heure d'Omsk", "OMST",
405.1 --- a/src/share/classes/sun/util/resources/TimeZoneNames_it.java Mon Nov 23 10:04:47 2009 +0000
405.2 +++ b/src/share/classes/sun/util/resources/TimeZoneNames_it.java Wed Nov 25 11:08:25 2009 -0800
405.3 @@ -141,6 +141,8 @@
405.4 "Ora estiva della Malaysia", "MYST"};
405.5 String NORONHA[] = new String[] {"Ora di Fernando de Noronha", "FNT",
405.6 "Ora estiva di Fernando de Noronha", "FNST"};
405.7 + String NOVT[] = new String[] {"Ora di Novosibirsk", "NOVT",
405.8 + "Ora estiva di Novosibirsk", "NOVST"};
405.9 String NPT[] = new String[] {"Ora del Nepal", "NPT",
405.10 "Ora estiva del Nepal", "NPST"};
405.11 String NST[] = new String[] {"Ora solare di Terranova", "NST",
405.12 @@ -441,7 +443,6 @@
405.13 {"America/Winnipeg", CST},
405.14 {"America/Yakutat", AKST},
405.15 {"America/Yellowknife", MST},
405.16 - {"Antarctica/Casey", WST_AUS},
405.17 {"Antarctica/Davis", new String[] {"Ora di Davis", "DAVT",
405.18 "Ora estiva di Davis", "DAVST"}},
405.19 {"Antarctica/DumontDUrville", new String[] {"Ora di Dumont-d'Urville", "DDUT",
405.20 @@ -529,8 +530,8 @@
405.21 "Ora estiva delle Filippine", "PHST"}},
405.22 {"Asia/Muscat", GST},
405.23 {"Asia/Nicosia", EET},
405.24 - {"Asia/Novosibirsk", new String[] {"Ora di Novosibirsk", "NOVT",
405.25 - "Ora estiva di Novosibirsk", "NOVST"}},
405.26 + {"Asia/Novokuznetsk", NOVT},
405.27 + {"Asia/Novosibirsk", NOVT},
405.28 {"Asia/Oral", new String[] {"Ora di Oral", "ORAT",
405.29 "Ora estiva di Oral", "ORAST"}},
405.30 {"Asia/Omsk", new String[] {"Ora di Omsk", "OMST",
406.1 --- a/src/share/classes/sun/util/resources/TimeZoneNames_ja.java Mon Nov 23 10:04:47 2009 +0000
406.2 +++ b/src/share/classes/sun/util/resources/TimeZoneNames_ja.java Wed Nov 25 11:08:25 2009 -0800
406.3 @@ -141,6 +141,8 @@
406.4 "\u30de\u30ec\u30fc\u30b7\u30a2\u590f\u6642\u9593", "MYST"};
406.5 String NORONHA[] = new String[] {"\u30d5\u30a7\u30eb\u30ca\u30f3\u30c9\u30fb\u30c7\u30fb\u30ce\u30ed\u30fc\u30cb\u30e3\u6642\u9593", "FNT",
406.6 "\u30d5\u30a7\u30eb\u30ca\u30f3\u30c9\u30fb\u30c7\u30fb\u30ce\u30ed\u30fc\u30cb\u30e3\u590f\u6642\u9593", "FNST"};
406.7 + String NOVT[] = new String[] {"\u30ce\u30dc\u30b7\u30d3\u30eb\u30b9\u30af\u6642\u9593", "NOVT",
406.8 + "\u30ce\u30dc\u30b7\u30d3\u30eb\u30b9\u30af\u590f\u6642\u9593", "NOVST"};
406.9 String NPT[] = new String[] {"\u30cd\u30d1\u30fc\u30eb\u6642\u9593", "NPT",
406.10 "\u30cd\u30d1\u30fc\u30eb\u590f\u6642\u9593", "NPST"};
406.11 String NST[] = new String[] {"\u30cb\u30e5\u30fc\u30d5\u30a1\u30f3\u30c9\u30e9\u30f3\u30c9\u6a19\u6e96\u6642", "NST",
406.12 @@ -441,7 +443,6 @@
406.13 {"America/Winnipeg", CST},
406.14 {"America/Yakutat", AKST},
406.15 {"America/Yellowknife", MST},
406.16 - {"Antarctica/Casey", WST_AUS},
406.17 {"Antarctica/Davis", new String[] {"\u30c7\u30a4\u30d3\u30b9\u6642\u9593", "DAVT",
406.18 "\u30c7\u30a4\u30d3\u30b9\u590f\u6642\u9593", "DAVST"}},
406.19 {"Antarctica/DumontDUrville", new String[] {"\u30c7\u30e5\u30e2\u30f3\u30c7\u30e5\u30eb\u30f4\u30a3\u30eb\u6642\u9593", "DDUT",
406.20 @@ -529,8 +530,8 @@
406.21 "\u30d5\u30a3\u30ea\u30d4\u30f3\u590f\u6642\u9593", "PHST"}},
406.22 {"Asia/Muscat", GST},
406.23 {"Asia/Nicosia", EET},
406.24 - {"Asia/Novosibirsk", new String[] {"\u30ce\u30dc\u30b7\u30d3\u30eb\u30b9\u30af\u6642\u9593", "NOVT",
406.25 - "\u30ce\u30dc\u30b7\u30d3\u30eb\u30b9\u30af\u590f\u6642\u9593", "NOVST"}},
406.26 + {"Asia/Novokuznetsk", NOVT},
406.27 + {"Asia/Novosibirsk", NOVT},
406.28 {"Asia/Oral", new String[] {"\u30aa\u30e9\u30eb\u6642\u9593", "ORAT",
406.29 "\u30aa\u30e9\u30eb\u590f\u6642\u9593", "ORAST"}},
406.30 {"Asia/Omsk", new String[] {"\u30aa\u30e0\u30b9\u30af\u6642\u9593", "OMST",
407.1 --- a/src/share/classes/sun/util/resources/TimeZoneNames_ko.java Mon Nov 23 10:04:47 2009 +0000
407.2 +++ b/src/share/classes/sun/util/resources/TimeZoneNames_ko.java Wed Nov 25 11:08:25 2009 -0800
407.3 @@ -141,6 +141,8 @@
407.4 "\ub9d0\ub808\uc774\uc2dc\uc544 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "MYST"};
407.5 String NORONHA[] = new String[] {"Fernando de Noronha \uc2dc\uac04", "FNT",
407.6 "Fernando de Noronha \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "FNST"};
407.7 + String NOVT[] = new String[] {"\ub178\ube0c\uc2dc\ube4c\uc2a4\ud06c \uc2dc\uac04", "NOVT",
407.8 + "\ub178\ube0c\uc2dc\ube4c\uc2a4\ud06c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "NOVST"};
407.9 String NPT[] = new String[] {"\ub124\ud314 \uc2dc\uac04", "NPT",
407.10 "\ub124\ud314 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "NPST"};
407.11 String NST[] = new String[] {"\ub274\ud380\ub4e4\ub79c\ub4dc \ud45c\uc900\uc2dc", "NST",
407.12 @@ -441,7 +443,6 @@
407.13 {"America/Winnipeg", CST},
407.14 {"America/Yakutat", AKST},
407.15 {"America/Yellowknife", MST},
407.16 - {"Antarctica/Casey", WST_AUS},
407.17 {"Antarctica/Davis", new String[] {"Davis \uc2dc\uac04", "DAVT",
407.18 "Davis \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "DAVST"}},
407.19 {"Antarctica/DumontDUrville", new String[] {"\ub4a4\ubabd \ub4a4\ub974\ube4c \uc2dc\uac04", "DDUT",
407.20 @@ -529,8 +530,8 @@
407.21 "\ud544\ub9ac\ud540 \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "PHST"}},
407.22 {"Asia/Muscat", GST},
407.23 {"Asia/Nicosia", EET},
407.24 - {"Asia/Novosibirsk", new String[] {"\ub178\ube0c\uc2dc\ube4c\uc2a4\ud06c \uc2dc\uac04", "NOVT",
407.25 - "\ub178\ube0c\uc2dc\ube4c\uc2a4\ud06c \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "NOVST"}},
407.26 + {"Asia/Novokuznetsk", NOVT},
407.27 + {"Asia/Novosibirsk", NOVT},
407.28 {"Asia/Oral", new String[] {"Oral \ud45c\uc900\uc2dc", "ORAT",
407.29 "Oral \uc77c\uad11\uc808\uc57d\uc2dc\uac04", "ORAST"}},
407.30 {"Asia/Omsk", new String[] {"Omsk \uc2dc\uac04", "OMST",
408.1 --- a/src/share/classes/sun/util/resources/TimeZoneNames_sv.java Mon Nov 23 10:04:47 2009 +0000
408.2 +++ b/src/share/classes/sun/util/resources/TimeZoneNames_sv.java Wed Nov 25 11:08:25 2009 -0800
408.3 @@ -141,6 +141,8 @@
408.4 "Malaysia, sommartid", "MYST"};
408.5 String NORONHA[] = new String[] {"Fernando de Noronha, normaltid", "FNT",
408.6 "Fernando de Noronha, sommartid", "FNST"};
408.7 + String NOVT[] = new String[] {"Novosibirsk, normaltid", "NOVT",
408.8 + "Novosibirsk, sommartid", "NOVST"};
408.9 String NPT[] = new String[] {"Nepal, normaltid", "NPT",
408.10 "Nepal, sommartid", "NPST"};
408.11 String NST[] = new String[] {"Newfoundland, normaltid", "NST",
408.12 @@ -441,7 +443,6 @@
408.13 {"America/Winnipeg", CST},
408.14 {"America/Yakutat", AKST},
408.15 {"America/Yellowknife", MST},
408.16 - {"Antarctica/Casey", WST_AUS},
408.17 {"Antarctica/Davis", new String[] {"Davis, normaltid", "DAVT",
408.18 "Davis, sommartid", "DAVST"}},
408.19 {"Antarctica/DumontDUrville", new String[] {"Dumont-d'Urville, normaltid", "DDUT",
408.20 @@ -529,8 +530,8 @@
408.21 "Filippinerna, sommartid", "PHST"}},
408.22 {"Asia/Muscat", GST},
408.23 {"Asia/Nicosia", EET},
408.24 - {"Asia/Novosibirsk", new String[] {"Novosibirsk, normaltid", "NOVT",
408.25 - "Novosibirsk, sommartid", "NOVST"}},
408.26 + {"Asia/Novokuznetsk", NOVT},
408.27 + {"Asia/Novosibirsk", NOVT},
408.28 {"Asia/Oral", new String[] {"Oral, normaltid", "ORAT",
408.29 "Oral, sommartid", "ORAST"}},
408.30 {"Asia/Omsk", new String[] {"Omsk, normaltid", "OMST",
409.1 --- a/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java Mon Nov 23 10:04:47 2009 +0000
409.2 +++ b/src/share/classes/sun/util/resources/TimeZoneNames_zh_CN.java Wed Nov 25 11:08:25 2009 -0800
409.3 @@ -141,6 +141,8 @@
409.4 "\u9a6c\u6765\u897f\u4e9a\u590f\u4ee4\u65f6", "MYST"};
409.5 String NORONHA[] = new String[] {"\u8d39\u5c14\u5357\u591a\u5fb7\u8bfa\u7f57\u5c3c\u4e9a\u65f6\u95f4", "FNT",
409.6 "\u8d39\u5c14\u5357\u591a\u5fb7\u8bfa\u7f57\u5c3c\u4e9a\u590f\u4ee4\u65f6", "FNST"};
409.7 + String NOVT[] = new String[] {"Novosibirsk \u65f6\u95f4", "NOVT",
409.8 + "Novosibirsk \u590f\u4ee4\u65f6", "NOVST"};
409.9 String NPT[] = new String[] {"\u5c3c\u6cca\u5c14\u65f6\u95f4", "NPT",
409.10 "\u5c3c\u6cca\u5c14\u590f\u4ee4\u65f6", "NPST"};
409.11 String NST[] = new String[] {"\u7ebd\u82ac\u5170\u6807\u51c6\u65f6\u95f4", "NST",
409.12 @@ -441,7 +443,6 @@
409.13 {"America/Winnipeg", CST},
409.14 {"America/Yakutat", AKST},
409.15 {"America/Yellowknife", MST},
409.16 - {"Antarctica/Casey", WST_AUS},
409.17 {"Antarctica/Davis", new String[] {"\u6234\u7ef4\u65af\u65f6\u95f4", "DAVT",
409.18 "\u6234\u7ef4\u65af\u590f\u4ee4\u65f6", "DAVST"}},
409.19 {"Antarctica/DumontDUrville", new String[] {"Dumont-d'Urville \u65f6\u95f4", "DDUT",
409.20 @@ -529,8 +530,8 @@
409.21 "\u83f2\u5f8b\u5bbe\u590f\u4ee4\u65f6", "PHST"}},
409.22 {"Asia/Muscat", GST},
409.23 {"Asia/Nicosia", EET},
409.24 - {"Asia/Novosibirsk", new String[] {"Novosibirsk \u65f6\u95f4", "NOVT",
409.25 - "Novosibirsk \u590f\u4ee4\u65f6", "NOVST"}},
409.26 + {"Asia/Novokuznetsk", NOVT},
409.27 + {"Asia/Novosibirsk", NOVT},
409.28 {"Asia/Oral", new String[] {"Oral \u65f6\u95f4", "ORAT",
409.29 "Oral \u590f\u4ee4\u65f6", "ORAST"}},
409.30 {"Asia/Omsk", new String[] {"\u9102\u6728\u65af\u514b\u65f6\u95f4", "OMST",
410.1 --- a/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java Mon Nov 23 10:04:47 2009 +0000
410.2 +++ b/src/share/classes/sun/util/resources/TimeZoneNames_zh_TW.java Wed Nov 25 11:08:25 2009 -0800
410.3 @@ -141,6 +141,8 @@
410.4 "\u99ac\u4f86\u897f\u4e9e\u590f\u4ee4\u6642\u9593", "MYST"};
410.5 String NORONHA[] = new String[] {"\u8cbb\u723e\u5357\u591a-\u8fea\u8afe\u7f85\u5c3c\u4e9e\u6642\u9593", "FNT",
410.6 "\u8cbb\u723e\u5357\u591a-\u8fea\u8afe\u7f85\u5c3c\u4e9e\u590f\u4ee4\u6642\u9593", "FNST"};
410.7 + String NOVT[] = new String[] {"Novosibirsk \u6642\u9593", "NOVT",
410.8 + "Novosibirsk \u590f\u4ee4\u6642\u9593", "NOVST"};
410.9 String NPT[] = new String[] {"\u5c3c\u6cca\u723e\u6642\u9593", "NPT",
410.10 "\u5c3c\u6cca\u723e\u590f\u4ee4\u6642\u9593", "NPST"};
410.11 String NST[] = new String[] {"\u7d10\u82ac\u862d\u6a19\u6e96\u6642\u9593", "NST",
410.12 @@ -441,7 +443,6 @@
410.13 {"America/Winnipeg", CST},
410.14 {"America/Yakutat", AKST},
410.15 {"America/Yellowknife", MST},
410.16 - {"Antarctica/Casey", WST_AUS},
410.17 {"Antarctica/Davis", new String[] {"\u81fa\u7dad\u65af\u6642\u9593", "DAVT",
410.18 "\u81fa\u7dad\u65af\u590f\u4ee4\u6642\u9593", "DAVST"}},
410.19 {"Antarctica/DumontDUrville", new String[] {"Dumont-d'Urville \u6642\u9593", "DDUT",
410.20 @@ -529,8 +530,8 @@
410.21 "\u83f2\u5f8b\u8cd3\u590f\u4ee4\u6642\u9593", "PHST"}},
410.22 {"Asia/Muscat", GST},
410.23 {"Asia/Nicosia", EET},
410.24 - {"Asia/Novosibirsk", new String[] {"Novosibirsk \u6642\u9593", "NOVT",
410.25 - "Novosibirsk \u590f\u4ee4\u6642\u9593", "NOVST"}},
410.26 + {"Asia/Novokuznetsk", NOVT},
410.27 + {"Asia/Novosibirsk", NOVT},
410.28 {"Asia/Oral", new String[] {"\u6b50\u4f5b\u6642\u9593", "ORAT",
410.29 "\u6b50\u4f5b\u590f\u4ee4\u6642\u9593", "ORAST"}},
410.30 {"Asia/Omsk", new String[] {"\u6b50\u59c6\u65af\u514b (Omsk) \u6642\u9593", "OMST",
411.1 --- a/src/share/native/java/util/zip/Deflater.c Mon Nov 23 10:04:47 2009 +0000
411.2 +++ b/src/share/native/java/util/zip/Deflater.c Wed Nov 25 11:08:25 2009 -0800
411.3 @@ -118,7 +118,7 @@
411.4
411.5 JNIEXPORT jint JNICALL
411.6 Java_java_util_zip_Deflater_deflateBytes(JNIEnv *env, jobject this,
411.7 - jarray b, jint off, jint len)
411.8 + jarray b, jint off, jint len, jint flush)
411.9 {
411.10 z_stream *strm = jlong_to_ptr((*env)->GetLongField(env, this, strmID));
411.11
411.12 @@ -197,7 +197,7 @@
411.13 strm->next_out = (Bytef *) out_buf;
411.14 strm->avail_in = this_len;
411.15 strm->avail_out = len;
411.16 - res = deflate(strm, finish ? Z_FINISH : Z_NO_FLUSH);
411.17 + res = deflate(strm, finish ? Z_FINISH : flush);
411.18
411.19 if (res == Z_STREAM_END || res == Z_OK) {
411.20 (*env)->SetByteArrayRegion(env, b, off, len - strm->avail_out, out_buf);
412.1 --- a/src/share/native/sun/awt/image/awt_ImageRep.c Mon Nov 23 10:04:47 2009 +0000
412.2 +++ b/src/share/native/sun/awt/image/awt_ImageRep.c Wed Nov 25 11:08:25 2009 -0800
412.3 @@ -142,84 +142,6 @@
412.4
412.5 }
412.6
412.7 -JNIEXPORT void JNICALL
412.8 -Java_sun_awt_image_ImageRepresentation_setBytePixels(JNIEnv *env, jclass cls,
412.9 - jint x, jint y, jint w,
412.10 - jint h, jbyteArray jpix,
412.11 - jint off, jint scansize,
412.12 - jobject jbct,
412.13 - jint chanOffs)
412.14 -{
412.15 - int sStride;
412.16 - int pixelStride;
412.17 - jobject jdata;
412.18 - unsigned char *srcData;
412.19 - unsigned char *dstData;
412.20 - unsigned char *dataP;
412.21 - unsigned char *pixP;
412.22 - int i;
412.23 - int j;
412.24 -
412.25 -
412.26 - if (JNU_IsNull(env, jpix)) {
412.27 - JNU_ThrowNullPointerException(env, "NullPointerException");
412.28 - return;
412.29 - }
412.30 -
412.31 - sStride = (*env)->GetIntField(env, jbct, g_BCRscanstrID);
412.32 - pixelStride = (*env)->GetIntField(env, jbct, g_BCRpixstrID);
412.33 - jdata = (*env)->GetObjectField(env, jbct, g_BCRdataID);
412.34 -
412.35 - srcData = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, jpix,
412.36 - NULL);
412.37 - if (srcData == NULL) {
412.38 - /* out of memory error already thrown */
412.39 - return;
412.40 - }
412.41 -
412.42 - dstData = (unsigned char *) (*env)->GetPrimitiveArrayCritical(env, jdata,
412.43 - NULL);
412.44 - if (dstData == NULL) {
412.45 - /* out of memory error already thrown */
412.46 - (*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
412.47 - return;
412.48 - }
412.49 -
412.50 - dataP = dstData + chanOffs + y*sStride + x*pixelStride;
412.51 - pixP = srcData + off;
412.52 - if (pixelStride == 1) {
412.53 - if (sStride == scansize && scansize == w) {
412.54 - memcpy(dataP, pixP, w*h);
412.55 - }
412.56 - else {
412.57 - for (i=0; i < h; i++) {
412.58 - memcpy(dataP, pixP, w);
412.59 - dataP += sStride;
412.60 - pixP += scansize;
412.61 - }
412.62 - }
412.63 - }
412.64 - else {
412.65 - unsigned char *ydataP = dataP;
412.66 - unsigned char *ypixP = pixP;
412.67 -
412.68 - for (i=0; i < h; i++) {
412.69 - dataP = ydataP;
412.70 - pixP = ypixP;
412.71 - for (j=0; j < w; j++) {
412.72 - *dataP = *pixP++;
412.73 - dataP += pixelStride;
412.74 - }
412.75 - ydataP += sStride;
412.76 - ypixP += scansize;
412.77 - }
412.78 - }
412.79 -
412.80 - (*env)->ReleasePrimitiveArrayCritical(env, jpix, srcData, JNI_ABORT);
412.81 - (*env)->ReleasePrimitiveArrayCritical(env, jdata, dstData, JNI_ABORT);
412.82 -
412.83 -}
412.84 -
412.85 JNIEXPORT jint JNICALL
412.86 Java_sun_awt_image_ImageRepresentation_setDiffICM(JNIEnv *env, jclass cls,
412.87 jint x, jint y, jint w,
412.88 @@ -266,6 +188,13 @@
412.89 jnewlut = (*env)->GetObjectField(env, jicm, g_ICMrgbID);
412.90 mapSize = (*env)->GetIntField(env, jicm, g_ICMmapSizeID);
412.91
412.92 + if (numLut < 0 || numLut > 256 || mapSize < 0 || mapSize > 256) {
412.93 + /* Ether old or new ICM has a palette that exceeds capacity
412.94 + of byte data type, so we have to convert the image data
412.95 + to default representation.
412.96 + */
412.97 + return 0;
412.98 + }
412.99 srcLUT = (unsigned int *) (*env)->GetPrimitiveArrayCritical(env, jlut,
412.100 NULL);
412.101 if (srcLUT == NULL) {
413.1 --- a/src/share/native/sun/awt/image/jpeg/imageioJPEG.c Mon Nov 23 10:04:47 2009 +0000
413.2 +++ b/src/share/native/sun/awt/image/jpeg/imageioJPEG.c Wed Nov 25 11:08:25 2009 -0800
413.3 @@ -676,6 +676,10 @@
413.4 #ifdef DEBUG_IIO_JPEG
413.5 printf("in setQTables, qlen = %d, write is %d\n", qlen, write);
413.6 #endif
413.7 + if (qlen > NUM_QUANT_TBLS) {
413.8 + /* Ignore extra qunterization tables. */
413.9 + qlen = NUM_QUANT_TBLS;
413.10 + }
413.11 for (i = 0; i < qlen; i++) {
413.12 table = (*env)->GetObjectArrayElement(env, qtables, i);
413.13 qdata = (*env)->GetObjectField(env, table, JPEGQTable_tableID);
413.14 @@ -727,6 +731,11 @@
413.15 hlensBody = (*env)->GetShortArrayElements(env,
413.16 huffLens,
413.17 NULL);
413.18 + if (hlensLen > 16) {
413.19 + /* Ignore extra elements of bits array. Only 16 elements can be
413.20 + stored. 0-th element is not used. (see jpeglib.h, line 107) */
413.21 + hlensLen = 16;
413.22 + }
413.23 for (i = 1; i <= hlensLen; i++) {
413.24 huff_ptr->bits[i] = (UINT8)hlensBody[i-1];
413.25 }
413.26 @@ -743,6 +752,11 @@
413.27 huffValues,
413.28 NULL);
413.29
413.30 + if (hvalsLen > 256) {
413.31 + /* Ignore extra elements of hufval array. Only 256 elements
413.32 + can be stored. (see jpeglib.h, line 109) */
413.33 + hlensLen = 256;
413.34 + }
413.35 for (i = 0; i < hvalsLen; i++) {
413.36 huff_ptr->huffval[i] = (UINT8)hvalsBody[i];
413.37 }
413.38 @@ -763,6 +777,11 @@
413.39 j_compress_ptr comp;
413.40 j_decompress_ptr decomp;
413.41 jsize hlen = (*env)->GetArrayLength(env, DCHuffmanTables);
413.42 +
413.43 + if (hlen > NUM_HUFF_TBLS) {
413.44 + /* Ignore extra DC huffman tables. */
413.45 + hlen = NUM_HUFF_TBLS;
413.46 + }
413.47 for (i = 0; i < hlen; i++) {
413.48 if (cinfo->is_decompressor) {
413.49 decomp = (j_decompress_ptr) cinfo;
413.50 @@ -784,6 +803,10 @@
413.51 huff_ptr->sent_table = !write;
413.52 }
413.53 hlen = (*env)->GetArrayLength(env, ACHuffmanTables);
413.54 + if (hlen > NUM_HUFF_TBLS) {
413.55 + /* Ignore extra AC huffman tables. */
413.56 + hlen = NUM_HUFF_TBLS;
413.57 + }
413.58 for (i = 0; i < hlen; i++) {
413.59 if (cinfo->is_decompressor) {
413.60 decomp = (j_decompress_ptr) cinfo;
413.61 @@ -1437,6 +1460,7 @@
413.62 JNU_ThrowByName( env,
413.63 "java/lang/OutOfMemoryError",
413.64 "Initializing Reader");
413.65 + free(cinfo);
413.66 return 0;
413.67 }
413.68
413.69 @@ -1473,6 +1497,7 @@
413.70 JNU_ThrowByName(env,
413.71 "java/lang/OutOfMemoryError",
413.72 "Initializing Reader");
413.73 + imageio_dispose((j_common_ptr)cinfo);
413.74 return 0;
413.75 }
413.76 cinfo->src->bytes_in_buffer = 0;
413.77 @@ -1489,6 +1514,7 @@
413.78 JNU_ThrowByName( env,
413.79 "java/lang/OutOfMemoryError",
413.80 "Initializing Reader");
413.81 + imageio_dispose((j_common_ptr)cinfo);
413.82 return 0;
413.83 }
413.84 return (jlong) ret;
413.85 @@ -1833,6 +1859,13 @@
413.86 return JNI_FALSE;
413.87 }
413.88
413.89 + if (stepX > cinfo->image_width) {
413.90 + stepX = cinfo->image_width;
413.91 + }
413.92 + if (stepY > cinfo->image_height) {
413.93 + stepY = cinfo->image_height;
413.94 + }
413.95 +
413.96 /*
413.97 * First get the source bands array and copy it to our local array
413.98 * so we don't have to worry about pinning and unpinning it again.
413.99 @@ -2420,8 +2453,7 @@
413.100 JNU_ThrowByName( env,
413.101 "java/lang/OutOfMemoryError",
413.102 "Initializing Writer");
413.103 - free(cinfo);
413.104 - free(jerr);
413.105 + imageio_dispose((j_common_ptr)cinfo);
413.106 return 0;
413.107 }
413.108
413.109 @@ -2439,8 +2471,7 @@
413.110 JNU_ThrowByName( env,
413.111 "java/lang/OutOfMemoryError",
413.112 "Initializing Writer");
413.113 - free(cinfo);
413.114 - free(jerr);
413.115 + imageio_dispose((j_common_ptr)cinfo);
413.116 return 0;
413.117 }
413.118 return (jlong) ret;
414.1 --- a/src/share/native/sun/awt/medialib/awt_ImagingLib.c Mon Nov 23 10:04:47 2009 +0000
414.2 +++ b/src/share/native/sun/awt/medialib/awt_ImagingLib.c Wed Nov 25 11:08:25 2009 -0800
414.3 @@ -960,21 +960,15 @@
414.4 mlib_filter filter;
414.5 unsigned int *dP;
414.6
414.7 - if ((srcRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {
414.8 - JNU_ThrowOutOfMemoryError(env, "Out of memory");
414.9 - return -1;
414.10 - }
414.11 -
414.12 - if ((dstRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {
414.13 - JNU_ThrowOutOfMemoryError(env, "Out of memory");
414.14 - free(srcRasterP);
414.15 - return -1;
414.16 - }
414.17 -
414.18 /* This function requires a lot of local refs ??? Is 64 enough ??? */
414.19 if ((*env)->EnsureLocalCapacity(env, 64) < 0)
414.20 return 0;
414.21
414.22 + if (s_nomlib) return 0;
414.23 + if (s_timeIt) {
414.24 + (*start_timer)(3600);
414.25 + }
414.26 +
414.27 switch(interpType) {
414.28 case java_awt_image_AffineTransformOp_TYPE_BILINEAR:
414.29 filter = MLIB_BILINEAR;
414.30 @@ -990,9 +984,15 @@
414.31 return -1;
414.32 }
414.33
414.34 - if (s_nomlib) return 0;
414.35 - if (s_timeIt) {
414.36 - (*start_timer)(3600);
414.37 + if ((srcRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {
414.38 + JNU_ThrowOutOfMemoryError(env, "Out of memory");
414.39 + return -1;
414.40 + }
414.41 +
414.42 + if ((dstRasterP = (RasterS_t *) calloc(1, sizeof(RasterS_t))) == NULL) {
414.43 + JNU_ThrowOutOfMemoryError(env, "Out of memory");
414.44 + free(srcRasterP);
414.45 + return -1;
414.46 }
414.47
414.48 if ((*env)->GetArrayLength(env, jmatrix) < 6) {
414.49 @@ -1215,6 +1215,9 @@
414.50 }
414.51
414.52 if (tbl == NULL || table == NULL || jtable == NULL) {
414.53 + if (tbl != NULL) free(tbl);
414.54 + if (table != NULL) free(table);
414.55 + if (jtable != NULL) free(jtable);
414.56 awt_freeParsedImage(srcImageP, TRUE);
414.57 awt_freeParsedImage(dstImageP, TRUE);
414.58 JNU_ThrowNullPointerException(env, "NULL LUT");
414.59 @@ -1224,6 +1227,11 @@
414.60 for (i=0; i < jlen; i++) {
414.61 jtable[i] = (*env)->GetObjectArrayElement(env, jtableArrays, i);
414.62 if (jtable[i] == NULL) {
414.63 + free(tbl);
414.64 + free(table);
414.65 + free(jtable);
414.66 + awt_freeParsedImage(srcImageP, TRUE);
414.67 + awt_freeParsedImage(dstImageP, TRUE);
414.68 return 0;
414.69 }
414.70 }
414.71 @@ -1232,6 +1240,9 @@
414.72 FALSE, &hint);
414.73 if (nbands < 1) {
414.74 /* Can't handle any custom images */
414.75 + free(tbl);
414.76 + free(table);
414.77 + free(jtable);
414.78 awt_freeParsedImage(srcImageP, TRUE);
414.79 awt_freeParsedImage(dstImageP, TRUE);
414.80 return 0;
414.81 @@ -1240,12 +1251,18 @@
414.82 /* Allocate the arrays */
414.83 if (allocateArray(env, srcImageP, &src, &sdata, TRUE, FALSE, FALSE) < 0) {
414.84 /* Must be some problem */
414.85 + free(tbl);
414.86 + free(table);
414.87 + free(jtable);
414.88 awt_freeParsedImage(srcImageP, TRUE);
414.89 awt_freeParsedImage(dstImageP, TRUE);
414.90 return 0;
414.91 }
414.92 if (allocateArray(env, dstImageP, &dst, &ddata, FALSE, FALSE, FALSE) < 0) {
414.93 /* Must be some problem */
414.94 + free(tbl);
414.95 + free(table);
414.96 + free(jtable);
414.97 freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL);
414.98 awt_freeParsedImage(srcImageP, TRUE);
414.99 awt_freeParsedImage(dstImageP, TRUE);
414.100 @@ -1284,6 +1301,9 @@
414.101 (jbyte *) table[j],
414.102 JNI_ABORT);
414.103 }
414.104 + free(tbl);
414.105 + free(table);
414.106 + free(jtable);
414.107 freeArray(env, srcImageP, src, sdata, NULL, NULL, NULL);
414.108 awt_freeParsedImage(srcImageP, TRUE);
414.109 awt_freeParsedImage(dstImageP, TRUE);
414.110 @@ -1413,12 +1433,15 @@
414.111
414.112 /* Parse the source raster - reject custom images */
414.113 if ((status = awt_parseRaster(env, jsrc, srcRasterP)) <= 0) {
414.114 + free(srcRasterP);
414.115 + free(dstRasterP);
414.116 return 0;
414.117 }
414.118
414.119 /* Parse the destination image - reject custom images */
414.120 if ((status = awt_parseRaster(env, jdst, dstRasterP)) <= 0) {
414.121 awt_freeParsedRaster(srcRasterP, TRUE);
414.122 + free(dstRasterP);
414.123 return 0;
414.124 }
414.125
415.1 --- a/src/share/native/sun/font/freetypeScaler.c Mon Nov 23 10:04:47 2009 +0000
415.2 +++ b/src/share/native/sun/font/freetypeScaler.c Wed Nov 25 11:08:25 2009 -0800
415.3 @@ -102,9 +102,21 @@
415.4 }
415.5
415.6 static void freeNativeResources(JNIEnv *env, FTScalerInfo* scalerInfo) {
415.7 + void *stream;
415.8 +
415.9 if (scalerInfo == NULL)
415.10 return;
415.11
415.12 + //apparently Done_Face will only close the stream
415.13 + // but will not relase the memory of stream structure.
415.14 + // We need to free it explicitly to avoid leak.
415.15 + //Direct access to the stream field might be not ideal solution as
415.16 + // it is considred to be "private".
415.17 + //Alternatively we could have stored pointer to the structure
415.18 + // in the scalerInfo but this will increase size of the structure
415.19 + // for no good reason
415.20 + stream = scalerInfo->face->stream;
415.21 +
415.22 FT_Done_Face(scalerInfo->face);
415.23 FT_Done_FreeType(scalerInfo->library);
415.24
415.25 @@ -116,6 +128,10 @@
415.26 free(scalerInfo->fontData);
415.27 }
415.28
415.29 + if (stream != NULL) {
415.30 + free(stream);
415.31 + }
415.32 +
415.33 free(scalerInfo);
415.34 }
415.35
416.1 --- a/src/solaris/classes/java/util/prefs/FileSystemPreferences.java Mon Nov 23 10:04:47 2009 +0000
416.2 +++ b/src/solaris/classes/java/util/prefs/FileSystemPreferences.java Wed Nov 25 11:08:25 2009 -0800
416.3 @@ -26,12 +26,12 @@
416.4 package java.util.prefs;
416.5 import java.util.*;
416.6 import java.io.*;
416.7 -import java.util.logging.Logger;
416.8 import java.security.AccessController;
416.9 import java.security.PrivilegedAction;
416.10 import java.security.PrivilegedExceptionAction;
416.11 import java.security.PrivilegedActionException;
416.12
416.13 +import sun.util.logging.PlatformLogger;
416.14
416.15 /**
416.16 * Preferences implementation for Unix. Preferences are stored in the file
416.17 @@ -61,8 +61,8 @@
416.18 * Returns logger for error messages. Backing store exceptions are logged at
416.19 * WARNING level.
416.20 */
416.21 - private static Logger getLogger() {
416.22 - return Logger.getLogger("java.util.prefs");
416.23 + private static PlatformLogger getLogger() {
416.24 + return PlatformLogger.getLogger("java.util.prefs");
416.25 }
416.26
416.27 /**
417.1 --- a/src/solaris/classes/sun/awt/X11/XDropTargetRegistry.java Mon Nov 23 10:04:47 2009 +0000
417.2 +++ b/src/solaris/classes/sun/awt/X11/XDropTargetRegistry.java Wed Nov 25 11:08:25 2009 -0800
417.3 @@ -534,71 +534,71 @@
417.4 return entry.getSite(x, y);
417.5 }
417.6
417.7 + /*
417.8 + * Note: this method should be called under AWT lock.
417.9 + */
417.10 public void registerDropSite(long window) {
417.11 + assert XToolkit.isAWTLockHeldByCurrentThread();
417.12 +
417.13 if (window == 0) {
417.14 throw new IllegalArgumentException();
417.15 }
417.16
417.17 XDropTargetEventProcessor.activate();
417.18
417.19 - XToolkit.awtLock();
417.20 - try {
417.21 - long toplevel = getToplevelWindow(window);
417.22 + long toplevel = getToplevelWindow(window);
417.23
417.24 - /*
417.25 - * No window with WM_STATE property is found.
417.26 - * Since the window can be a plugin window reparented to the browser
417.27 - * toplevel, we cannot determine which window will eventually have
417.28 - * WM_STATE property set. So we schedule a timer callback that will
417.29 - * periodically attempt to find an ancestor with WM_STATE and
417.30 - * register the drop site appropriately.
417.31 - */
417.32 - if (toplevel == 0) {
417.33 - addDelayedRegistrationEntry(window);
417.34 - return;
417.35 + /*
417.36 + * No window with WM_STATE property is found.
417.37 + * Since the window can be a plugin window reparented to the browser
417.38 + * toplevel, we cannot determine which window will eventually have
417.39 + * WM_STATE property set. So we schedule a timer callback that will
417.40 + * periodically attempt to find an ancestor with WM_STATE and
417.41 + * register the drop site appropriately.
417.42 + */
417.43 + if (toplevel == 0) {
417.44 + addDelayedRegistrationEntry(window);
417.45 + return;
417.46 + }
417.47 +
417.48 + if (toplevel == window) {
417.49 + Iterator dropTargetProtocols =
417.50 + XDragAndDropProtocols.getDropTargetProtocols();
417.51 +
417.52 + while (dropTargetProtocols.hasNext()) {
417.53 + XDropTargetProtocol dropTargetProtocol =
417.54 + (XDropTargetProtocol)dropTargetProtocols.next();
417.55 + dropTargetProtocol.registerDropTarget(toplevel);
417.56 }
417.57 -
417.58 - if (toplevel == window) {
417.59 - Iterator dropTargetProtocols =
417.60 - XDragAndDropProtocols.getDropTargetProtocols();
417.61 -
417.62 - while (dropTargetProtocols.hasNext()) {
417.63 - XDropTargetProtocol dropTargetProtocol =
417.64 - (XDropTargetProtocol)dropTargetProtocols.next();
417.65 - dropTargetProtocol.registerDropTarget(toplevel);
417.66 - }
417.67 - } else {
417.68 - registerEmbeddedDropSite(toplevel, window);
417.69 - }
417.70 - } finally {
417.71 - XToolkit.awtUnlock();
417.72 + } else {
417.73 + registerEmbeddedDropSite(toplevel, window);
417.74 }
417.75 }
417.76
417.77 + /*
417.78 + * Note: this method should be called under AWT lock.
417.79 + */
417.80 public void unregisterDropSite(long window) {
417.81 + assert XToolkit.isAWTLockHeldByCurrentThread();
417.82 +
417.83 if (window == 0) {
417.84 throw new IllegalArgumentException();
417.85 }
417.86
417.87 - XToolkit.awtLock();
417.88 - try {
417.89 - long toplevel = getToplevelWindow(window);
417.90 + long toplevel = getToplevelWindow(window);
417.91
417.92 - if (toplevel == window) {
417.93 - Iterator dropProtocols =
417.94 - XDragAndDropProtocols.getDropTargetProtocols();
417.95 + if (toplevel == window) {
417.96 + Iterator dropProtocols =
417.97 + XDragAndDropProtocols.getDropTargetProtocols();
417.98
417.99 - removeDelayedRegistrationEntry(window);
417.100 + removeDelayedRegistrationEntry(window);
417.101
417.102 - while (dropProtocols.hasNext()) {
417.103 - XDropTargetProtocol dropProtocol = (XDropTargetProtocol)dropProtocols.next();
417.104 - dropProtocol.unregisterDropTarget(window);
417.105 - }
417.106 - } else {
417.107 - unregisterEmbeddedDropSite(toplevel, window);
417.108 + while (dropProtocols.hasNext()) {
417.109 + XDropTargetProtocol dropProtocol = (XDropTargetProtocol)dropProtocols.next();
417.110 + dropProtocol.unregisterDropTarget(window);
417.111 }
417.112 - } finally {
417.113 - XToolkit.awtUnlock();
417.114 + } else {
417.115 + unregisterEmbeddedDropSite(toplevel, window);
417.116 }
417.117 }
417.118
418.1 --- a/src/solaris/classes/sun/awt/X11/XWindow.java Mon Nov 23 10:04:47 2009 +0000
418.2 +++ b/src/solaris/classes/sun/awt/X11/XWindow.java Wed Nov 25 11:08:25 2009 -0800
418.3 @@ -1509,4 +1509,24 @@
418.4 return new XAtomList();
418.5 }
418.6
418.7 + /**
418.8 + * Indicates if the window is currently in the FSEM.
418.9 + * Synchronization: state lock.
418.10 + */
418.11 + private boolean fullScreenExclusiveModeState = false;
418.12 +
418.13 + // Implementation of the X11ComponentPeer
418.14 + @Override
418.15 + public void setFullScreenExclusiveModeState(boolean state) {
418.16 + synchronized (getStateLock()) {
418.17 + fullScreenExclusiveModeState = state;
418.18 + }
418.19 + }
418.20 +
418.21 + public final boolean isFullScreenExclusiveMode() {
418.22 + synchronized (getStateLock()) {
418.23 + return fullScreenExclusiveModeState;
418.24 + }
418.25 + }
418.26 +
418.27 }
419.1 --- a/src/solaris/classes/sun/awt/X11/XWindowPeer.java Mon Nov 23 10:04:47 2009 +0000
419.2 +++ b/src/solaris/classes/sun/awt/X11/XWindowPeer.java Wed Nov 25 11:08:25 2009 -0800
419.3 @@ -1079,31 +1079,39 @@
419.4 updateSecurityWarningVisibility();
419.5 }
419.6
419.7 + @Override
419.8 + public void setFullScreenExclusiveModeState(boolean state) {
419.9 + super.setFullScreenExclusiveModeState(state);
419.10 + updateSecurityWarningVisibility();
419.11 + }
419.12 +
419.13 public void updateSecurityWarningVisibility() {
419.14 if (warningWindow == null) {
419.15 return;
419.16 }
419.17
419.18 - boolean show = false;
419.19 -
419.20 - int state = getWMState();
419.21 -
419.22 if (!isVisible()) {
419.23 return; // The warning window should already be hidden.
419.24 }
419.25
419.26 - // getWMState() always returns 0 (Withdrawn) for simple windows. Hence
419.27 - // we ignore the state for such windows.
419.28 - if (isVisible() && (state == XUtilConstants.NormalState || isSimpleWindow())) {
419.29 - if (XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow() ==
419.30 - getTarget())
419.31 - {
419.32 - show = true;
419.33 - }
419.34 + boolean show = false;
419.35
419.36 - if (isMouseAbove() || warningWindow.isMouseAbove())
419.37 - {
419.38 - show = true;
419.39 + if (!isFullScreenExclusiveMode()) {
419.40 + int state = getWMState();
419.41 +
419.42 + // getWMState() always returns 0 (Withdrawn) for simple windows. Hence
419.43 + // we ignore the state for such windows.
419.44 + if (isVisible() && (state == XUtilConstants.NormalState || isSimpleWindow())) {
419.45 + if (XKeyboardFocusManagerPeer.getCurrentNativeFocusedWindow() ==
419.46 + getTarget())
419.47 + {
419.48 + show = true;
419.49 + }
419.50 +
419.51 + if (isMouseAbove() || warningWindow.isMouseAbove())
419.52 + {
419.53 + show = true;
419.54 + }
419.55 }
419.56 }
419.57
419.58 @@ -1756,25 +1764,36 @@
419.59 }
419.60 }
419.61
419.62 + // should be synchronized on awtLock
419.63 private int dropTargetCount = 0;
419.64
419.65 - public synchronized void addDropTarget() {
419.66 - if (dropTargetCount == 0) {
419.67 - long window = getWindow();
419.68 - if (window != 0) {
419.69 - XDropTargetRegistry.getRegistry().registerDropSite(window);
419.70 + public void addDropTarget() {
419.71 + XToolkit.awtLock();
419.72 + try {
419.73 + if (dropTargetCount == 0) {
419.74 + long window = getWindow();
419.75 + if (window != 0) {
419.76 + XDropTargetRegistry.getRegistry().registerDropSite(window);
419.77 + }
419.78 }
419.79 + dropTargetCount++;
419.80 + } finally {
419.81 + XToolkit.awtUnlock();
419.82 }
419.83 - dropTargetCount++;
419.84 }
419.85
419.86 - public synchronized void removeDropTarget() {
419.87 - dropTargetCount--;
419.88 - if (dropTargetCount == 0) {
419.89 - long window = getWindow();
419.90 - if (window != 0) {
419.91 - XDropTargetRegistry.getRegistry().unregisterDropSite(window);
419.92 + public void removeDropTarget() {
419.93 + XToolkit.awtLock();
419.94 + try {
419.95 + dropTargetCount--;
419.96 + if (dropTargetCount == 0) {
419.97 + long window = getWindow();
419.98 + if (window != 0) {
419.99 + XDropTargetRegistry.getRegistry().unregisterDropSite(window);
419.100 + }
419.101 }
419.102 + } finally {
419.103 + XToolkit.awtUnlock();
419.104 }
419.105 }
419.106 void addRootPropertyEventDispatcher() {
419.107 @@ -1837,13 +1856,18 @@
419.108 }
419.109 }
419.110
419.111 - protected synchronized void updateDropTarget() {
419.112 - if (dropTargetCount > 0) {
419.113 - long window = getWindow();
419.114 - if (window != 0) {
419.115 - XDropTargetRegistry.getRegistry().unregisterDropSite(window);
419.116 - XDropTargetRegistry.getRegistry().registerDropSite(window);
419.117 + protected void updateDropTarget() {
419.118 + XToolkit.awtLock();
419.119 + try {
419.120 + if (dropTargetCount > 0) {
419.121 + long window = getWindow();
419.122 + if (window != 0) {
419.123 + XDropTargetRegistry.getRegistry().unregisterDropSite(window);
419.124 + XDropTargetRegistry.getRegistry().registerDropSite(window);
419.125 + }
419.126 }
419.127 + } finally {
419.128 + XToolkit.awtUnlock();
419.129 }
419.130 }
419.131
420.1 --- a/src/solaris/classes/sun/awt/X11ComponentPeer.java Mon Nov 23 10:04:47 2009 +0000
420.2 +++ b/src/solaris/classes/sun/awt/X11ComponentPeer.java Wed Nov 25 11:08:25 2009 -0800
420.3 @@ -1,5 +1,5 @@
420.4 /*
420.5 - * Copyright 2003-2005 Sun Microsystems, Inc. All Rights Reserved.
420.6 + * Copyright 2003-2009 Sun Microsystems, Inc. All Rights Reserved.
420.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
420.8 *
420.9 * This code is free software; you can redistribute it and/or modify it
420.10 @@ -39,4 +39,5 @@
420.11 Rectangle getBounds();
420.12 Graphics getGraphics();
420.13 Object getTarget();
420.14 + void setFullScreenExclusiveModeState(boolean state);
420.15 }
421.1 --- a/src/solaris/classes/sun/awt/X11GraphicsDevice.java Mon Nov 23 10:04:47 2009 +0000
421.2 +++ b/src/solaris/classes/sun/awt/X11GraphicsDevice.java Wed Nov 25 11:08:25 2009 -0800
421.3 @@ -1,5 +1,5 @@
421.4 /*
421.5 - * Copyright 1997-2008 Sun Microsystems, Inc. All Rights Reserved.
421.6 + * Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
421.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
421.8 *
421.9 * This code is free software; you can redistribute it and/or modify it
421.10 @@ -134,7 +134,7 @@
421.11 makeConfigurations();
421.12 }
421.13 }
421.14 - return configs;
421.15 + return configs.clone();
421.16 }
421.17
421.18 private void makeConfigurations() {
421.19 @@ -306,12 +306,14 @@
421.20 X11ComponentPeer peer = (X11ComponentPeer)w.getPeer();
421.21 if (peer != null) {
421.22 enterFullScreenExclusive(peer.getContentWindow());
421.23 + peer.setFullScreenExclusiveModeState(true);
421.24 }
421.25 }
421.26
421.27 private static void exitFullScreenExclusive(Window w) {
421.28 X11ComponentPeer peer = (X11ComponentPeer)w.getPeer();
421.29 if (peer != null) {
421.30 + peer.setFullScreenExclusiveModeState(false);
421.31 exitFullScreenExclusive(peer.getContentWindow());
421.32 }
421.33 }
422.1 --- a/src/solaris/classes/sun/java2d/x11/X11SurfaceData.java Mon Nov 23 10:04:47 2009 +0000
422.2 +++ b/src/solaris/classes/sun/java2d/x11/X11SurfaceData.java Wed Nov 25 11:08:25 2009 -0800
422.3 @@ -388,7 +388,10 @@
422.4 // if a GlyphVector overrides the AA setting.
422.5 // We use getRenderLoops() rather than setting solidloops
422.6 // directly so that we get the appropriate loops in XOR mode.
422.7 - sg2d.loops = getRenderLoops(sg2d);
422.8 + if (sg2d.loops == null) {
422.9 + // assert(some pipe will always be a LoopBasedPipe)
422.10 + sg2d.loops = getRenderLoops(sg2d);
422.11 + }
422.12 } else {
422.13 super.validatePipe(sg2d);
422.14 }
423.1 --- a/src/solaris/classes/sun/net/NetHooks.java Mon Nov 23 10:04:47 2009 +0000
423.2 +++ b/src/solaris/classes/sun/net/NetHooks.java Wed Nov 25 11:08:25 2009 -0800
423.3 @@ -81,7 +81,7 @@
423.4 try {
423.5 c = (Class<Provider>)Class.forName(cn, true, null);
423.6 } catch (ClassNotFoundException x) {
423.7 - throw new AssertionError(x);
423.8 + return null;
423.9 }
423.10 try {
423.11 return c.newInstance();
424.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
424.2 +++ b/src/solaris/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Wed Nov 25 11:08:25 2009 -0800
424.3 @@ -0,0 +1,423 @@
424.4 +/*
424.5 + * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
424.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
424.7 + *
424.8 + * This code is free software; you can redistribute it and/or modify it
424.9 + * under the terms of the GNU General Public License version 2 only, as
424.10 + * published by the Free Software Foundation. Sun designates this
424.11 + * particular file as subject to the "Classpath" exception as provided
424.12 + * by Sun in the LICENSE file that accompanied this code.
424.13 + *
424.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
424.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
424.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
424.17 + * version 2 for more details (a copy is included in the LICENSE file that
424.18 + * accompanied this code).
424.19 + *
424.20 + * You should have received a copy of the GNU General Public License version
424.21 + * 2 along with this work; if not, write to the Free Software Foundation,
424.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
424.23 + *
424.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
424.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
424.26 + * have any questions.
424.27 + */
424.28 +
424.29 +package sun.net.www.protocol.http.ntlm;
424.30 +
424.31 +import java.io.IOException;
424.32 +import java.io.UnsupportedEncodingException;
424.33 +import java.net.InetAddress;
424.34 +import java.net.PasswordAuthentication;
424.35 +import java.net.UnknownHostException;
424.36 +import java.net.URL;
424.37 +import java.security.GeneralSecurityException;
424.38 +import java.security.MessageDigest;
424.39 +import java.security.NoSuchAlgorithmException;
424.40 +import javax.crypto.Cipher;
424.41 +import javax.crypto.NoSuchPaddingException;
424.42 +import javax.crypto.SecretKey;
424.43 +import javax.crypto.SecretKeyFactory;
424.44 +import javax.crypto.spec.DESKeySpec;
424.45 +
424.46 +import sun.net.www.HeaderParser;
424.47 +import sun.net.www.protocol.http.AuthenticationInfo;
424.48 +import sun.net.www.protocol.http.AuthScheme;
424.49 +import sun.net.www.protocol.http.HttpURLConnection;
424.50 +
424.51 +/**
424.52 + * NTLMAuthentication:
424.53 + *
424.54 + * @author Michael McMahon
424.55 + */
424.56 +
424.57 +/*
424.58 + * NTLM authentication is nominally based on the framework defined in RFC2617,
424.59 + * but differs from the standard (Basic & Digest) schemes as follows:
424.60 + *
424.61 + * 1. A complete authentication requires three request/response transactions
424.62 + * as shown below:
424.63 + * REQ ------------------------------->
424.64 + * <---- 401 (signalling NTLM) --------
424.65 + *
424.66 + * REQ (with type1 NTLM msg) --------->
424.67 + * <---- 401 (with type 2 NTLM msg) ---
424.68 + *
424.69 + * REQ (with type3 NTLM msg) --------->
424.70 + * <---- OK ---------------------------
424.71 + *
424.72 + * 2. The scope of the authentication is the TCP connection (which must be kept-alive)
424.73 + * after the type2 response is received. This means that NTLM does not work end-to-end
424.74 + * through a proxy, rather between client and proxy, or between client and server (with no proxy)
424.75 + */
424.76 +
424.77 +public class NTLMAuthentication extends AuthenticationInfo {
424.78 + private static final long serialVersionUID = -2403849171106437142L;
424.79 +
424.80 + private byte[] type1;
424.81 + private byte[] type3;
424.82 +
424.83 + private SecretKeyFactory fac;
424.84 + private Cipher cipher;
424.85 + private MessageDigest md4;
424.86 + private String hostname;
424.87 + private static String defaultDomain; /* Domain to use if not specified by user */
424.88 +
424.89 + static {
424.90 + defaultDomain = java.security.AccessController.doPrivileged(
424.91 + new sun.security.action.GetPropertyAction("http.auth.ntlm.domain",
424.92 + "domain"));
424.93 + };
424.94 +
424.95 + public static boolean supportsTransparentAuth () {
424.96 + return false;
424.97 + }
424.98 +
424.99 + private void init0() {
424.100 + type1 = new byte[256];
424.101 + type3 = new byte[256];
424.102 + System.arraycopy (new byte[] {'N','T','L','M','S','S','P',0,1}, 0, type1, 0, 9);
424.103 + type1[12] = (byte) 3;
424.104 + type1[13] = (byte) 0xb2;
424.105 + type1[28] = (byte) 0x20;
424.106 + System.arraycopy (new byte[] {'N','T','L','M','S','S','P',0,3}, 0, type3, 0, 9);
424.107 + type3[12] = (byte) 0x18;
424.108 + type3[14] = (byte) 0x18;
424.109 + type3[20] = (byte) 0x18;
424.110 + type3[22] = (byte) 0x18;
424.111 + type3[32] = (byte) 0x40;
424.112 + type3[60] = (byte) 1;
424.113 + type3[61] = (byte) 0x82;
424.114 +
424.115 + try {
424.116 + hostname = java.security.AccessController.doPrivileged(
424.117 + new java.security.PrivilegedAction<String>() {
424.118 + public String run() {
424.119 + String localhost;
424.120 + try {
424.121 + localhost = InetAddress.getLocalHost().getHostName().toUpperCase();
424.122 + } catch (UnknownHostException e) {
424.123 + localhost = "localhost";
424.124 + }
424.125 + return localhost;
424.126 + }
424.127 + });
424.128 + int x = hostname.indexOf ('.');
424.129 + if (x != -1) {
424.130 + hostname = hostname.substring (0, x);
424.131 + }
424.132 + fac = SecretKeyFactory.getInstance ("DES");
424.133 + cipher = Cipher.getInstance ("DES/ECB/NoPadding");
424.134 + md4 = sun.security.provider.MD4.getInstance();
424.135 + } catch (NoSuchPaddingException e) {
424.136 + assert false;
424.137 + } catch (NoSuchAlgorithmException e) {
424.138 + assert false;
424.139 + }
424.140 + };
424.141 +
424.142 + PasswordAuthentication pw;
424.143 + String username;
424.144 + String ntdomain;
424.145 + String password;
424.146 +
424.147 + /**
424.148 + * Create a NTLMAuthentication:
424.149 + * Username may be specified as domain<BACKSLASH>username in the application Authenticator.
424.150 + * If this notation is not used, then the domain will be taken
424.151 + * from a system property: "http.auth.ntlm.domain".
424.152 + */
424.153 + public NTLMAuthentication(boolean isProxy, URL url, PasswordAuthentication pw) {
424.154 + super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
424.155 + AuthScheme.NTLM,
424.156 + url,
424.157 + "");
424.158 + init (pw);
424.159 + }
424.160 +
424.161 + private void init (PasswordAuthentication pw) {
424.162 + this.pw = pw;
424.163 + String s = pw.getUserName();
424.164 + int i = s.indexOf ('\\');
424.165 + if (i == -1) {
424.166 + username = s;
424.167 + ntdomain = defaultDomain;
424.168 + } else {
424.169 + ntdomain = s.substring (0, i).toUpperCase();
424.170 + username = s.substring (i+1);
424.171 + }
424.172 + password = new String (pw.getPassword());
424.173 + init0();
424.174 + }
424.175 +
424.176 + /**
424.177 + * Constructor used for proxy entries
424.178 + */
424.179 + public NTLMAuthentication(boolean isProxy, String host, int port,
424.180 + PasswordAuthentication pw) {
424.181 + super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
424.182 + AuthScheme.NTLM,
424.183 + host,
424.184 + port,
424.185 + "");
424.186 + init (pw);
424.187 + }
424.188 +
424.189 + /**
424.190 + * @return true if this authentication supports preemptive authorization
424.191 + */
424.192 + @Override
424.193 + public boolean supportsPreemptiveAuthorization() {
424.194 + return false;
424.195 + }
424.196 +
424.197 + /**
424.198 + * Not supported. Must use the setHeaders() method
424.199 + */
424.200 + @Override
424.201 + public String getHeaderValue(URL url, String method) {
424.202 + throw new RuntimeException ("getHeaderValue not supported");
424.203 + }
424.204 +
424.205 + /**
424.206 + * Check if the header indicates that the current auth. parameters are stale.
424.207 + * If so, then replace the relevant field with the new value
424.208 + * and return true. Otherwise return false.
424.209 + * returning true means the request can be retried with the same userid/password
424.210 + * returning false means we have to go back to the user to ask for a new
424.211 + * username password.
424.212 + */
424.213 + @Override
424.214 + public boolean isAuthorizationStale (String header) {
424.215 + return false; /* should not be called for ntlm */
424.216 + }
424.217 +
424.218 + /**
424.219 + * Set header(s) on the given connection.
424.220 + * @param conn The connection to apply the header(s) to
424.221 + * @param p A source of header values for this connection, not used because
424.222 + * HeaderParser converts the fields to lower case, use raw instead
424.223 + * @param raw The raw header field.
424.224 + * @return true if all goes well, false if no headers were set.
424.225 + */
424.226 + @Override
424.227 + public synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
424.228 +
424.229 + try {
424.230 + String response;
424.231 + if (raw.length() < 6) { /* NTLM<sp> */
424.232 + response = buildType1Msg ();
424.233 + } else {
424.234 + String msg = raw.substring (5); /* skip NTLM<sp> */
424.235 + response = buildType3Msg (msg);
424.236 + }
424.237 + conn.setAuthenticationProperty(getHeaderName(), response);
424.238 + return true;
424.239 + } catch (IOException e) {
424.240 + return false;
424.241 + } catch (GeneralSecurityException e) {
424.242 + return false;
424.243 + }
424.244 + }
424.245 +
424.246 + private void copybytes (byte[] dest, int destpos, String src, String enc) {
424.247 + try {
424.248 + byte[] x = src.getBytes(enc);
424.249 + System.arraycopy (x, 0, dest, destpos, x.length);
424.250 + } catch (UnsupportedEncodingException e) {
424.251 + assert false;
424.252 + }
424.253 + }
424.254 +
424.255 + private String buildType1Msg () {
424.256 + int dlen = ntdomain.length();
424.257 + type1[16]= (byte) (dlen % 256);
424.258 + type1[17]= (byte) (dlen / 256);
424.259 + type1[18] = type1[16];
424.260 + type1[19] = type1[17];
424.261 +
424.262 + int hlen = hostname.length();
424.263 + type1[24]= (byte) (hlen % 256);
424.264 + type1[25]= (byte) (hlen / 256);
424.265 + type1[26] = type1[24];
424.266 + type1[27] = type1[25];
424.267 +
424.268 + copybytes (type1, 32, hostname, "ISO8859_1");
424.269 + copybytes (type1, hlen+32, ntdomain, "ISO8859_1");
424.270 + type1[20] = (byte) ((hlen+32) % 256);
424.271 + type1[21] = (byte) ((hlen+32) / 256);
424.272 +
424.273 + byte[] msg = new byte [32 + hlen + dlen];
424.274 + System.arraycopy (type1, 0, msg, 0, 32 + hlen + dlen);
424.275 + String result = "NTLM " + (new B64Encoder()).encode (msg);
424.276 + return result;
424.277 + }
424.278 +
424.279 +
424.280 + /* Convert a 7 byte array to an 8 byte array (for a des key with parity)
424.281 + * input starts at offset off
424.282 + */
424.283 + private byte[] makeDesKey (byte[] input, int off) {
424.284 + int[] in = new int [input.length];
424.285 + for (int i=0; i<in.length; i++ ) {
424.286 + in[i] = input[i]<0 ? input[i]+256: input[i];
424.287 + }
424.288 + byte[] out = new byte[8];
424.289 + out[0] = (byte)in[off+0];
424.290 + out[1] = (byte)(((in[off+0] << 7) & 0xFF) | (in[off+1] >> 1));
424.291 + out[2] = (byte)(((in[off+1] << 6) & 0xFF) | (in[off+2] >> 2));
424.292 + out[3] = (byte)(((in[off+2] << 5) & 0xFF) | (in[off+3] >> 3));
424.293 + out[4] = (byte)(((in[off+3] << 4) & 0xFF) | (in[off+4] >> 4));
424.294 + out[5] = (byte)(((in[off+4] << 3) & 0xFF) | (in[off+5] >> 5));
424.295 + out[6] = (byte)(((in[off+5] << 2) & 0xFF) | (in[off+6] >> 6));
424.296 + out[7] = (byte)((in[off+6] << 1) & 0xFF);
424.297 + return out;
424.298 + }
424.299 +
424.300 + private byte[] calcLMHash () throws GeneralSecurityException {
424.301 + byte[] magic = {0x4b, 0x47, 0x53, 0x21, 0x40, 0x23, 0x24, 0x25};
424.302 + byte[] pwb = password.toUpperCase ().getBytes();
424.303 + byte[] pwb1 = new byte [14];
424.304 + int len = password.length();
424.305 + if (len > 14)
424.306 + len = 14;
424.307 + System.arraycopy (pwb, 0, pwb1, 0, len); /* Zero padded */
424.308 +
424.309 + DESKeySpec dks1 = new DESKeySpec (makeDesKey (pwb1, 0));
424.310 + DESKeySpec dks2 = new DESKeySpec (makeDesKey (pwb1, 7));
424.311 +
424.312 + SecretKey key1 = fac.generateSecret (dks1);
424.313 + SecretKey key2 = fac.generateSecret (dks2);
424.314 + cipher.init (Cipher.ENCRYPT_MODE, key1);
424.315 + byte[] out1 = cipher.doFinal (magic, 0, 8);
424.316 + cipher.init (Cipher.ENCRYPT_MODE, key2);
424.317 + byte[] out2 = cipher.doFinal (magic, 0, 8);
424.318 +
424.319 + byte[] result = new byte [21];
424.320 + System.arraycopy (out1, 0, result, 0, 8);
424.321 + System.arraycopy (out2, 0, result, 8, 8);
424.322 + return result;
424.323 + }
424.324 +
424.325 + private byte[] calcNTHash () throws GeneralSecurityException {
424.326 + byte[] pw = null;
424.327 + try {
424.328 + pw = password.getBytes ("UnicodeLittleUnmarked");
424.329 + } catch (UnsupportedEncodingException e) {
424.330 + assert false;
424.331 + }
424.332 + byte[] out = md4.digest (pw);
424.333 + byte[] result = new byte [21];
424.334 + System.arraycopy (out, 0, result, 0, 16);
424.335 + return result;
424.336 + }
424.337 +
424.338 + /* key is a 21 byte array. Split it into 3 7 byte chunks,
424.339 + * Convert each to 8 byte DES keys, encrypt the text arg with
424.340 + * each key and return the three results in a sequential []
424.341 + */
424.342 + private byte[] calcResponse (byte[] key, byte[] text)
424.343 + throws GeneralSecurityException {
424.344 + assert key.length == 21;
424.345 + DESKeySpec dks1 = new DESKeySpec (makeDesKey (key, 0));
424.346 + DESKeySpec dks2 = new DESKeySpec (makeDesKey (key, 7));
424.347 + DESKeySpec dks3 = new DESKeySpec (makeDesKey (key, 14));
424.348 + SecretKey key1 = fac.generateSecret (dks1);
424.349 + SecretKey key2 = fac.generateSecret (dks2);
424.350 + SecretKey key3 = fac.generateSecret (dks3);
424.351 + cipher.init (Cipher.ENCRYPT_MODE, key1);
424.352 + byte[] out1 = cipher.doFinal (text, 0, 8);
424.353 + cipher.init (Cipher.ENCRYPT_MODE, key2);
424.354 + byte[] out2 = cipher.doFinal (text, 0, 8);
424.355 + cipher.init (Cipher.ENCRYPT_MODE, key3);
424.356 + byte[] out3 = cipher.doFinal (text, 0, 8);
424.357 + byte[] result = new byte [24];
424.358 + System.arraycopy (out1, 0, result, 0, 8);
424.359 + System.arraycopy (out2, 0, result, 8, 8);
424.360 + System.arraycopy (out3, 0, result, 16, 8);
424.361 + return result;
424.362 + }
424.363 +
424.364 + private String buildType3Msg (String challenge) throws GeneralSecurityException,
424.365 + IOException {
424.366 + /* First decode the type2 message to get the server nonce */
424.367 + /* nonce is located at type2[24] for 8 bytes */
424.368 +
424.369 + byte[] type2 = (new sun.misc.BASE64Decoder()).decodeBuffer (challenge);
424.370 + byte[] nonce = new byte [8];
424.371 + System.arraycopy (type2, 24, nonce, 0, 8);
424.372 +
424.373 + int ulen = username.length()*2;
424.374 + type3[36] = type3[38] = (byte) (ulen % 256);
424.375 + type3[37] = type3[39] = (byte) (ulen / 256);
424.376 + int dlen = ntdomain.length()*2;
424.377 + type3[28] = type3[30] = (byte) (dlen % 256);
424.378 + type3[29] = type3[31] = (byte) (dlen / 256);
424.379 + int hlen = hostname.length()*2;
424.380 + type3[44] = type3[46] = (byte) (hlen % 256);
424.381 + type3[45] = type3[47] = (byte) (hlen / 256);
424.382 +
424.383 + int l = 64;
424.384 + copybytes (type3, l, ntdomain, "UnicodeLittleUnmarked");
424.385 + type3[32] = (byte) (l % 256);
424.386 + type3[33] = (byte) (l / 256);
424.387 + l += dlen;
424.388 + copybytes (type3, l, username, "UnicodeLittleUnmarked");
424.389 + type3[40] = (byte) (l % 256);
424.390 + type3[41] = (byte) (l / 256);
424.391 + l += ulen;
424.392 + copybytes (type3, l, hostname, "UnicodeLittleUnmarked");
424.393 + type3[48] = (byte) (l % 256);
424.394 + type3[49] = (byte) (l / 256);
424.395 + l += hlen;
424.396 +
424.397 + byte[] lmhash = calcLMHash();
424.398 + byte[] lmresponse = calcResponse (lmhash, nonce);
424.399 + byte[] nthash = calcNTHash();
424.400 + byte[] ntresponse = calcResponse (nthash, nonce);
424.401 + System.arraycopy (lmresponse, 0, type3, l, 24);
424.402 + type3[16] = (byte) (l % 256);
424.403 + type3[17] = (byte) (l / 256);
424.404 + l += 24;
424.405 + System.arraycopy (ntresponse, 0, type3, l, 24);
424.406 + type3[24] = (byte) (l % 256);
424.407 + type3[25] = (byte) (l / 256);
424.408 + l += 24;
424.409 + type3[56] = (byte) (l % 256);
424.410 + type3[57] = (byte) (l / 256);
424.411 +
424.412 + byte[] msg = new byte [l];
424.413 + System.arraycopy (type3, 0, msg, 0, l);
424.414 + String result = "NTLM " + (new B64Encoder()).encode (msg);
424.415 + return result;
424.416 + }
424.417 +
424.418 +}
424.419 +
424.420 +
424.421 +class B64Encoder extends sun.misc.BASE64Encoder {
424.422 + /* to force it to to the entire encoding in one line */
424.423 + protected int bytesPerLine () {
424.424 + return 1024;
424.425 + }
424.426 +}
425.1 --- a/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java Mon Nov 23 10:04:47 2009 +0000
425.2 +++ b/src/solaris/classes/sun/nio/ch/EPollArrayWrapper.java Wed Nov 25 11:08:25 2009 -0800
425.3 @@ -28,6 +28,7 @@
425.4 import java.io.IOException;
425.5 import java.util.LinkedList;
425.6 import java.util.HashSet;
425.7 +import java.util.Iterator;
425.8
425.9 /**
425.10 * Manipulates a native array of epoll_event structs on Linux:
425.11 @@ -200,12 +201,9 @@
425.12 void release(SelChImpl channel) {
425.13 synchronized (updateList) {
425.14 // flush any pending updates
425.15 - int i = 0;
425.16 - while (i < updateList.size()) {
425.17 - if (updateList.get(i).channel == channel) {
425.18 - updateList.remove(i);
425.19 - } else {
425.20 - i++;
425.21 + for (Iterator<Updator> it = updateList.iterator(); it.hasNext();) {
425.22 + if (it.next().channel == channel) {
425.23 + it.remove();
425.24 }
425.25 }
425.26
426.1 --- a/src/solaris/native/sun/awt/awt_GraphicsEnv.c Mon Nov 23 10:04:47 2009 +0000
426.2 +++ b/src/solaris/native/sun/awt/awt_GraphicsEnv.c Wed Nov 25 11:08:25 2009 -0800
426.3 @@ -1654,6 +1654,7 @@
426.4 #ifndef HEADLESS
426.5
426.6 #define BIT_DEPTH_MULTI java_awt_DisplayMode_BIT_DEPTH_MULTI
426.7 +#define REFRESH_RATE_UNKNOWN java_awt_DisplayMode_REFRESH_RATE_UNKNOWN
426.8
426.9 typedef Status
426.10 (*XRRQueryVersionType) (Display *dpy, int *major_versionp, int *minor_versionp);
426.11 @@ -1680,6 +1681,9 @@
426.12 Rotation rotation,
426.13 short rate,
426.14 Time timestamp);
426.15 +typedef Rotation
426.16 + (*XRRConfigRotationsType)(XRRScreenConfiguration *config,
426.17 + Rotation *current_rotation);
426.18
426.19 static XRRQueryVersionType awt_XRRQueryVersion;
426.20 static XRRGetScreenInfoType awt_XRRGetScreenInfo;
426.21 @@ -1689,6 +1693,7 @@
426.22 static XRRConfigSizesType awt_XRRConfigSizes;
426.23 static XRRConfigCurrentConfigurationType awt_XRRConfigCurrentConfiguration;
426.24 static XRRSetScreenConfigAndRateType awt_XRRSetScreenConfigAndRate;
426.25 +static XRRConfigRotationsType awt_XRRConfigRotations;
426.26
426.27 #define LOAD_XRANDR_FUNC(f) \
426.28 do { \
426.29 @@ -1755,6 +1760,7 @@
426.30 LOAD_XRANDR_FUNC(XRRConfigSizes);
426.31 LOAD_XRANDR_FUNC(XRRConfigCurrentConfiguration);
426.32 LOAD_XRANDR_FUNC(XRRSetScreenConfigAndRate);
426.33 + LOAD_XRANDR_FUNC(XRRConfigRotations);
426.34
426.35 return JNI_TRUE;
426.36 }
426.37 @@ -1765,6 +1771,7 @@
426.38 {
426.39 jclass displayModeClass;
426.40 jmethodID cid;
426.41 + jint validRefreshRate = refreshRate;
426.42
426.43 displayModeClass = (*env)->FindClass(env, "java/awt/DisplayMode");
426.44 if (JNU_IsNull(env, displayModeClass)) {
426.45 @@ -1780,8 +1787,13 @@
426.46 return NULL;
426.47 }
426.48
426.49 + // early versions of xrandr may report "empty" rates (6880694)
426.50 + if (validRefreshRate <= 0) {
426.51 + validRefreshRate = REFRESH_RATE_UNKNOWN;
426.52 + }
426.53 +
426.54 return (*env)->NewObject(env, displayModeClass, cid,
426.55 - width, height, bitDepth, refreshRate);
426.56 + width, height, bitDepth, validRefreshRate);
426.57 }
426.58
426.59 static void
426.60 @@ -1926,8 +1938,7 @@
426.61 curRate = awt_XRRConfigCurrentRate(config);
426.62
426.63 if ((sizes != NULL) &&
426.64 - (curSizeIndex < nsizes) &&
426.65 - (curRate > 0))
426.66 + (curSizeIndex < nsizes))
426.67 {
426.68 XRRScreenSize curSize = sizes[curSizeIndex];
426.69 displayMode = X11GD_CreateDisplayMode(env,
426.70 @@ -2004,6 +2015,7 @@
426.71 jboolean success = JNI_FALSE;
426.72 XRRScreenConfiguration *config;
426.73 Drawable root;
426.74 + Rotation currentRotation = RR_Rotate_0;
426.75
426.76 AWT_LOCK();
426.77
426.78 @@ -2015,6 +2027,7 @@
426.79 short chosenRate = -1;
426.80 int nsizes;
426.81 XRRScreenSize *sizes = awt_XRRConfigSizes(config, &nsizes);
426.82 + awt_XRRConfigRotations(config, ¤tRotation);
426.83
426.84 if (sizes != NULL) {
426.85 int i, j;
426.86 @@ -2048,7 +2061,7 @@
426.87 Status status =
426.88 awt_XRRSetScreenConfigAndRate(awt_display, config, root,
426.89 chosenSizeIndex,
426.90 - RR_Rotate_0,
426.91 + currentRotation,
426.92 chosenRate,
426.93 CurrentTime);
426.94
427.1 --- a/src/solaris/native/sun/awt/awt_GraphicsEnv.h Mon Nov 23 10:04:47 2009 +0000
427.2 +++ b/src/solaris/native/sun/awt/awt_GraphicsEnv.h Wed Nov 25 11:08:25 2009 -0800
427.3 @@ -42,6 +42,10 @@
427.4 #include <sys/ipc.h>
427.5 #include <sys/shm.h>
427.6 #include <X11/extensions/XShm.h>
427.7 +#ifndef X_ShmAttach
427.8 +#include <X11/Xmd.h>
427.9 +#include <X11/extensions/shmproto.h>
427.10 +#endif
427.11
427.12 extern int XShmQueryExtension();
427.13
428.1 --- a/src/solaris/native/sun/awt/gtk2_interface.c Mon Nov 23 10:04:47 2009 +0000
428.2 +++ b/src/solaris/native/sun/awt/gtk2_interface.c Wed Nov 25 11:08:25 2009 -0800
428.3 @@ -637,13 +637,13 @@
428.4 if (gtk_modules_env && strstr (gtk_modules_env, "atk-bridge") ||
428.5 gtk_modules_env && strstr (gtk_modules_env, "gail"))
428.6 {
428.7 - gchar *tmp_env = strdup (gtk_modules_env);
428.8 /* the new env will be smaller than the old one */
428.9 gchar *s, *new_env = malloc (sizeof(ENV_PREFIX)+strlen (gtk_modules_env));
428.10
428.11 if (new_env != NULL )
428.12 {
428.13 /* careful, strtok modifies its args */
428.14 + gchar *tmp_env = strdup (gtk_modules_env);
428.15 strcpy(new_env, ENV_PREFIX);
428.16
428.17 /* strip out 'atk-bridge' and 'gail' */
429.1 --- a/src/solaris/native/sun/xawt/XToolkit.c Mon Nov 23 10:04:47 2009 +0000
429.2 +++ b/src/solaris/native/sun/xawt/XToolkit.c Wed Nov 25 11:08:25 2009 -0800
429.3 @@ -677,7 +677,7 @@
429.4 jstring ret = NULL;
429.5
429.6 keystr = JNU_GetStringPlatformChars(env, key, NULL);
429.7 - if (key) {
429.8 + if (keystr) {
429.9 ptr = getenv(keystr);
429.10 if (ptr) {
429.11 ret = JNU_NewStringPlatform(env, (const char *) ptr);
430.1 --- a/src/windows/classes/sun/awt/Win32GraphicsDevice.java Mon Nov 23 10:04:47 2009 +0000
430.2 +++ b/src/windows/classes/sun/awt/Win32GraphicsDevice.java Wed Nov 25 11:08:25 2009 -0800
430.3 @@ -165,7 +165,7 @@
430.4 if (defaultConfig != null) {
430.5 configs = new GraphicsConfiguration[1];
430.6 configs[0] = defaultConfig;
430.7 - return configs;
430.8 + return configs.clone();
430.9 }
430.10 }
430.11
430.12 @@ -196,7 +196,7 @@
430.13 configs = new GraphicsConfiguration[v.size()];
430.14 v.copyInto(configs);
430.15 }
430.16 - return configs;
430.17 + return configs.clone();
430.18 }
430.19
430.20 /**
430.21 @@ -353,6 +353,7 @@
430.22 }
430.23 WWindowPeer peer = (WWindowPeer)old.getPeer();
430.24 if (peer != null) {
430.25 + peer.setFullScreenExclusiveModeState(false);
430.26 // we used to destroy the buffers on exiting fs mode, this
430.27 // is no longer needed since fs change will cause a surface
430.28 // data replacement
430.29 @@ -370,12 +371,15 @@
430.30 addFSWindowListener(w);
430.31 // Enter full screen exclusive mode.
430.32 WWindowPeer peer = (WWindowPeer)w.getPeer();
430.33 - synchronized(peer) {
430.34 - enterFullScreenExclusive(screen, peer);
430.35 - // Note: removed replaceSurfaceData() call because
430.36 - // changing the window size or making it visible
430.37 - // will cause this anyway, and both of these events happen
430.38 - // as part of switching into fullscreen mode.
430.39 + if (peer != null) {
430.40 + synchronized(peer) {
430.41 + enterFullScreenExclusive(screen, peer);
430.42 + // Note: removed replaceSurfaceData() call because
430.43 + // changing the window size or making it visible
430.44 + // will cause this anyway, and both of these events happen
430.45 + // as part of switching into fullscreen mode.
430.46 + }
430.47 + peer.setFullScreenExclusiveModeState(true);
430.48 }
430.49
430.50 // fix for 4868278
431.1 --- a/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java Mon Nov 23 10:04:47 2009 +0000
431.2 +++ b/src/windows/classes/sun/awt/shell/Win32ShellFolder2.java Wed Nov 25 11:08:25 2009 -0800
431.3 @@ -524,7 +524,7 @@
431.4 // NOTE: this method uses COM and must be called on the 'COM thread'. See ComInvoker for the details
431.5 private static native int compareIDs(long pParentIShellFolder, long pidl1, long pidl2);
431.6
431.7 - private Boolean cachedIsFileSystem;
431.8 + private volatile Boolean cachedIsFileSystem;
431.9
431.10 /**
431.11 * @return Whether this is a file system shell folder
431.12 @@ -693,29 +693,32 @@
431.13 ArrayList<Win32ShellFolder2> list = new ArrayList<Win32ShellFolder2>();
431.14 long pEnumObjects = getEnumObjects(includeHiddenFiles);
431.15 if (pEnumObjects != 0) {
431.16 - long childPIDL;
431.17 - int testedAttrs = ATTRIB_FILESYSTEM | ATTRIB_FILESYSANCESTOR;
431.18 - do {
431.19 - childPIDL = getNextChild(pEnumObjects);
431.20 - boolean releasePIDL = true;
431.21 - if (childPIDL != 0 &&
431.22 - (getAttributes0(pIShellFolder, childPIDL, testedAttrs) & testedAttrs) != 0) {
431.23 - Win32ShellFolder2 childFolder;
431.24 - if (Win32ShellFolder2.this.equals(desktop)
431.25 - && personal != null
431.26 - && pidlsEqual(pIShellFolder, childPIDL, personal.disposer.relativePIDL)) {
431.27 - childFolder = personal;
431.28 - } else {
431.29 - childFolder = new Win32ShellFolder2(Win32ShellFolder2.this, childPIDL);
431.30 - releasePIDL = false;
431.31 + try {
431.32 + long childPIDL;
431.33 + int testedAttrs = ATTRIB_FILESYSTEM | ATTRIB_FILESYSANCESTOR;
431.34 + do {
431.35 + childPIDL = getNextChild(pEnumObjects);
431.36 + boolean releasePIDL = true;
431.37 + if (childPIDL != 0 &&
431.38 + (getAttributes0(pIShellFolder, childPIDL, testedAttrs) & testedAttrs) != 0) {
431.39 + Win32ShellFolder2 childFolder;
431.40 + if (Win32ShellFolder2.this.equals(desktop)
431.41 + && personal != null
431.42 + && pidlsEqual(pIShellFolder, childPIDL, personal.disposer.relativePIDL)) {
431.43 + childFolder = personal;
431.44 + } else {
431.45 + childFolder = new Win32ShellFolder2(Win32ShellFolder2.this, childPIDL);
431.46 + releasePIDL = false;
431.47 + }
431.48 + list.add(childFolder);
431.49 }
431.50 - list.add(childFolder);
431.51 - }
431.52 - if (releasePIDL) {
431.53 - releasePIDL(childPIDL);
431.54 - }
431.55 - } while (childPIDL != 0 && !Thread.currentThread().isInterrupted());
431.56 - releaseEnumObjects(pEnumObjects);
431.57 + if (releasePIDL) {
431.58 + releasePIDL(childPIDL);
431.59 + }
431.60 + } while (childPIDL != 0 && !Thread.currentThread().isInterrupted());
431.61 + } finally {
431.62 + releaseEnumObjects(pEnumObjects);
431.63 + }
431.64 }
431.65 return Thread.currentThread().isInterrupted()
431.66 ? new File[0]
431.67 @@ -759,7 +762,7 @@
431.68 }, InterruptedException.class);
431.69 }
431.70
431.71 - private Boolean cachedIsLink;
431.72 + private volatile Boolean cachedIsLink;
431.73
431.74 /**
431.75 * @return Whether this shell folder is a link
432.1 --- a/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Mon Nov 23 10:04:47 2009 +0000
432.2 +++ b/src/windows/classes/sun/awt/shell/Win32ShellFolderManager2.java Wed Nov 25 11:08:25 2009 -0800
432.3 @@ -79,9 +79,12 @@
432.4 // Shouldn't happen but watch for it anyway
432.5 throw new FileNotFoundException("File " + file.getAbsolutePath() + " not found");
432.6 }
432.7 - Win32ShellFolder2 folder = createShellFolderFromRelativePIDL(parent, pIDL);
432.8 - Win32ShellFolder2.releasePIDL(pIDL);
432.9 - return folder;
432.10 +
432.11 + try {
432.12 + return createShellFolderFromRelativePIDL(parent, pIDL);
432.13 + } finally {
432.14 + Win32ShellFolder2.releasePIDL(pIDL);
432.15 + }
432.16 }
432.17
432.18 static Win32ShellFolder2 createShellFolderFromRelativePIDL(Win32ShellFolder2 parent, long pIDL)
432.19 @@ -269,7 +272,7 @@
432.20 Arrays.sort(secondLevelFolders);
432.21 for (File secondLevelFolder : secondLevelFolders) {
432.22 Win32ShellFolder2 folder = (Win32ShellFolder2) secondLevelFolder;
432.23 - if (!folder.isFileSystem() || folder.isDirectory()) {
432.24 + if (!folder.isFileSystem() || (folder.isDirectory() && !folder.isLink())) {
432.25 folders.add(folder);
432.26 // Add third level for "My Computer"
432.27 if (folder.equals(drives)) {
433.1 --- a/src/windows/classes/sun/awt/windows/WComponentPeer.java Mon Nov 23 10:04:47 2009 +0000
433.2 +++ b/src/windows/classes/sun/awt/windows/WComponentPeer.java Wed Nov 25 11:08:25 2009 -0800
433.3 @@ -550,8 +550,34 @@
433.4 final static Font defaultFont = new Font(Font.DIALOG, Font.PLAIN, 12);
433.5
433.6 public Graphics getGraphics() {
433.7 + if (isDisposed()) {
433.8 + return null;
433.9 + }
433.10 +
433.11 + Component target = (Component)getTarget();
433.12 + Window window = SunToolkit.getContainingWindow(target);
433.13 + if (window != null && !window.isOpaque()) {
433.14 + // Non-opaque windows do not support heavyweight children.
433.15 + // Redirect all painting to the Window's Graphics instead.
433.16 + // The caller is responsible for calling the
433.17 + // WindowPeer.updateWindow() after painting has finished.
433.18 + int x = 0, y = 0;
433.19 + for (Component c = target; c != window; c = c.getParent()) {
433.20 + x += c.getX();
433.21 + y += c.getY();
433.22 + }
433.23 +
433.24 + Graphics g =
433.25 + ((WWindowPeer)window.getPeer()).getTranslucentGraphics();
433.26 +
433.27 + g.translate(x, y);
433.28 + g.clipRect(0, 0, target.getWidth(), target.getHeight());
433.29 +
433.30 + return g;
433.31 + }
433.32 +
433.33 SurfaceData surfaceData = this.surfaceData;
433.34 - if (!isDisposed() && surfaceData != null) {
433.35 + if (surfaceData != null) {
433.36 /* Fix for bug 4746122. Color and Font shouldn't be null */
433.37 Color bgColor = background;
433.38 if (bgColor == null) {
434.1 --- a/src/windows/classes/sun/awt/windows/WWindowPeer.java Mon Nov 23 10:04:47 2009 +0000
434.2 +++ b/src/windows/classes/sun/awt/windows/WWindowPeer.java Wed Nov 25 11:08:25 2009 -0800
434.3 @@ -510,6 +510,9 @@
434.4
434.5 private native int getScreenImOn();
434.6
434.7 + // Used in Win32GraphicsDevice.
434.8 + public final native void setFullScreenExclusiveModeState(boolean state);
434.9 +
434.10 /*
434.11 * ----END DISPLAY CHANGE SUPPORT----
434.12 */
434.13 @@ -575,11 +578,17 @@
434.14 }
434.15 }
434.16
434.17 + public final Graphics getTranslucentGraphics() {
434.18 + synchronized (getStateLock()) {
434.19 + return isOpaque ? null : painter.getBackBuffer(false).getGraphics();
434.20 + }
434.21 + }
434.22 +
434.23 @Override
434.24 public Graphics getGraphics() {
434.25 synchronized (getStateLock()) {
434.26 if (!isOpaque) {
434.27 - return painter.getBackBuffer(false).getGraphics();
434.28 + return getTranslucentGraphics();
434.29 }
434.30 }
434.31 return super.getGraphics();
435.1 --- a/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java Mon Nov 23 10:04:47 2009 +0000
435.2 +++ b/src/windows/classes/sun/java2d/d3d/D3DGraphicsDevice.java Wed Nov 25 11:08:25 2009 -0800
435.3 @@ -429,7 +429,7 @@
435.4 if (defaultConfig != null) {
435.5 configs = new GraphicsConfiguration[1];
435.6 configs[0] = defaultConfig;
435.7 - return configs;
435.8 + return configs.clone();
435.9 }
435.10 }
435.11 }
436.1 --- a/src/windows/classes/sun/java2d/windows/GDIWindowSurfaceData.java Mon Nov 23 10:04:47 2009 +0000
436.2 +++ b/src/windows/classes/sun/java2d/windows/GDIWindowSurfaceData.java Wed Nov 25 11:08:25 2009 -0800
436.3 @@ -210,7 +210,10 @@
436.4 // if a GlyphVector overrides the AA setting.
436.5 // We use getRenderLoops() rather than setting solidloops
436.6 // directly so that we get the appropriate loops in XOR mode.
436.7 - sg2d.loops = getRenderLoops(sg2d);
436.8 + if (sg2d.loops == null) {
436.9 + // assert(some pipe will always be a LoopBasedPipe)
436.10 + sg2d.loops = getRenderLoops(sg2d);
436.11 + }
436.12 } else {
436.13 super.validatePipe(sg2d);
436.14 }
437.1 --- a/src/windows/classes/sun/net/www/protocol/http/NTLMAuthSequence.java Mon Nov 23 10:04:47 2009 +0000
437.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
437.3 @@ -1,85 +0,0 @@
437.4 -/*
437.5 - * Copyright 2002 Sun Microsystems, Inc. All Rights Reserved.
437.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
437.7 - *
437.8 - * This code is free software; you can redistribute it and/or modify it
437.9 - * under the terms of the GNU General Public License version 2 only, as
437.10 - * published by the Free Software Foundation. Sun designates this
437.11 - * particular file as subject to the "Classpath" exception as provided
437.12 - * by Sun in the LICENSE file that accompanied this code.
437.13 - *
437.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
437.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
437.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
437.17 - * version 2 for more details (a copy is included in the LICENSE file that
437.18 - * accompanied this code).
437.19 - *
437.20 - * You should have received a copy of the GNU General Public License version
437.21 - * 2 along with this work; if not, write to the Free Software Foundation,
437.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
437.23 - *
437.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
437.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
437.26 - * have any questions.
437.27 - */
437.28 -
437.29 -package sun.net.www.protocol.http;
437.30 -
437.31 -import java.io.IOException;
437.32 -import sun.misc.BASE64Encoder;
437.33 -import sun.misc.BASE64Decoder;
437.34 -
437.35 -/*
437.36 - * Hooks into Windows implementation of NTLM.
437.37 - * This class will be replaced if a cross-platform version of NTLM
437.38 - * is implemented in the future.
437.39 - */
437.40 -
437.41 -public class NTLMAuthSequence {
437.42 -
437.43 - private String username;
437.44 - private String password;
437.45 - private String ntdomain;
437.46 - private int state;
437.47 - private long crdHandle;
437.48 - private long ctxHandle;
437.49 -
437.50 - static {
437.51 - initFirst();
437.52 - }
437.53 -
437.54 - NTLMAuthSequence (String username, String password, String ntdomain)
437.55 - throws IOException
437.56 - {
437.57 - this.username = username;
437.58 - this.password = password;
437.59 - this.ntdomain = ntdomain;
437.60 - state = 0;
437.61 - crdHandle = getCredentialsHandle (username, ntdomain, password);
437.62 - if (crdHandle == 0) {
437.63 - throw new IOException ("could not get credentials handle");
437.64 - }
437.65 - }
437.66 -
437.67 - public String getAuthHeader (String token) throws IOException {
437.68 - byte[] input = null;
437.69 - if (token != null)
437.70 - input = (new BASE64Decoder()).decodeBuffer(token);
437.71 - byte[] b = getNextToken (crdHandle, input);
437.72 - if (b == null)
437.73 - throw new IOException ("Internal authentication error");
437.74 - return (new B64Encoder()).encode (b);
437.75 - }
437.76 -
437.77 - private native static void initFirst ();
437.78 -
437.79 - private native long getCredentialsHandle (String user, String domain, String password);
437.80 -
437.81 - private native byte[] getNextToken (long crdHandle, byte[] lastToken);
437.82 -}
437.83 -
437.84 -class B64Encoder extends BASE64Encoder {
437.85 - protected int bytesPerLine () {
437.86 - return 1024;
437.87 - }
437.88 -}
438.1 --- a/src/windows/classes/sun/net/www/protocol/http/NTLMAuthentication.java Mon Nov 23 10:04:47 2009 +0000
438.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
438.3 @@ -1,195 +0,0 @@
438.4 -/*
438.5 - * Copyright 2002-2005 Sun Microsystems, Inc. All Rights Reserved.
438.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
438.7 - *
438.8 - * This code is free software; you can redistribute it and/or modify it
438.9 - * under the terms of the GNU General Public License version 2 only, as
438.10 - * published by the Free Software Foundation. Sun designates this
438.11 - * particular file as subject to the "Classpath" exception as provided
438.12 - * by Sun in the LICENSE file that accompanied this code.
438.13 - *
438.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
438.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
438.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
438.17 - * version 2 for more details (a copy is included in the LICENSE file that
438.18 - * accompanied this code).
438.19 - *
438.20 - * You should have received a copy of the GNU General Public License version
438.21 - * 2 along with this work; if not, write to the Free Software Foundation,
438.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
438.23 - *
438.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
438.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
438.26 - * have any questions.
438.27 - */
438.28 -
438.29 -package sun.net.www.protocol.http;
438.30 -
438.31 -import java.io.IOException;
438.32 -import java.net.InetAddress;
438.33 -import java.net.PasswordAuthentication;
438.34 -import java.net.UnknownHostException;
438.35 -import java.net.URL;
438.36 -import sun.net.www.HeaderParser;
438.37 -
438.38 -/**
438.39 - * NTLMAuthentication:
438.40 - *
438.41 - * @author Michael McMahon
438.42 - */
438.43 -
438.44 -class NTLMAuthentication extends AuthenticationInfo {
438.45 -
438.46 - private static final long serialVersionUID = 100L;
438.47 -
438.48 - private String hostname;
438.49 - private static String defaultDomain; /* Domain to use if not specified by user */
438.50 -
438.51 - static {
438.52 - defaultDomain = java.security.AccessController.doPrivileged(
438.53 - new sun.security.action.GetPropertyAction("http.auth.ntlm.domain",
438.54 - "domain"));
438.55 - };
438.56 -
438.57 - private void init0() {
438.58 -
438.59 - hostname = java.security.AccessController.doPrivileged(
438.60 - new java.security.PrivilegedAction<String>() {
438.61 - public String run() {
438.62 - String localhost;
438.63 - try {
438.64 - localhost = InetAddress.getLocalHost().getHostName().toUpperCase();
438.65 - } catch (UnknownHostException e) {
438.66 - localhost = "localhost";
438.67 - }
438.68 - return localhost;
438.69 - }
438.70 - });
438.71 - int x = hostname.indexOf ('.');
438.72 - if (x != -1) {
438.73 - hostname = hostname.substring (0, x);
438.74 - }
438.75 - }
438.76 -
438.77 - String username;
438.78 - String ntdomain;
438.79 - String password;
438.80 -
438.81 - /**
438.82 - * Create a NTLMAuthentication:
438.83 - * Username may be specified as domain<BACKSLASH>username in the application Authenticator.
438.84 - * If this notation is not used, then the domain will be taken
438.85 - * from a system property: "http.auth.ntlm.domain".
438.86 - */
438.87 - public NTLMAuthentication(boolean isProxy, URL url, PasswordAuthentication pw) {
438.88 - super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
438.89 - AuthScheme.NTLM,
438.90 - url,
438.91 - "");
438.92 - init (pw);
438.93 - }
438.94 -
438.95 - private void init (PasswordAuthentication pw) {
438.96 - this.pw = pw;
438.97 - if (pw != null) {
438.98 - String s = pw.getUserName();
438.99 - int i = s.indexOf ('\\');
438.100 - if (i == -1) {
438.101 - username = s;
438.102 - ntdomain = defaultDomain;
438.103 - } else {
438.104 - ntdomain = s.substring (0, i).toUpperCase();
438.105 - username = s.substring (i+1);
438.106 - }
438.107 - password = new String (pw.getPassword());
438.108 - } else {
438.109 - /* credentials will be acquired from OS */
438.110 - username = null;
438.111 - ntdomain = null;
438.112 - password = null;
438.113 - }
438.114 - init0();
438.115 - }
438.116 -
438.117 - /**
438.118 - * Constructor used for proxy entries
438.119 - */
438.120 - public NTLMAuthentication(boolean isProxy, String host, int port,
438.121 - PasswordAuthentication pw) {
438.122 - super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION,
438.123 - AuthScheme.NTLM,
438.124 - host,
438.125 - port,
438.126 - "");
438.127 - init (pw);
438.128 - }
438.129 -
438.130 - /**
438.131 - * @return true if this authentication supports preemptive authorization
438.132 - */
438.133 - boolean supportsPreemptiveAuthorization() {
438.134 - return false;
438.135 - }
438.136 -
438.137 - /**
438.138 - * @return true if NTLM supported transparently (no password needed, SSO)
438.139 - */
438.140 - static boolean supportsTransparentAuth() {
438.141 - return true;
438.142 - }
438.143 -
438.144 - /**
438.145 - * @return the name of the HTTP header this authentication wants set
438.146 - */
438.147 - String getHeaderName() {
438.148 - if (type == SERVER_AUTHENTICATION) {
438.149 - return "Authorization";
438.150 - } else {
438.151 - return "Proxy-authorization";
438.152 - }
438.153 - }
438.154 -
438.155 - /**
438.156 - * Not supported. Must use the setHeaders() method
438.157 - */
438.158 - String getHeaderValue(URL url, String method) {
438.159 - throw new RuntimeException ("getHeaderValue not supported");
438.160 - }
438.161 -
438.162 - /**
438.163 - * Check if the header indicates that the current auth. parameters are stale.
438.164 - * If so, then replace the relevant field with the new value
438.165 - * and return true. Otherwise return false.
438.166 - * returning true means the request can be retried with the same userid/password
438.167 - * returning false means we have to go back to the user to ask for a new
438.168 - * username password.
438.169 - */
438.170 - boolean isAuthorizationStale (String header) {
438.171 - return false; /* should not be called for ntlm */
438.172 - }
438.173 -
438.174 - /**
438.175 - * Set header(s) on the given connection.
438.176 - * @param conn The connection to apply the header(s) to
438.177 - * @param p A source of header values for this connection, not used because
438.178 - * HeaderParser converts the fields to lower case, use raw instead
438.179 - * @param raw The raw header field.
438.180 - * @return true if all goes well, false if no headers were set.
438.181 - */
438.182 - synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
438.183 -
438.184 - try {
438.185 - NTLMAuthSequence seq = (NTLMAuthSequence)conn.authObj;
438.186 - if (seq == null) {
438.187 - seq = new NTLMAuthSequence (username, password, ntdomain);
438.188 - conn.authObj = seq;
438.189 - }
438.190 - String response = "NTLM " + seq.getAuthHeader (raw.length()>6?raw.substring(5):null);
438.191 - conn.setAuthenticationProperty(getHeaderName(), response);
438.192 - return true;
438.193 - } catch (IOException e) {
438.194 - return false;
438.195 - }
438.196 - }
438.197 -
438.198 -}
439.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
439.2 +++ b/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java Wed Nov 25 11:08:25 2009 -0800
439.3 @@ -0,0 +1,85 @@
439.4 +/*
439.5 + * Copyright 2002 Sun Microsystems, Inc. All Rights Reserved.
439.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
439.7 + *
439.8 + * This code is free software; you can redistribute it and/or modify it
439.9 + * under the terms of the GNU General Public License version 2 only, as
439.10 + * published by the Free Software Foundation. Sun designates this
439.11 + * particular file as subject to the "Classpath" exception as provided
439.12 + * by Sun in the LICENSE file that accompanied this code.
439.13 + *
439.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
439.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
439.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
439.17 + * version 2 for more details (a copy is included in the LICENSE file that
439.18 + * accompanied this code).
439.19 + *
439.20 + * You should have received a copy of the GNU General Public License version
439.21 + * 2 along with this work; if not, write to the Free Software Foundation,
439.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
439.23 + *
439.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
439.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
439.26 + * have any questions.
439.27 + */
439.28 +
439.29 +package sun.net.www.protocol.http.ntlm;
439.30 +
439.31 +import java.io.IOException;
439.32 +import sun.misc.BASE64Encoder;
439.33 +import sun.misc.BASE64Decoder;
439.34 +
439.35 +/*
439.36 + * Hooks into Windows implementation of NTLM.
439.37 + * This class will be replaced if a cross-platform version of NTLM
439.38 + * is implemented in the future.
439.39 + */
439.40 +
439.41 +public class NTLMAuthSequence {
439.42 +
439.43 + private String username;
439.44 + private String password;
439.45 + private String ntdomain;
439.46 + private int state;
439.47 + private long crdHandle;
439.48 + private long ctxHandle;
439.49 +
439.50 + static {
439.51 + initFirst();
439.52 + }
439.53 +
439.54 + NTLMAuthSequence (String username, String password, String ntdomain)
439.55 + throws IOException
439.56 + {
439.57 + this.username = username;
439.58 + this.password = password;
439.59 + this.ntdomain = ntdomain;
439.60 + state = 0;
439.61 + crdHandle = getCredentialsHandle (username, ntdomain, password);
439.62 + if (crdHandle == 0) {
439.63 + throw new IOException ("could not get credentials handle");
439.64 + }
439.65 + }
439.66 +
439.67 + public String getAuthHeader (String token) throws IOException {
439.68 + byte[] input = null;
439.69 + if (token != null)
439.70 + input = (new BASE64Decoder()).decodeBuffer(token);
439.71 + byte[] b = getNextToken (crdHandle, input);
439.72 + if (b == null)
439.73 + throw new IOException ("Internal authentication error");
439.74 + return (new B64Encoder()).encode (b);
439.75 + }
439.76 +
439.77 + private native static void initFirst ();
439.78 +
439.79 + private native long getCredentialsHandle (String user, String domain, String password);
439.80 +
439.81 + private native byte[] getNextToken (long crdHandle, byte[] lastToken);
439.82 +}
439.83 +
439.84 +class B64Encoder extends BASE64Encoder {
439.85 + protected int bytesPerLine () {
439.86 + return 1024;
439.87 + }
439.88 +}
440.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
440.2 +++ b/src/windows/classes/sun/net/www/protocol/http/ntlm/NTLMAuthentication.java Wed Nov 25 11:08:25 2009 -0800
440.3 @@ -0,0 +1,191 @@
440.4 +/*
440.5 + * Copyright 2002-2005 Sun Microsystems, Inc. All Rights Reserved.
440.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
440.7 + *
440.8 + * This code is free software; you can redistribute it and/or modify it
440.9 + * under the terms of the GNU General Public License version 2 only, as
440.10 + * published by the Free Software Foundation. Sun designates this
440.11 + * particular file as subject to the "Classpath" exception as provided
440.12 + * by Sun in the LICENSE file that accompanied this code.
440.13 + *
440.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
440.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
440.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
440.17 + * version 2 for more details (a copy is included in the LICENSE file that
440.18 + * accompanied this code).
440.19 + *
440.20 + * You should have received a copy of the GNU General Public License version
440.21 + * 2 along with this work; if not, write to the Free Software Foundation,
440.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
440.23 + *
440.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
440.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
440.26 + * have any questions.
440.27 + */
440.28 +
440.29 +package sun.net.www.protocol.http.ntlm;
440.30 +
440.31 +import java.io.IOException;
440.32 +import java.net.InetAddress;
440.33 +import java.net.PasswordAuthentication;
440.34 +import java.net.UnknownHostException;
440.35 +import java.net.URL;
440.36 +import sun.net.www.HeaderParser;
440.37 +import sun.net.www.protocol.http.AuthenticationInfo;
440.38 +import sun.net.www.protocol.http.AuthScheme;
440.39 +import sun.net.www.protocol.http.HttpURLConnection;
440.40 +
440.41 +/**
440.42 + * NTLMAuthentication:
440.43 + *
440.44 + * @author Michael McMahon
440.45 + */
440.46 +
440.47 +public class NTLMAuthentication extends AuthenticationInfo {
440.48 +
440.49 + private static final long serialVersionUID = 100L;
440.50 +
440.51 + private String hostname;
440.52 + private static String defaultDomain; /* Domain to use if not specified by user */
440.53 +
440.54 + static {
440.55 + defaultDomain = java.security.AccessController.doPrivileged(
440.56 + new sun.security.action.GetPropertyAction("http.auth.ntlm.domain",
440.57 + "domain"));
440.58 + };
440.59 +
440.60 + private void init0() {
440.61 +
440.62 + hostname = java.security.AccessController.doPrivileged(
440.63 + new java.security.PrivilegedAction<String>() {
440.64 + public String run() {
440.65 + String localhost;
440.66 + try {
440.67 + localhost = InetAddress.getLocalHost().getHostName().toUpperCase();
440.68 + } catch (UnknownHostException e) {
440.69 + localhost = "localhost";
440.70 + }
440.71 + return localhost;
440.72 + }
440.73 + });
440.74 + int x = hostname.indexOf ('.');
440.75 + if (x != -1) {
440.76 + hostname = hostname.substring (0, x);
440.77 + }
440.78 + }
440.79 +
440.80 + String username;
440.81 + String ntdomain;
440.82 + String password;
440.83 +
440.84 + /**
440.85 + * Create a NTLMAuthentication:
440.86 + * Username may be specified as domain<BACKSLASH>username in the application Authenticator.
440.87 + * If this notation is not used, then the domain will be taken
440.88 + * from a system property: "http.auth.ntlm.domain".
440.89 + */
440.90 + public NTLMAuthentication(boolean isProxy, URL url, PasswordAuthentication pw) {
440.91 + super(isProxy ? PROXY_AUTHENTICATION : SERVER_AUTHENTICATION,
440.92 + AuthScheme.NTLM,
440.93 + url,
440.94 + "");
440.95 + init (pw);
440.96 + }
440.97 +
440.98 + private void init (PasswordAuthentication pw) {
440.99 + this.pw = pw;
440.100 + if (pw != null) {
440.101 + String s = pw.getUserName();
440.102 + int i = s.indexOf ('\\');
440.103 + if (i == -1) {
440.104 + username = s;
440.105 + ntdomain = defaultDomain;
440.106 + } else {
440.107 + ntdomain = s.substring (0, i).toUpperCase();
440.108 + username = s.substring (i+1);
440.109 + }
440.110 + password = new String (pw.getPassword());
440.111 + } else {
440.112 + /* credentials will be acquired from OS */
440.113 + username = null;
440.114 + ntdomain = null;
440.115 + password = null;
440.116 + }
440.117 + init0();
440.118 + }
440.119 +
440.120 + /**
440.121 + * Constructor used for proxy entries
440.122 + */
440.123 + public NTLMAuthentication(boolean isProxy, String host, int port,
440.124 + PasswordAuthentication pw) {
440.125 + super(isProxy?PROXY_AUTHENTICATION:SERVER_AUTHENTICATION,
440.126 + AuthScheme.NTLM,
440.127 + host,
440.128 + port,
440.129 + "");
440.130 + init (pw);
440.131 + }
440.132 +
440.133 + /**
440.134 + * @return true if this authentication supports preemptive authorization
440.135 + */
440.136 + @Override
440.137 + public boolean supportsPreemptiveAuthorization() {
440.138 + return false;
440.139 + }
440.140 +
440.141 + /**
440.142 + * @return true if NTLM supported transparently (no password needed, SSO)
440.143 + */
440.144 + public static boolean supportsTransparentAuth() {
440.145 + return true;
440.146 + }
440.147 +
440.148 + /**
440.149 + * Not supported. Must use the setHeaders() method
440.150 + */
440.151 + @Override
440.152 + public String getHeaderValue(URL url, String method) {
440.153 + throw new RuntimeException ("getHeaderValue not supported");
440.154 + }
440.155 +
440.156 + /**
440.157 + * Check if the header indicates that the current auth. parameters are stale.
440.158 + * If so, then replace the relevant field with the new value
440.159 + * and return true. Otherwise return false.
440.160 + * returning true means the request can be retried with the same userid/password
440.161 + * returning false means we have to go back to the user to ask for a new
440.162 + * username password.
440.163 + */
440.164 + @Override
440.165 + public boolean isAuthorizationStale (String header) {
440.166 + return false; /* should not be called for ntlm */
440.167 + }
440.168 +
440.169 + /**
440.170 + * Set header(s) on the given connection.
440.171 + * @param conn The connection to apply the header(s) to
440.172 + * @param p A source of header values for this connection, not used because
440.173 + * HeaderParser converts the fields to lower case, use raw instead
440.174 + * @param raw The raw header field.
440.175 + * @return true if all goes well, false if no headers were set.
440.176 + */
440.177 + @Override
440.178 + public synchronized boolean setHeaders(HttpURLConnection conn, HeaderParser p, String raw) {
440.179 +
440.180 + try {
440.181 + NTLMAuthSequence seq = (NTLMAuthSequence)conn.authObj();
440.182 + if (seq == null) {
440.183 + seq = new NTLMAuthSequence (username, password, ntdomain);
440.184 + conn.authObj(seq);
440.185 + }
440.186 + String response = "NTLM " + seq.getAuthHeader (raw.length()>6?raw.substring(5):null);
440.187 + conn.setAuthenticationProperty(getHeaderName(), response);
440.188 + return true;
440.189 + } catch (IOException e) {
440.190 + return false;
440.191 + }
440.192 + }
440.193 +
440.194 +}
441.1 --- a/src/windows/native/sun/net/www/protocol/http/NTLMAuthSequence.c Mon Nov 23 10:04:47 2009 +0000
441.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
441.3 @@ -1,311 +0,0 @@
441.4 -/*
441.5 - * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
441.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
441.7 - *
441.8 - * This code is free software; you can redistribute it and/or modify it
441.9 - * under the terms of the GNU General Public License version 2 only, as
441.10 - * published by the Free Software Foundation. Sun designates this
441.11 - * particular file as subject to the "Classpath" exception as provided
441.12 - * by Sun in the LICENSE file that accompanied this code.
441.13 - *
441.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
441.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
441.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
441.17 - * version 2 for more details (a copy is included in the LICENSE file that
441.18 - * accompanied this code).
441.19 - *
441.20 - * You should have received a copy of the GNU General Public License version
441.21 - * 2 along with this work; if not, write to the Free Software Foundation,
441.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
441.23 - *
441.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
441.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
441.26 - * have any questions.
441.27 - */
441.28 -
441.29 -#include <jni.h>
441.30 -#include <windows.h>
441.31 -#include <rpc.h>
441.32 -#include <winsock.h>
441.33 -#include <lm.h>
441.34 -
441.35 -#include <stdio.h>
441.36 -#include <stdarg.h>
441.37 -#include <stdlib.h>
441.38 -#include <string.h>
441.39 -#include <tchar.h>
441.40 -#include <fcntl.h>
441.41 -
441.42 -#include "jni_util.h"
441.43 -
441.44 -#define SECURITY_WIN32
441.45 -#include "sspi.h"
441.46 -
441.47 -
441.48 -/*
441.49 - * OS calls loaded from DLL on intialization
441.50 - */
441.51 -
441.52 -static FREE_CREDENTIALS_HANDLE_FN pFreeCredentialsHandle;
441.53 -static ACQUIRE_CREDENTIALS_HANDLE_FN pAcquireCredentialsHandle;
441.54 -static FREE_CONTEXT_BUFFER_FN pFreeContextBuffer;
441.55 -static INITIALIZE_SECURITY_CONTEXT_FN pInitializeSecurityContext;
441.56 -static COMPLETE_AUTH_TOKEN_FN pCompleteAuthToken;
441.57 -static DELETE_SECURITY_CONTEXT_FN pDeleteSecurityContext;
441.58 -
441.59 -static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle);
441.60 -
441.61 -static jfieldID ntlm_ctxHandleID;
441.62 -static jfieldID ntlm_crdHandleID;
441.63 -
441.64 -static HINSTANCE lib = NULL;
441.65 -
441.66 -JNIEXPORT void JNICALL Java_sun_net_www_protocol_http_NTLMAuthSequence_initFirst
441.67 -(JNIEnv *env, jclass clazz)
441.68 -{
441.69 - OSVERSIONINFO version;
441.70 - UCHAR libName[MAX_PATH];
441.71 -
441.72 - ntlm_ctxHandleID = (*env)->GetFieldID(env, clazz, "ctxHandle", "J");
441.73 - ntlm_crdHandleID = (*env)->GetFieldID(env, clazz, "crdHandle", "J");
441.74 -
441.75 - version.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
441.76 - GetVersionEx (&version);
441.77 -
441.78 - if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
441.79 - strcpy (libName, "security.dll" );
441.80 - }
441.81 - else if (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
441.82 - strcpy (libName, "secur32.dll" );
441.83 - }
441.84 -
441.85 - lib = LoadLibrary (libName);
441.86 -
441.87 - pFreeCredentialsHandle
441.88 - = (FREE_CREDENTIALS_HANDLE_FN) GetProcAddress(
441.89 - lib, "FreeCredentialsHandle" );
441.90 -
441.91 - pAcquireCredentialsHandle
441.92 - = (ACQUIRE_CREDENTIALS_HANDLE_FN) GetProcAddress(
441.93 - lib, "AcquireCredentialsHandleA" );
441.94 -
441.95 - pFreeContextBuffer
441.96 - = (FREE_CONTEXT_BUFFER_FN) GetProcAddress(
441.97 - lib, "FreeContextBuffer" );
441.98 -
441.99 - pInitializeSecurityContext
441.100 - = (INITIALIZE_SECURITY_CONTEXT_FN) GetProcAddress(
441.101 - lib, "InitializeSecurityContextA" );
441.102 -
441.103 - pCompleteAuthToken
441.104 - = (COMPLETE_AUTH_TOKEN_FN) GetProcAddress(
441.105 - lib, "CompleteAuthToken" );
441.106 -
441.107 - pDeleteSecurityContext
441.108 - = (DELETE_SECURITY_CONTEXT_FN) GetProcAddress(
441.109 - lib, "DeleteSecurityContext" );
441.110 -
441.111 -}
441.112 -
441.113 -/*
441.114 - * Class: sun_net_www_protocol_http_NTLMAuthSequence
441.115 - * Method: getCredentialsHandle
441.116 - * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J
441.117 - */
441.118 -
441.119 -JNIEXPORT jlong JNICALL Java_sun_net_www_protocol_http_NTLMAuthSequence_getCredentialsHandle
441.120 -(JNIEnv *env, jobject this, jstring user, jstring domain, jstring password)
441.121 -{
441.122 - SEC_WINNT_AUTH_IDENTITY AuthId;
441.123 - SEC_WINNT_AUTH_IDENTITY * pAuthId;
441.124 - const CHAR *pUser = 0;
441.125 - const CHAR *pDomain = 0;
441.126 - const CHAR *pPassword = 0;
441.127 - CredHandle *pCred;
441.128 - TimeStamp ltime;
441.129 - jboolean isCopy;
441.130 - SECURITY_STATUS ss;
441.131 -
441.132 - if (user != 0) {
441.133 - pUser = JNU_GetStringPlatformChars(env, user, &isCopy);
441.134 - if (pUser == NULL)
441.135 - return 0; // pending Exception
441.136 - }
441.137 - if (domain != 0) {
441.138 - pDomain = JNU_GetStringPlatformChars(env, domain, &isCopy);
441.139 - if (pDomain == NULL) {
441.140 - if (pUser != NULL)
441.141 - JNU_ReleaseStringPlatformChars(env, user, pUser);
441.142 - return 0; // pending Exception
441.143 - }
441.144 - }
441.145 - if (password != 0) {
441.146 - pPassword = JNU_GetStringPlatformChars(env, password, &isCopy);
441.147 - if (pPassword == NULL) {
441.148 - if(pUser != NULL)
441.149 - JNU_ReleaseStringPlatformChars(env, user, pUser);
441.150 - if(pDomain != NULL)
441.151 - JNU_ReleaseStringPlatformChars(env, domain, pDomain);
441.152 - return 0; // pending Exception
441.153 - }
441.154 - }
441.155 - pCred = (CredHandle *)malloc(sizeof (CredHandle));
441.156 -
441.157 - if ( ((pUser != NULL) || (pPassword != NULL)) || (pDomain != NULL)) {
441.158 - pAuthId = &AuthId;
441.159 -
441.160 - memset( &AuthId, 0, sizeof( AuthId ));
441.161 -
441.162 - if ( pUser != NULL ) {
441.163 - AuthId.User = (unsigned char *) pUser;
441.164 - AuthId.UserLength = strlen( pUser );
441.165 - }
441.166 -
441.167 - if ( pPassword != NULL ) {
441.168 - AuthId.Password = (unsigned char *) pPassword;
441.169 - AuthId.PasswordLength = strlen( pPassword );
441.170 - }
441.171 -
441.172 - if ( pDomain != NULL ) {
441.173 - AuthId.Domain = (unsigned char *) pDomain;
441.174 - AuthId.DomainLength = strlen( pDomain );
441.175 - }
441.176 -
441.177 - AuthId.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
441.178 - } else {
441.179 - pAuthId = NULL;
441.180 - }
441.181 -
441.182 - ss = pAcquireCredentialsHandle(
441.183 - NULL, "NTLM", SECPKG_CRED_OUTBOUND,
441.184 - NULL, pAuthId, NULL, NULL,
441.185 - pCred, <ime
441.186 - );
441.187 -
441.188 - /* Release resources held by JNU_GetStringPlatformChars */
441.189 - if (pUser != NULL)
441.190 - JNU_ReleaseStringPlatformChars(env, user, pUser);
441.191 - if (pPassword != NULL)
441.192 - JNU_ReleaseStringPlatformChars(env, password, pPassword);
441.193 - if (pDomain != NULL)
441.194 - JNU_ReleaseStringPlatformChars(env, domain, pDomain);
441.195 -
441.196 - if (ss == 0) {
441.197 - return (jlong) pCred;
441.198 - } else {
441.199 - return 0;
441.200 - }
441.201 -}
441.202 -
441.203 -JNIEXPORT jbyteArray JNICALL Java_sun_net_www_protocol_http_NTLMAuthSequence_getNextToken
441.204 -(JNIEnv *env, jobject this, jlong crdHandle, jbyteArray lastToken)
441.205 -{
441.206 -
441.207 - VOID *pInput = 0;
441.208 - DWORD inputLen;
441.209 - CHAR buffOut[512];
441.210 - jboolean isCopy;
441.211 - SECURITY_STATUS ss;
441.212 - SecBufferDesc OutBuffDesc;
441.213 - SecBuffer OutSecBuff;
441.214 - SecBufferDesc InBuffDesc;
441.215 - SecBuffer InSecBuff;
441.216 - ULONG ContextAttributes;
441.217 - CredHandle *pCred = (CredHandle *)crdHandle;
441.218 - CtxtHandle *pCtx;
441.219 - CtxtHandle *newContext;
441.220 - TimeStamp ltime;
441.221 - jbyteArray result;
441.222 -
441.223 -
441.224 - pCtx = (CtxtHandle *) (*env)->GetLongField (env, this, ntlm_ctxHandleID);
441.225 - if (pCtx == 0) { /* first call */
441.226 - newContext = (CtxtHandle *)malloc(sizeof(CtxtHandle));
441.227 - (*env)->SetLongField (env, this, ntlm_ctxHandleID, (jlong)newContext);
441.228 - } else {
441.229 - newContext = pCtx;
441.230 - }
441.231 -
441.232 - OutBuffDesc.ulVersion = 0;
441.233 - OutBuffDesc.cBuffers = 1;
441.234 - OutBuffDesc.pBuffers = &OutSecBuff;
441.235 -
441.236 - OutSecBuff.cbBuffer = 512;
441.237 - OutSecBuff.BufferType = SECBUFFER_TOKEN;
441.238 - OutSecBuff.pvBuffer = buffOut;
441.239 -
441.240 - /*
441.241 - * Prepare our Input buffer - Note the server is expecting the client's
441.242 - * negotiation packet on the first call
441.243 - */
441.244 -
441.245 - if (lastToken != 0)
441.246 - {
441.247 - pInput = (VOID *)(*env)->GetByteArrayElements(env, lastToken, &isCopy);
441.248 - inputLen = (*env)->GetArrayLength(env, lastToken);
441.249 -
441.250 - InBuffDesc.ulVersion = 0;
441.251 - InBuffDesc.cBuffers = 1;
441.252 - InBuffDesc.pBuffers = &InSecBuff;
441.253 -
441.254 - InSecBuff.cbBuffer = inputLen;
441.255 - InSecBuff.BufferType = SECBUFFER_TOKEN;
441.256 - InSecBuff.pvBuffer = pInput;
441.257 - }
441.258 -
441.259 - /*
441.260 - * will return success when its done but we still
441.261 - * need to send the out buffer if there are bytes to send
441.262 - */
441.263 -
441.264 - ss = pInitializeSecurityContext(
441.265 - pCred, pCtx, NULL, 0, 0, SECURITY_NATIVE_DREP,
441.266 - lastToken ? &InBuffDesc : NULL, 0, newContext, &OutBuffDesc,
441.267 - &ContextAttributes, <ime
441.268 - );
441.269 -
441.270 - if (pInput != 0) {
441.271 - (*env)->ReleaseByteArrayElements(env, lastToken, pInput, JNI_ABORT);
441.272 - }
441.273 -
441.274 - if (ss < 0) {
441.275 - endSequence (pCred, pCtx);
441.276 - return 0;
441.277 - }
441.278 -
441.279 - if ((ss == SEC_I_COMPLETE_NEEDED) || (ss == SEC_I_COMPLETE_AND_CONTINUE) ) {
441.280 - ss = pCompleteAuthToken( pCtx, &OutBuffDesc );
441.281 -
441.282 - if (ss < 0) {
441.283 - endSequence (pCred, pCtx);
441.284 - return 0;
441.285 - }
441.286 - }
441.287 -
441.288 - if ( OutSecBuff.cbBuffer > 0 ) {
441.289 - jbyteArray ret = (*env)->NewByteArray(env, OutSecBuff.cbBuffer);
441.290 - (*env)->SetByteArrayRegion(env, ret, 0, OutSecBuff.cbBuffer,
441.291 - OutSecBuff.pvBuffer);
441.292 - if (lastToken != 0) // 2nd stage
441.293 - endSequence (pCred, pCtx);
441.294 - result = ret;
441.295 - }
441.296 -
441.297 - if ((ss != SEC_I_CONTINUE_NEEDED) && (ss == SEC_I_COMPLETE_AND_CONTINUE)) {
441.298 - endSequence (pCred, pCtx);
441.299 - }
441.300 -
441.301 - return result;
441.302 -}
441.303 -
441.304 -static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle) {
441.305 - if (credHand != 0) {
441.306 - pFreeCredentialsHandle (credHand);
441.307 - free (credHand);
441.308 - }
441.309 -
441.310 - if (ctxHandle != 0) {
441.311 - pDeleteSecurityContext(ctxHandle);
441.312 - free (ctxHandle);
441.313 - }
441.314 -}
442.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
442.2 +++ b/src/windows/native/sun/net/www/protocol/http/ntlm/NTLMAuthSequence.c Wed Nov 25 11:08:25 2009 -0800
442.3 @@ -0,0 +1,311 @@
442.4 +/*
442.5 + * Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
442.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
442.7 + *
442.8 + * This code is free software; you can redistribute it and/or modify it
442.9 + * under the terms of the GNU General Public License version 2 only, as
442.10 + * published by the Free Software Foundation. Sun designates this
442.11 + * particular file as subject to the "Classpath" exception as provided
442.12 + * by Sun in the LICENSE file that accompanied this code.
442.13 + *
442.14 + * This code is distributed in the hope that it will be useful, but WITHOUT
442.15 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
442.16 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
442.17 + * version 2 for more details (a copy is included in the LICENSE file that
442.18 + * accompanied this code).
442.19 + *
442.20 + * You should have received a copy of the GNU General Public License version
442.21 + * 2 along with this work; if not, write to the Free Software Foundation,
442.22 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
442.23 + *
442.24 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
442.25 + * CA 95054 USA or visit www.sun.com if you need additional information or
442.26 + * have any questions.
442.27 + */
442.28 +
442.29 +#include <jni.h>
442.30 +#include <windows.h>
442.31 +#include <rpc.h>
442.32 +#include <winsock.h>
442.33 +#include <lm.h>
442.34 +
442.35 +#include <stdio.h>
442.36 +#include <stdarg.h>
442.37 +#include <stdlib.h>
442.38 +#include <string.h>
442.39 +#include <tchar.h>
442.40 +#include <fcntl.h>
442.41 +
442.42 +#include "jni_util.h"
442.43 +
442.44 +#define SECURITY_WIN32
442.45 +#include "sspi.h"
442.46 +
442.47 +
442.48 +/*
442.49 + * OS calls loaded from DLL on intialization
442.50 + */
442.51 +
442.52 +static FREE_CREDENTIALS_HANDLE_FN pFreeCredentialsHandle;
442.53 +static ACQUIRE_CREDENTIALS_HANDLE_FN pAcquireCredentialsHandle;
442.54 +static FREE_CONTEXT_BUFFER_FN pFreeContextBuffer;
442.55 +static INITIALIZE_SECURITY_CONTEXT_FN pInitializeSecurityContext;
442.56 +static COMPLETE_AUTH_TOKEN_FN pCompleteAuthToken;
442.57 +static DELETE_SECURITY_CONTEXT_FN pDeleteSecurityContext;
442.58 +
442.59 +static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle);
442.60 +
442.61 +static jfieldID ntlm_ctxHandleID;
442.62 +static jfieldID ntlm_crdHandleID;
442.63 +
442.64 +static HINSTANCE lib = NULL;
442.65 +
442.66 +JNIEXPORT void JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_initFirst
442.67 +(JNIEnv *env, jclass clazz)
442.68 +{
442.69 + OSVERSIONINFO version;
442.70 + UCHAR libName[MAX_PATH];
442.71 +
442.72 + ntlm_ctxHandleID = (*env)->GetFieldID(env, clazz, "ctxHandle", "J");
442.73 + ntlm_crdHandleID = (*env)->GetFieldID(env, clazz, "crdHandle", "J");
442.74 +
442.75 + version.dwOSVersionInfoSize = sizeof (OSVERSIONINFO);
442.76 + GetVersionEx (&version);
442.77 +
442.78 + if (version.dwPlatformId == VER_PLATFORM_WIN32_NT) {
442.79 + strcpy (libName, "security.dll" );
442.80 + }
442.81 + else if (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
442.82 + strcpy (libName, "secur32.dll" );
442.83 + }
442.84 +
442.85 + lib = LoadLibrary (libName);
442.86 +
442.87 + pFreeCredentialsHandle
442.88 + = (FREE_CREDENTIALS_HANDLE_FN) GetProcAddress(
442.89 + lib, "FreeCredentialsHandle" );
442.90 +
442.91 + pAcquireCredentialsHandle
442.92 + = (ACQUIRE_CREDENTIALS_HANDLE_FN) GetProcAddress(
442.93 + lib, "AcquireCredentialsHandleA" );
442.94 +
442.95 + pFreeContextBuffer
442.96 + = (FREE_CONTEXT_BUFFER_FN) GetProcAddress(
442.97 + lib, "FreeContextBuffer" );
442.98 +
442.99 + pInitializeSecurityContext
442.100 + = (INITIALIZE_SECURITY_CONTEXT_FN) GetProcAddress(
442.101 + lib, "InitializeSecurityContextA" );
442.102 +
442.103 + pCompleteAuthToken
442.104 + = (COMPLETE_AUTH_TOKEN_FN) GetProcAddress(
442.105 + lib, "CompleteAuthToken" );
442.106 +
442.107 + pDeleteSecurityContext
442.108 + = (DELETE_SECURITY_CONTEXT_FN) GetProcAddress(
442.109 + lib, "DeleteSecurityContext" );
442.110 +
442.111 +}
442.112 +
442.113 +/*
442.114 + * Class: sun_net_www_protocol_http_NTLMAuthSequence
442.115 + * Method: getCredentialsHandle
442.116 + * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)J
442.117 + */
442.118 +
442.119 +JNIEXPORT jlong JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_getCredentialsHandle
442.120 +(JNIEnv *env, jobject this, jstring user, jstring domain, jstring password)
442.121 +{
442.122 + SEC_WINNT_AUTH_IDENTITY AuthId;
442.123 + SEC_WINNT_AUTH_IDENTITY * pAuthId;
442.124 + const CHAR *pUser = 0;
442.125 + const CHAR *pDomain = 0;
442.126 + const CHAR *pPassword = 0;
442.127 + CredHandle *pCred;
442.128 + TimeStamp ltime;
442.129 + jboolean isCopy;
442.130 + SECURITY_STATUS ss;
442.131 +
442.132 + if (user != 0) {
442.133 + pUser = JNU_GetStringPlatformChars(env, user, &isCopy);
442.134 + if (pUser == NULL)
442.135 + return 0; // pending Exception
442.136 + }
442.137 + if (domain != 0) {
442.138 + pDomain = JNU_GetStringPlatformChars(env, domain, &isCopy);
442.139 + if (pDomain == NULL) {
442.140 + if (pUser != NULL)
442.141 + JNU_ReleaseStringPlatformChars(env, user, pUser);
442.142 + return 0; // pending Exception
442.143 + }
442.144 + }
442.145 + if (password != 0) {
442.146 + pPassword = JNU_GetStringPlatformChars(env, password, &isCopy);
442.147 + if (pPassword == NULL) {
442.148 + if(pUser != NULL)
442.149 + JNU_ReleaseStringPlatformChars(env, user, pUser);
442.150 + if(pDomain != NULL)
442.151 + JNU_ReleaseStringPlatformChars(env, domain, pDomain);
442.152 + return 0; // pending Exception
442.153 + }
442.154 + }
442.155 + pCred = (CredHandle *)malloc(sizeof (CredHandle));
442.156 +
442.157 + if ( ((pUser != NULL) || (pPassword != NULL)) || (pDomain != NULL)) {
442.158 + pAuthId = &AuthId;
442.159 +
442.160 + memset( &AuthId, 0, sizeof( AuthId ));
442.161 +
442.162 + if ( pUser != NULL ) {
442.163 + AuthId.User = (unsigned char *) pUser;
442.164 + AuthId.UserLength = strlen( pUser );
442.165 + }
442.166 +
442.167 + if ( pPassword != NULL ) {
442.168 + AuthId.Password = (unsigned char *) pPassword;
442.169 + AuthId.PasswordLength = strlen( pPassword );
442.170 + }
442.171 +
442.172 + if ( pDomain != NULL ) {
442.173 + AuthId.Domain = (unsigned char *) pDomain;
442.174 + AuthId.DomainLength = strlen( pDomain );
442.175 + }
442.176 +
442.177 + AuthId.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
442.178 + } else {
442.179 + pAuthId = NULL;
442.180 + }
442.181 +
442.182 + ss = pAcquireCredentialsHandle(
442.183 + NULL, "NTLM", SECPKG_CRED_OUTBOUND,
442.184 + NULL, pAuthId, NULL, NULL,
442.185 + pCred, <ime
442.186 + );
442.187 +
442.188 + /* Release resources held by JNU_GetStringPlatformChars */
442.189 + if (pUser != NULL)
442.190 + JNU_ReleaseStringPlatformChars(env, user, pUser);
442.191 + if (pPassword != NULL)
442.192 + JNU_ReleaseStringPlatformChars(env, password, pPassword);
442.193 + if (pDomain != NULL)
442.194 + JNU_ReleaseStringPlatformChars(env, domain, pDomain);
442.195 +
442.196 + if (ss == 0) {
442.197 + return (jlong) pCred;
442.198 + } else {
442.199 + return 0;
442.200 + }
442.201 +}
442.202 +
442.203 +JNIEXPORT jbyteArray JNICALL Java_sun_net_www_protocol_http_ntlm_NTLMAuthSequence_getNextToken
442.204 +(JNIEnv *env, jobject this, jlong crdHandle, jbyteArray lastToken)
442.205 +{
442.206 +
442.207 + VOID *pInput = 0;
442.208 + DWORD inputLen;
442.209 + CHAR buffOut[512];
442.210 + jboolean isCopy;
442.211 + SECURITY_STATUS ss;
442.212 + SecBufferDesc OutBuffDesc;
442.213 + SecBuffer OutSecBuff;
442.214 + SecBufferDesc InBuffDesc;
442.215 + SecBuffer InSecBuff;
442.216 + ULONG ContextAttributes;
442.217 + CredHandle *pCred = (CredHandle *)crdHandle;
442.218 + CtxtHandle *pCtx;
442.219 + CtxtHandle *newContext;
442.220 + TimeStamp ltime;
442.221 + jbyteArray result;
442.222 +
442.223 +
442.224 + pCtx = (CtxtHandle *) (*env)->GetLongField (env, this, ntlm_ctxHandleID);
442.225 + if (pCtx == 0) { /* first call */
442.226 + newContext = (CtxtHandle *)malloc(sizeof(CtxtHandle));
442.227 + (*env)->SetLongField (env, this, ntlm_ctxHandleID, (jlong)newContext);
442.228 + } else {
442.229 + newContext = pCtx;
442.230 + }
442.231 +
442.232 + OutBuffDesc.ulVersion = 0;
442.233 + OutBuffDesc.cBuffers = 1;
442.234 + OutBuffDesc.pBuffers = &OutSecBuff;
442.235 +
442.236 + OutSecBuff.cbBuffer = 512;
442.237 + OutSecBuff.BufferType = SECBUFFER_TOKEN;
442.238 + OutSecBuff.pvBuffer = buffOut;
442.239 +
442.240 + /*
442.241 + * Prepare our Input buffer - Note the server is expecting the client's
442.242 + * negotiation packet on the first call
442.243 + */
442.244 +
442.245 + if (lastToken != 0)
442.246 + {
442.247 + pInput = (VOID *)(*env)->GetByteArrayElements(env, lastToken, &isCopy);
442.248 + inputLen = (*env)->GetArrayLength(env, lastToken);
442.249 +
442.250 + InBuffDesc.ulVersion = 0;
442.251 + InBuffDesc.cBuffers = 1;
442.252 + InBuffDesc.pBuffers = &InSecBuff;
442.253 +
442.254 + InSecBuff.cbBuffer = inputLen;
442.255 + InSecBuff.BufferType = SECBUFFER_TOKEN;
442.256 + InSecBuff.pvBuffer = pInput;
442.257 + }
442.258 +
442.259 + /*
442.260 + * will return success when its done but we still
442.261 + * need to send the out buffer if there are bytes to send
442.262 + */
442.263 +
442.264 + ss = pInitializeSecurityContext(
442.265 + pCred, pCtx, NULL, 0, 0, SECURITY_NATIVE_DREP,
442.266 + lastToken ? &InBuffDesc : NULL, 0, newContext, &OutBuffDesc,
442.267 + &ContextAttributes, <ime
442.268 + );
442.269 +
442.270 + if (pInput != 0) {
442.271 + (*env)->ReleaseByteArrayElements(env, lastToken, pInput, JNI_ABORT);
442.272 + }
442.273 +
442.274 + if (ss < 0) {
442.275 + endSequence (pCred, pCtx);
442.276 + return 0;
442.277 + }
442.278 +
442.279 + if ((ss == SEC_I_COMPLETE_NEEDED) || (ss == SEC_I_COMPLETE_AND_CONTINUE) ) {
442.280 + ss = pCompleteAuthToken( pCtx, &OutBuffDesc );
442.281 +
442.282 + if (ss < 0) {
442.283 + endSequence (pCred, pCtx);
442.284 + return 0;
442.285 + }
442.286 + }
442.287 +
442.288 + if ( OutSecBuff.cbBuffer > 0 ) {
442.289 + jbyteArray ret = (*env)->NewByteArray(env, OutSecBuff.cbBuffer);
442.290 + (*env)->SetByteArrayRegion(env, ret, 0, OutSecBuff.cbBuffer,
442.291 + OutSecBuff.pvBuffer);
442.292 + if (lastToken != 0) // 2nd stage
442.293 + endSequence (pCred, pCtx);
442.294 + result = ret;
442.295 + }
442.296 +
442.297 + if ((ss != SEC_I_CONTINUE_NEEDED) && (ss == SEC_I_COMPLETE_AND_CONTINUE)) {
442.298 + endSequence (pCred, pCtx);
442.299 + }
442.300 +
442.301 + return result;
442.302 +}
442.303 +
442.304 +static void endSequence (PCredHandle credHand, PCtxtHandle ctxHandle) {
442.305 + if (credHand != 0) {
442.306 + pFreeCredentialsHandle (credHand);
442.307 + free (credHand);
442.308 + }
442.309 +
442.310 + if (ctxHandle != 0) {
442.311 + pDeleteSecurityContext(ctxHandle);
442.312 + free (ctxHandle);
442.313 + }
442.314 +}
443.1 --- a/src/windows/native/sun/windows/awt_PrintControl.cpp Mon Nov 23 10:04:47 2009 +0000
443.2 +++ b/src/windows/native/sun/windows/awt_PrintControl.cpp Wed Nov 25 11:08:25 2009 -0800
443.3 @@ -687,7 +687,7 @@
443.4 // Now, set-up the struct for the real calls to ::PrintDlg and ::CreateDC
443.5
443.6 pd.hwndOwner = hwndOwner;
443.7 - pd.Flags = PD_ENABLEPRINTHOOK | PD_RETURNDC;
443.8 + pd.Flags = PD_ENABLEPRINTHOOK | PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE;
443.9 pd.lpfnPrintHook = (LPPRINTHOOKPROC)PrintDlgHook;
443.10
443.11 if (env->CallBooleanMethod(printCtrl, AwtPrintControl::getCollateID)) {
444.1 --- a/src/windows/native/sun/windows/awt_TrayIcon.cpp Mon Nov 23 10:04:47 2009 +0000
444.2 +++ b/src/windows/native/sun/windows/awt_TrayIcon.cpp Wed Nov 25 11:08:25 2009 -0800
444.3 @@ -59,7 +59,7 @@
444.4 };
444.5
444.6 typedef struct tagBitmapheader {
444.7 - BITMAPINFOHEADER bmiHeader;
444.8 + BITMAPV5HEADER bmiHeader;
444.9 DWORD dwMasks[256];
444.10 } Bitmapheader, *LPBITMAPHEADER;
444.11
444.12 @@ -638,12 +638,12 @@
444.13
444.14 HBITMAP AwtTrayIcon::CreateBMP(HWND hW,int* imageData,int nSS, int nW, int nH)
444.15 {
444.16 - Bitmapheader bmhHeader;
444.17 + Bitmapheader bmhHeader = {0};
444.18 HDC hDC;
444.19 char *ptrImageData;
444.20 HBITMAP hbmpBitmap;
444.21 HBITMAP hBitmap;
444.22 - int nNumChannels = 3;
444.23 + int nNumChannels = 4;
444.24
444.25 if (!hW) {
444.26 hW = ::GetDesktopWindow();
444.27 @@ -653,14 +653,20 @@
444.28 return NULL;
444.29 }
444.30
444.31 - memset(&bmhHeader, 0, sizeof(Bitmapheader));
444.32 - bmhHeader.bmiHeader.biSize = sizeof(BITMAPINFOHEADER);
444.33 - bmhHeader.bmiHeader.biWidth = nW;
444.34 - bmhHeader.bmiHeader.biHeight = -nH;
444.35 - bmhHeader.bmiHeader.biPlanes = 1;
444.36 + bmhHeader.bmiHeader.bV5Size = sizeof(BITMAPV5HEADER);
444.37 + bmhHeader.bmiHeader.bV5Width = nW;
444.38 + bmhHeader.bmiHeader.bV5Height = -nH;
444.39 + bmhHeader.bmiHeader.bV5Planes = 1;
444.40
444.41 - bmhHeader.bmiHeader.biBitCount = 24;
444.42 - bmhHeader.bmiHeader.biCompression = BI_RGB;
444.43 + bmhHeader.bmiHeader.bV5BitCount = 32;
444.44 + bmhHeader.bmiHeader.bV5Compression = BI_BITFIELDS;
444.45 +
444.46 + // The following mask specification specifies a supported 32 BPP
444.47 + // alpha format for Windows XP.
444.48 + bmhHeader.bmiHeader.bV5RedMask = 0x00FF0000;
444.49 + bmhHeader.bmiHeader.bV5GreenMask = 0x0000FF00;
444.50 + bmhHeader.bmiHeader.bV5BlueMask = 0x000000FF;
444.51 + bmhHeader.bmiHeader.bV5AlphaMask = 0xFF000000;
444.52
444.53 hbmpBitmap = ::CreateDIBSection(hDC, (BITMAPINFO*)&(bmhHeader),
444.54 DIB_RGB_COLORS,
444.55 @@ -674,6 +680,7 @@
444.56 }
444.57 for (int nOutern = 0; nOutern < nH; nOutern++) {
444.58 for (int nInner = 0; nInner < nSS; nInner++) {
444.59 + dstPtr[3] = (*srcPtr >> 0x18) & 0xFF;
444.60 dstPtr[2] = (*srcPtr >> 0x10) & 0xFF;
444.61 dstPtr[1] = (*srcPtr >> 0x08) & 0xFF;
444.62 dstPtr[0] = *srcPtr & 0xFF;
445.1 --- a/src/windows/native/sun/windows/awt_Window.cpp Mon Nov 23 10:04:47 2009 +0000
445.2 +++ b/src/windows/native/sun/windows/awt_Window.cpp Wed Nov 25 11:08:25 2009 -0800
445.3 @@ -143,6 +143,11 @@
445.4 jobject window;
445.5 };
445.6
445.7 +struct SetFullScreenExclusiveModeStateStruct {
445.8 + jobject window;
445.9 + jboolean isFSEMState;
445.10 +};
445.11 +
445.12
445.13 /************************************************************************
445.14 * AwtWindow fields
445.15 @@ -915,7 +920,9 @@
445.16
445.17 bool show = false;
445.18
445.19 - if (IsVisible() && currentWmSizeState != SIZE_MINIMIZED) {
445.20 + if (IsVisible() && currentWmSizeState != SIZE_MINIMIZED &&
445.21 + !isFullScreenExclusiveMode())
445.22 + {
445.23 if (AwtComponent::GetFocusedWindow() == GetHWnd()) {
445.24 show = true;
445.25 }
445.26 @@ -2954,6 +2961,25 @@
445.27 delete uws;
445.28 }
445.29
445.30 +void AwtWindow::_SetFullScreenExclusiveModeState(void *param)
445.31 +{
445.32 + JNIEnv *env = (JNIEnv *)JNU_GetEnv(jvm, JNI_VERSION_1_2);
445.33 +
445.34 + SetFullScreenExclusiveModeStateStruct * data =
445.35 + (SetFullScreenExclusiveModeStateStruct*)param;
445.36 + jobject self = data->window;
445.37 + jboolean state = data->isFSEMState;
445.38 +
445.39 + PDATA pData;
445.40 + JNI_CHECK_PEER_GOTO(self, ret);
445.41 + AwtWindow *window = (AwtWindow *)pData;
445.42 +
445.43 + window->setFullScreenExclusiveModeState(state != 0);
445.44 +
445.45 + ret:
445.46 + env->DeleteGlobalRef(self);
445.47 + delete data;
445.48 +}
445.49
445.50 extern "C" {
445.51
445.52 @@ -3335,6 +3361,29 @@
445.53
445.54 /*
445.55 * Class: sun_awt_windows_WWindowPeer
445.56 + * Method: setFullScreenExclusiveModeState
445.57 + * Signature: (Z)V
445.58 + */
445.59 +JNIEXPORT void JNICALL
445.60 +Java_sun_awt_windows_WWindowPeer_setFullScreenExclusiveModeState(JNIEnv *env,
445.61 + jobject self, jboolean state)
445.62 +{
445.63 + TRY;
445.64 +
445.65 + SetFullScreenExclusiveModeStateStruct *data =
445.66 + new SetFullScreenExclusiveModeStateStruct;
445.67 + data->window = env->NewGlobalRef(self);
445.68 + data->isFSEMState = state;
445.69 +
445.70 + AwtToolkit::GetInstance().SyncCall(
445.71 + AwtWindow::_SetFullScreenExclusiveModeState, data);
445.72 + // global ref and data are deleted in the invoked method
445.73 +
445.74 + CATCH_BAD_ALLOC;
445.75 +}
445.76 +
445.77 +/*
445.78 + * Class: sun_awt_windows_WWindowPeer
445.79 * Method: modalDisable
445.80 * Signature: (J)V
445.81 */
446.1 --- a/src/windows/native/sun/windows/awt_Window.h Mon Nov 23 10:04:47 2009 +0000
446.2 +++ b/src/windows/native/sun/windows/awt_Window.h Wed Nov 25 11:08:25 2009 -0800
446.3 @@ -229,6 +229,7 @@
446.4 static void _SetOpaque(void* param);
446.5 static void _UpdateWindow(void* param);
446.6 static void _RepositionSecurityWarning(void* param);
446.7 + static void _SetFullScreenExclusiveModeState(void* param);
446.8
446.9 inline static BOOL IsResizing() {
446.10 return sm_resizing;
446.11 @@ -331,6 +332,16 @@
446.12 static void SetLayered(HWND window, bool layered);
446.13 static bool IsLayered(HWND window);
446.14
446.15 + BOOL fullScreenExclusiveModeState;
446.16 + inline void setFullScreenExclusiveModeState(BOOL isEntered) {
446.17 + fullScreenExclusiveModeState = isEntered;
446.18 + UpdateSecurityWarningVisibility();
446.19 + }
446.20 + inline BOOL isFullScreenExclusiveMode() {
446.21 + return fullScreenExclusiveModeState;
446.22 + }
446.23 +
446.24 +
446.25 public:
446.26 void UpdateSecurityWarningVisibility();
446.27 static bool IsWarningWindow(HWND hWnd);
447.1 --- a/test/Makefile Mon Nov 23 10:04:47 2009 +0000
447.2 +++ b/test/Makefile Wed Nov 25 11:08:25 2009 -0800
447.3 @@ -1,5 +1,5 @@
447.4 #
447.5 -# Copyright 1995-2008 Sun Microsystems, Inc. All Rights Reserved.
447.6 +# Copyright 1995-2009 Sun Microsystems, Inc. All Rights Reserved.
447.7 # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
447.8 #
447.9 # This code is free software; you can redistribute it and/or modify it
447.10 @@ -27,83 +27,141 @@
447.11 # Makefile to run various jdk tests
447.12 #
447.13
447.14 -# Get OS/ARCH specifics
447.15 -OSNAME = $(shell uname -s)
447.16 +# Empty these to get rid of some default rules
447.17 +.SUFFIXES:
447.18 +.SUFFIXES: .java
447.19 +CO=
447.20 +GET=
447.21 +
447.22 +# Utilities used
447.23 +AWK = awk
447.24 +CAT = cat
447.25 +CD = cd
447.26 +CHMOD = chmod
447.27 +CP = cp
447.28 +CUT = cut
447.29 +ECHO = echo
447.30 +EGREP = egrep
447.31 +EXPAND = expand
447.32 +EXPR = expr
447.33 +KILL = /usr/bin/kill
447.34 +MKDIR = mkdir
447.35 +NOHUP = nohup
447.36 +PWD = pwd
447.37 +SED = sed
447.38 +SLEEP = sleep
447.39 +SORT = sort
447.40 +TEE = tee
447.41 +UNAME = uname
447.42 +UNIQ = uniq
447.43 +WC = wc
447.44 +XHOST = xhost
447.45 +ZIP = zip
447.46 +
447.47 +# Get OS name from uname
447.48 +UNAME_S := $(shell $(UNAME) -s)
447.49
447.50 # Commands to run on paths to make mixed paths for java on windows
447.51 -GETMIXEDPATH=echo
447.52 +GETMIXEDPATH=$(ECHO)
447.53
447.54 # Location of developer shared files
447.55 SLASH_JAVA = /java
447.56
447.57 # Platform specific settings
447.58 -ifeq ($(OSNAME), SunOS)
447.59 - PLATFORM = solaris
447.60 - ARCH = $(shell uname -p)
447.61 - ifeq ($(ARCH), i386)
447.62 - ARCH=i586
447.63 - endif
447.64 +ifeq ($(UNAME_S), SunOS)
447.65 + OS_NAME = solaris
447.66 + OS_ARCH := $(shell $(UNAME) -p)
447.67 + OS_VERSION := $(shell $(UNAME) -r)
447.68 endif
447.69 -ifeq ($(OSNAME), Linux)
447.70 - PLATFORM = linux
447.71 - ARCH = $(shell uname -m)
447.72 - ifeq ($(ARCH), i386)
447.73 - ARCH=i586
447.74 +ifeq ($(UNAME_S), Linux)
447.75 + OS_NAME = linux
447.76 + OS_ARCH := $(shell $(UNAME) -m)
447.77 + OS_VERSION := $(shell $(UNAME) -r)
447.78 +endif
447.79 +ifndef OS_NAME
447.80 + ifneq ($(PROCESSOR_IDENTIFIER), )
447.81 + OS_NAME = windows
447.82 + SLASH_JAVA = J:
447.83 + # A variety of ways to say X64 arch :^(
447.84 + OS_ARCH:=$(word 1, $(PROCESSOR_IDENTIFIER))
447.85 + EXESUFFIX = .exe
447.86 + # These need to be different depending on MKS or CYGWIN
447.87 + ifeq ($(findstring cygdrive,$(shell ($(CD) C:/ && $(PWD)))), )
447.88 + GETMIXEDPATH = dosname -s
447.89 + OS_VERSION := $(shell $(UNAME) -r)
447.90 + else
447.91 + GETMIXEDPATH = cygpath -m -s
447.92 + OS_VERSION := $(shell $(UNAME) -s | $(CUT) -d'-' -f2)
447.93 + endif
447.94 endif
447.95 endif
447.96
447.97 -# Cannot trust uname output
447.98 -ifneq ($(PROCESSOR_IDENTIFIER), )
447.99 - PLATFORM = windows
447.100 - SLASH_JAVA = J:
447.101 - # A variety of ways to say X64 arch :^(
447.102 - PROC_ARCH:=$(word 1, $(PROCESSOR_IDENTIFIER))
447.103 - PROC_ARCH:=$(subst x86,X86,$(PROC_ARCH))
447.104 - PROC_ARCH:=$(subst x64,X64,$(PROC_ARCH))
447.105 - PROC_ARCH:=$(subst AMD64,X64,$(PROC_ARCH))
447.106 - PROC_ARCH:=$(subst amd64,X64,$(PROC_ARCH))
447.107 - PROC_ARCH:=$(subst EM64T,X64,$(PROC_ARCH))
447.108 - PROC_ARCH:=$(subst em64t,X64,$(PROC_ARCH))
447.109 - PROC_ARCH:=$(subst intel64,X64,$(PROC_ARCH))
447.110 - PROC_ARCH:=$(subst Intel64,X64,$(PROC_ARCH))
447.111 - PROC_ARCH:=$(subst INTEL64,X64,$(PROC_ARCH))
447.112 - PROC_ARCH:=$(subst ia64,IA64,$(PROC_ARCH))
447.113 - ifeq ($(PROC_ARCH),IA64)
447.114 - ARCH = ia64
447.115 +# Only want major and minor numbers from os version
447.116 +OS_VERSION := $(shell $(ECHO) "$(OS_VERSION)" | $(CUT) -d'.' -f1,2)
447.117 +
447.118 +# Try and use names i586, x64, and ia64 consistently
447.119 +OS_ARCH:=$(subst X64,x64,$(OS_ARCH))
447.120 +OS_ARCH:=$(subst AMD64,x64,$(OS_ARCH))
447.121 +OS_ARCH:=$(subst amd64,x64,$(OS_ARCH))
447.122 +OS_ARCH:=$(subst x86_64,x64,$(OS_ARCH))
447.123 +OS_ARCH:=$(subst EM64T,x64,$(OS_ARCH))
447.124 +OS_ARCH:=$(subst em64t,x64,$(OS_ARCH))
447.125 +OS_ARCH:=$(subst intel64,x64,$(OS_ARCH))
447.126 +OS_ARCH:=$(subst Intel64,x64,$(OS_ARCH))
447.127 +OS_ARCH:=$(subst INTEL64,x64,$(OS_ARCH))
447.128 +OS_ARCH:=$(subst IA64,ia64,$(OS_ARCH))
447.129 +OS_ARCH:=$(subst X86,i586,$(OS_ARCH))
447.130 +OS_ARCH:=$(subst x86,i586,$(OS_ARCH))
447.131 +OS_ARCH:=$(subst i386,i586,$(OS_ARCH))
447.132 +OS_ARCH:=$(subst i486,i586,$(OS_ARCH))
447.133 +OS_ARCH:=$(subst i686,i586,$(OS_ARCH))
447.134 +
447.135 +# Check for ARCH_DATA_MODEL, adjust OS_ARCH accordingly
447.136 +ifndef ARCH_DATA_MODEL
447.137 + ARCH_DATA_MODEL=32
447.138 +endif
447.139 +ARCH_DATA_MODEL_ERROR= \
447.140 + ARCH_DATA_MODEL=$(ARCH_DATA_MODEL) cannot be used with $(OS_NAME)-$(ARCH)
447.141 +ifeq ($(ARCH_DATA_MODEL),64)
447.142 + ifeq ($(OS_NAME)-$(OS_ARCH),solaris-i586)
447.143 + OS_ARCH=x64
447.144 + endif
447.145 + ifeq ($(OS_NAME)-$(OS_ARCH),solaris-sparc)
447.146 + OS_ARCH=sparcv9
447.147 + endif
447.148 + ifeq ($(OS_ARCH),i586)
447.149 + x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)")
447.150 + endif
447.151 + ifeq ($(OS_ARCH),sparc)
447.152 + x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)")
447.153 + endif
447.154 +else
447.155 + ifeq ($(ARCH_DATA_MODEL),32)
447.156 + ifeq ($(OS_ARCH),x64)
447.157 + x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)")
447.158 + endif
447.159 + ifeq ($(OS_ARCH),ia64)
447.160 + x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)")
447.161 + endif
447.162 + ifeq ($(OS_ARCH),sparcv9)
447.163 + x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)")
447.164 + endif
447.165 else
447.166 - ifeq ($(PROC_ARCH),X64)
447.167 - ARCH = x64
447.168 - else
447.169 - ARCH = i586
447.170 - endif
447.171 - endif
447.172 - EXESUFFIX = .exe
447.173 - # These need to be different depending on MKS or CYGWIN
447.174 - ifeq ($(findstring cygdrive,$(shell (cd C:/ && pwd))), )
447.175 - GETMIXEDPATH=dosname -s
447.176 - else
447.177 - GETMIXEDPATH=cygpath -m -s
447.178 + x:=$(warning "WARNING: $(ARCH_DATA_MODEL_ERROR)")
447.179 endif
447.180 endif
447.181
447.182 -# Utilities used
447.183 -CD = cd
447.184 -CP = cp
447.185 -ECHO = echo
447.186 -MKDIR = mkdir
447.187 -ZIP = zip
447.188 -
447.189 # Root of this test area (important to use full paths in some places)
447.190 -TEST_ROOT := $(shell pwd)
447.191 +TEST_ROOT := $(shell $(PWD))
447.192
447.193 # Root of all test results
447.194 ifdef ALT_OUTPUTDIR
447.195 ABS_OUTPUTDIR = $(ALT_OUTPUTDIR)
447.196 else
447.197 - ABS_OUTPUTDIR = $(TEST_ROOT)/../build/$(PLATFORM)-$(ARCH)
447.198 + ABS_OUTPUTDIR = $(TEST_ROOT)/../build/$(OS_NAME)-$(OS_ARCH)
447.199 endif
447.200 ABS_BUILD_ROOT = $(ABS_OUTPUTDIR)
447.201 -ABS_TEST_OUTPUT_DIR := $(ABS_BUILD_ROOT)/testoutput
447.202 +ABS_TEST_OUTPUT_DIR := $(ABS_BUILD_ROOT)/testoutput/$(UNIQUE_DIR)
447.203
447.204 # Expect JPRT to set PRODUCT_HOME (the product or jdk in this case to test)
447.205 ifndef PRODUCT_HOME
447.206 @@ -114,13 +172,14 @@
447.207 if [ -d $(ABS_JDK_IMAGE) ] ; then \
447.208 $(ECHO) "$(ABS_JDK_IMAGE)"; \
447.209 else \
447.210 - $(ECHO) "$(ABS_BUILD_ROOT)" ; \
447.211 + $(ECHO) "$(ABS_BUILD_ROOT)"; \
447.212 fi)
447.213 PRODUCT_HOME := $(PRODUCT_HOME)
447.214 endif
447.215
447.216 # Expect JPRT to set JPRT_PRODUCT_ARGS (e.g. -server etc.)
447.217 # Should be passed into 'java' only.
447.218 +# Could include: -d64 -server -client OR any java option
447.219 ifdef JPRT_PRODUCT_ARGS
447.220 JAVA_ARGS = $(JPRT_PRODUCT_ARGS)
447.221 endif
447.222 @@ -131,18 +190,131 @@
447.223 JAVA_VM_ARGS = $(JPRT_PRODUCT_VM_ARGS)
447.224 endif
447.225
447.226 +# Check JAVA_ARGS arguments based on ARCH_DATA_MODEL etc.
447.227 +ifeq ($(OS_NAME),solaris)
447.228 + D64_ERROR_MESSAGE=Mismatch between ARCH_DATA_MODEL=$(ARCH_DATA_MODEL) and use of -d64 in JAVA_ARGS=$(JAVA_ARGS)
447.229 + ifeq ($(ARCH_DATA_MODEL),32)
447.230 + ifneq ($(findstring -d64,$(JAVA_ARGS)),)
447.231 + x:=$(warning "WARNING: $(D64_ERROR_MESSAGE)")
447.232 + endif
447.233 + endif
447.234 + ifeq ($(ARCH_DATA_MODEL),64)
447.235 + ifeq ($(findstring -d64,$(JAVA_ARGS)),)
447.236 + x:=$(warning "WARNING: $(D64_ERROR_MESSAGE)")
447.237 + endif
447.238 + endif
447.239 +endif
447.240 +
447.241 # Expect JPRT to set JPRT_ARCHIVE_BUNDLE (path to zip bundle for results)
447.242 ARCHIVE_BUNDLE = $(ABS_TEST_OUTPUT_DIR)/ARCHIVE_BUNDLE.zip
447.243 ifdef JPRT_ARCHIVE_BUNDLE
447.244 ARCHIVE_BUNDLE = $(JPRT_ARCHIVE_BUNDLE)
447.245 endif
447.246
447.247 +# DISPLAY settings for virtual frame buffer
447.248 +START_XVFB = start-Xvfb.sh
447.249 +NOHUP_OUTPUT = $(ABS_TEST_OUTPUT_DIR)/start-Xvfb.nohup-output.txt
447.250 +DISPLAY_PID_FILE=$(ABS_TEST_OUTPUT_DIR)/xvfb-display-number.txt
447.251 +DISPLAY_SLEEP_TIME=10
447.252 +DISPLAY_MAX_SLEEPS=10
447.253 +ifeq ($(OS_NAME),solaris)
447.254 + VIRTUAL_FRAME_BUFFER = true
447.255 +endif
447.256 +ifeq ($(OS_NAME),linux)
447.257 + VIRTUAL_FRAME_BUFFER = true
447.258 +endif
447.259 +
447.260 +# Does not work yet, display dies as soon as it gets used. :^(
447.261 +VIRTUAL_FRAME_BUFFER = false
447.262 +
447.263 +# Are we using a VIRTUAL_FRAME_BUFFER (Xvfb)
447.264 +ifeq ($(VIRTUAL_FRAME_BUFFER),true)
447.265 +
447.266 + PREP_DISPLAY = \
447.267 + $(CP) $(START_XVFB) $(ABS_TEST_OUTPUT_DIR); \
447.268 + $(CHMOD) a+x $(ABS_TEST_OUTPUT_DIR)/$(START_XVFB); \
447.269 + ( $(CD) $(ABS_TEST_OUTPUT_DIR) && \
447.270 + $(NOHUP) $(ABS_TEST_OUTPUT_DIR)/$(START_XVFB) $(DISPLAY_PID_FILE) > $(NOHUP_OUTPUT) 2>&1 && \
447.271 + $(SLEEP) $(DISPLAY_SLEEP_TIME) ) & \
447.272 + count=1; \
447.273 + while [ ! -s $(DISPLAY_PID_FILE) ] ; do \
447.274 + $(ECHO) "Sleeping $(DISPLAY_SLEEP_TIME) more seconds, DISPLAY not ready"; \
447.275 + $(SLEEP) $(DISPLAY_SLEEP_TIME); \
447.276 + count=`$(EXPR) $${count} '+' 1`; \
447.277 + if [ $${count} -gt $(DISPLAY_MAX_SLEEPS) ] ; then \
447.278 + $(ECHO) "ERROR: DISPLAY not ready, giving up on DISPLAY"; \
447.279 + exit 9; \
447.280 + fi; \
447.281 + done ; \
447.282 + DISPLAY=":`$(CAT) $(DISPLAY_PID_FILE)`"; \
447.283 + export DISPLAY; \
447.284 + $(CAT) $(NOHUP_OUTPUT); \
447.285 + $(ECHO) "Prepared DISPLAY=$${DISPLAY}"; \
447.286 + $(XHOST) || \
447.287 + ( $(ECHO) "ERROR: No display" ; exit 8)
447.288 +
447.289 + KILL_DISPLAY = \
447.290 + ( \
447.291 + DISPLAY=":`$(CAT) $(DISPLAY_PID_FILE)`"; \
447.292 + export DISPLAY; \
447.293 + if [ -s "$(DISPLAY_PID_FILE)" ] ; then \
447.294 + $(KILL) `$(CAT) $(DISPLAY_PID_FILE)` > /dev/null 2>&1; \
447.295 + $(KILL) -9 `$(CAT) $(DISPLAY_PID_FILE)` > /dev/null 2>&1; \
447.296 + fi; \
447.297 + $(ECHO) "Killed DISPLAY=$${DISPLAY}"; \
447.298 + )
447.299 +
447.300 +else
447.301 +
447.302 + PREP_DISPLAY = $(ECHO) "VIRTUAL_FRAME_BUFFER=$(VIRTUAL_FRAME_BUFFER)"
447.303 + KILL_DISPLAY = $(ECHO) "VIRTUAL_FRAME_BUFFER=$(VIRTUAL_FRAME_BUFFER)"
447.304 +
447.305 +endif
447.306 +
447.307 # How to create the test bundle (pass or fail, we want to create this)
447.308 # Follow command with ";$(BUNDLE_UP_AND_EXIT)", so it always gets executed.
447.309 ZIP_UP_RESULTS = ( $(MKDIR) -p `dirname $(ARCHIVE_BUNDLE)` \
447.310 && $(CD) $(ABS_TEST_OUTPUT_DIR) \
447.311 && $(ZIP) -q -r $(ARCHIVE_BUNDLE) . )
447.312 -BUNDLE_UP_AND_EXIT = ( exitCode=$$? && $(ZIP_UP_RESULTS) && exit $${exitCode} )
447.313 +SUMMARY_TXT = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTreport/text/summary.txt
447.314 +STATS_TXT_NAME = Stats.txt
447.315 +STATS_TXT = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/$(STATS_TXT_NAME)
447.316 +RUNLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/runlist.txt
447.317 +PASSLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/passlist.txt
447.318 +FAILLIST = $(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/faillist.txt
447.319 +BUNDLE_UP_AND_EXIT = \
447.320 +( \
447.321 + exitCode=$$? && \
447.322 + _summary="$(SUMMARY_TXT)"; \
447.323 + $(RM) -f $(STATS_TXT) $(RUNLIST) $(PASSLIST) $(FAILLIST); \
447.324 + if [ -r "$${_summary}" ] ; then \
447.325 + $(ECHO) "Summary: $${_summary}" > $(STATS_TXT); \
447.326 + $(EXPAND) $${_summary} | $(EGREP) -v ' Not run\.' > $(RUNLIST); \
447.327 + $(EGREP) ' Passed\.' $(RUNLIST) \
447.328 + | $(EGREP) -v ' Error\.' \
447.329 + | $(EGREP) -v ' Failed\.' > $(PASSLIST); \
447.330 + ( $(EGREP) ' Failed\.' $(RUNLIST); \
447.331 + $(EGREP) ' Error\.' $(RUNLIST); \
447.332 + $(EGREP) -v ' Passed\.' $(RUNLIST) ) \
447.333 + | $(SORT) | $(UNIQ) > $(FAILLIST); \
447.334 + if [ $${exitCode} != 0 -o -s $(FAILLIST) ] ; then \
447.335 + $(EXPAND) $(FAILLIST) \
447.336 + | $(CUT) -d' ' -f1 \
447.337 + | $(SED) -e 's@^@FAILED: @' >> $(STATS_TXT); \
447.338 + fi; \
447.339 + runc="`$(CAT) $(RUNLIST) | $(WC) -l | $(AWK) '{print $$1;}'`"; \
447.340 + passc="`$(CAT) $(PASSLIST) | $(WC) -l | $(AWK) '{print $$1;}'`"; \
447.341 + failc="`$(CAT) $(FAILLIST) | $(WC) -l | $(AWK) '{print $$1;}'`"; \
447.342 + exclc="`$(CAT) $(EXCLUDELIST) | $(WC) -l | $(AWK) '{print $$1;}'`"; \
447.343 + $(ECHO) "TEST STATS: run=$${runc} pass=$${passc} fail=$${failc} excluded=$${exclc}" \
447.344 + >> $(STATS_TXT); \
447.345 + else \
447.346 + $(ECHO) "Missing file: $${_summary}" >> $(STATS_TXT); \
447.347 + fi; \
447.348 + $(CAT) $(STATS_TXT); \
447.349 + $(ZIP_UP_RESULTS) && $(KILL_DISPLAY) && \
447.350 + exit $${exitCode} \
447.351 +)
447.352
447.353 ################################################################
447.354
447.355 @@ -172,32 +344,239 @@
447.356
447.357 # Expect JPRT to set TESTDIRS to the jtreg test dirs
447.358 ifndef TESTDIRS
447.359 - TESTDIRS = demo/jvmti/gctest demo/jvmti/hprof
447.360 + TESTDIRS = demo
447.361 endif
447.362
447.363 +# Samevm settings (default is false)
447.364 +ifndef USE_JTREG_SAMEVM
447.365 + USE_JTREG_SAMEVM=false
447.366 +endif
447.367 +# With samevm, you cannot use -javaoptions?
447.368 +ifeq ($(USE_JTREG_SAMEVM),true)
447.369 + EXTRA_JTREG_OPTIONS += -samevm $(JAVA_ARGS) $(JAVA_ARGS:%=-vmoption:%)
447.370 + JTREG_TEST_OPTIONS = $(JAVA_VM_ARGS:%=-vmoption:%)
447.371 +else
447.372 + JTREG_TEST_OPTIONS = $(JAVA_ARGS:%=-javaoptions:%) $(JAVA_VM_ARGS:%=-vmoption:%)
447.373 +endif
447.374 +
447.375 +# Some tests annoy me and fail frequently
447.376 +PROBLEM_LIST=ProblemList.txt
447.377 +EXCLUDELIST=$(ABS_TEST_OUTPUT_DIR)/excludelist.txt
447.378 +
447.379 +# Create exclude list for this platform and arch
447.380 +ifdef NO_EXCLUDES
447.381 +$(EXCLUDELIST): $(PROBLEM_LIST) $(TESTDIRS)
447.382 + @$(ECHO) "NOTHING_EXCLUDED" > $@
447.383 +else
447.384 +$(EXCLUDELIST): $(PROBLEM_LIST) $(TESTDIRS)
447.385 + @$(RM) $@ $@.temp1 $@.temp2
447.386 + @( ( $(EGREP) -- '$(OS_NAME)-all' $< ) ;\
447.387 + ( $(EGREP) -- '$(OS_NAME)-$(OS_ARCH)' $< ) ;\
447.388 + ( $(EGREP) -- '$(OS_NAME)-$(OS_VERSION)' $< ) ;\
447.389 + ( $(EGREP) -- 'generic-$(OS_ARCH)' $< ) ;\
447.390 + ( $(EGREP) -- 'generic-all' $< ) ;\
447.391 + ( $(ECHO) "#") ;\
447.392 + ) | $(SED) -e 's@^[\ ]*@@' \
447.393 + | $(EGREP) -v '^#' > $@.temp1
447.394 + @for tdir in $(TESTDIRS) ; do \
447.395 + ( ( $(CAT) $@.temp1 | $(EGREP) "^$${tdir}" ) ; $(ECHO) "#" ) >> $@.temp2 ; \
447.396 + done
447.397 + @$(ECHO) "# at least one line" >> $@.temp2
447.398 + @( $(EGREP) -v '^#' $@.temp2 ; true ) > $@
447.399 + @$(ECHO) "Excluding list contains `$(EXPAND) $@ | $(WC) -l` items"
447.400 +endif
447.401 +
447.402 +# Running batches of tests with or without samevm
447.403 +define RunSamevmBatch
447.404 +$(ECHO) "Running tests in samevm mode: $?"
447.405 +$(MAKE) TESTDIRS="$?" USE_JTREG_SAMEVM=true UNIQUE_DIR=$@ jtreg_tests
447.406 +endef
447.407 +define RunOthervmBatch
447.408 +$(ECHO) "Running tests in othervm mode: $?"
447.409 +$(MAKE) TESTDIRS="$?" USE_JTREG_SAMEVM=false UNIQUE_DIR=$@ jtreg_tests
447.410 +endef
447.411 +define SummaryInfo
447.412 +$(ECHO) "Summary for: $?"
447.413 +$(CAT) $(?:%=$(ABS_TEST_OUTPUT_DIR)/%/$(STATS_TXT_NAME))
447.414 +endef
447.415 +
447.416 +# ------------------------------------------------------------------
447.417 +
447.418 +# Batches of tests (somewhat arbitrary assigments to jdk_* targets)
447.419 +JDK_ALL_TARGETS =
447.420 +
447.421 +# Stable othervm testruns (minus items from PROBLEM_LIST)
447.422 +# Using samevm has problems, and doesn't help performance as much as others.
447.423 +JDK_ALL_TARGETS += jdk_awt
447.424 +jdk_awt: com/sun/awt java/awt sun/awt
447.425 + $(call RunOthervmBatch)
447.426 +
447.427 +# Stable samevm testruns (minus items from PROBLEM_LIST)
447.428 +JDK_ALL_TARGETS += jdk_beans1
447.429 +jdk_beans1: java/beans/beancontext java/beans/PropertyChangeSupport \
447.430 + java/beans/Introspector java/beans/Performance \
447.431 + java/beans/VetoableChangeSupport java/beans/Statement
447.432 + $(call RunSamevmBatch)
447.433 +
447.434 +# Stable othervm testruns (minus items from PROBLEM_LIST)
447.435 +# Using samevm has serious problems with these tests
447.436 +JDK_ALL_TARGETS += jdk_beans2
447.437 +jdk_beans2: java/beans/Beans java/beans/EventHandler java/beans/XMLDecoder \
447.438 + java/beans/PropertyEditor
447.439 + $(call RunOthervmBatch)
447.440 +JDK_ALL_TARGETS += jdk_beans3
447.441 +jdk_beans3: java/beans/XMLEncoder
447.442 + $(call RunOthervmBatch)
447.443 +
447.444 +# Stable samevm testruns (minus items from PROBLEM_LIST)
447.445 +JDK_ALL_TARGETS += jdk_io
447.446 +jdk_io: java/io
447.447 + $(call RunSamevmBatch)
447.448 +
447.449 +# Stable samevm testruns (minus items from PROBLEM_LIST)
447.450 +JDK_ALL_TARGETS += jdk_lang
447.451 +jdk_lang: java/lang
447.452 + $(call RunSamevmBatch)
447.453 +
447.454 +# Stable othervm testruns (minus items from PROBLEM_LIST)
447.455 +# Using samevm has serious problems with these tests
447.456 +JDK_ALL_TARGETS += jdk_management1
447.457 +jdk_management1: javax/management
447.458 + $(call RunOthervmBatch)
447.459 +
447.460 +# Stable othervm testruns (minus items from PROBLEM_LIST)
447.461 +# Using samevm has serious problems with these tests
447.462 +JDK_ALL_TARGETS += jdk_management2
447.463 +jdk_management2: com/sun/jmx com/sun/management sun/management
447.464 + $(call RunOthervmBatch)
447.465 +
447.466 +# Stable samevm testruns (minus items from PROBLEM_LIST)
447.467 +JDK_ALL_TARGETS += jdk_math
447.468 +jdk_math: java/math
447.469 + $(call RunSamevmBatch)
447.470 +
447.471 +# Stable samevm testruns (minus items from PROBLEM_LIST)
447.472 +JDK_ALL_TARGETS += jdk_misc
447.473 +jdk_misc: demo javax/imageio javax/naming javax/print javax/script \
447.474 + javax/smartcardio javax/sound com/sun/java com/sun/jndi \
447.475 + com/sun/org sun/misc sun/pisces
447.476 + $(call RunSamevmBatch)
447.477 +
447.478 +# Stable samevm testruns (minus items from PROBLEM_LIST)
447.479 +JDK_ALL_TARGETS += jdk_net
447.480 +jdk_net: com/sun/net java/net sun/net
447.481 + $(call RunSamevmBatch)
447.482 +
447.483 +# Stable samevm testruns (minus items from PROBLEM_LIST)
447.484 +JDK_ALL_TARGETS += jdk_nio1
447.485 +jdk_nio1: java/nio/file
447.486 + $(call RunSamevmBatch)
447.487 +
447.488 +# Stable othervm testruns (minus items from PROBLEM_LIST)
447.489 +# Using samevm has serious problems with these tests
447.490 +JDK_ALL_TARGETS += jdk_nio2
447.491 +jdk_nio2: java/nio/Buffer java/nio/ByteOrder \
447.492 + java/nio/channels java/nio/BufferPoolMXBean java/nio/MappedByteBuffer
447.493 + $(call RunOthervmBatch)
447.494 +JDK_ALL_TARGETS += jdk_nio3
447.495 +jdk_nio3: com/sun/nio sun/nio
447.496 + $(call RunOthervmBatch)
447.497 +
447.498 +# Stable othervm testruns (minus items from PROBLEM_LIST)
447.499 +# Using samevm has serious problems with these tests
447.500 +JDK_ALL_TARGETS += jdk_rmi
447.501 +jdk_rmi: java/rmi javax/rmi sun/rmi
447.502 + $(call RunOthervmBatch)
447.503 +
447.504 +# Stable samevm testruns (minus items from PROBLEM_LIST)
447.505 +JDK_ALL_TARGETS += jdk_security1
447.506 +jdk_security1: java/security
447.507 + $(call RunSamevmBatch)
447.508 +
447.509 +# Stable othervm testruns (minus items from PROBLEM_LIST)
447.510 +# Using samevm has serious problems with these tests
447.511 +JDK_ALL_TARGETS += jdk_security2
447.512 +jdk_security2: javax/crypto com/sun/crypto
447.513 + $(call RunOthervmBatch)
447.514 +JDK_ALL_TARGETS += jdk_security3
447.515 +jdk_security3: com/sun/security lib/security javax/security sun/security
447.516 + $(call RunOthervmBatch)
447.517 +
447.518 +# Stable othervm testruns (minus items from PROBLEM_LIST)
447.519 +# Using samevm has problems, and doesn't help performance as much as others.
447.520 +JDK_ALL_TARGETS += jdk_swing
447.521 +jdk_swing: javax/swing sun/java2d
447.522 + $(call RunOthervmBatch)
447.523 +
447.524 +# Stable samevm testruns (minus items from PROBLEM_LIST)
447.525 +JDK_ALL_TARGETS += jdk_text
447.526 +jdk_text: java/text sun/text
447.527 + $(call RunSamevmBatch)
447.528 +
447.529 +# Stable othervm testruns (minus items from PROBLEM_LIST)
447.530 +# Using samevm has serious problems with these tests
447.531 +JDK_ALL_TARGETS += jdk_tools1
447.532 +jdk_tools1: com/sun/jdi
447.533 + $(call RunOthervmBatch)
447.534 +JDK_ALL_TARGETS += jdk_tools2
447.535 +jdk_tools2: com/sun/tools sun/jvmstat sun/tools tools vm com/sun/servicetag com/sun/tracing
447.536 + $(call RunOthervmBatch)
447.537 +
447.538 +# Stable samevm testruns (minus items from PROBLEM_LIST)
447.539 +JDK_ALL_TARGETS += jdk_util
447.540 +jdk_util: java/util sun/util
447.541 + $(call RunSamevmBatch)
447.542 +
447.543 +# ------------------------------------------------------------------
447.544 +
447.545 +# Run all tests
447.546 +jdk_all: $(filter-out jdk_awt jdk_rmi jdk_swing, $(JDK_ALL_TARGETS))
447.547 + @$(SummaryInfo)
447.548 +
447.549 +# These are all phony targets
447.550 +PHONY_LIST += $(JDK_ALL_TARGETS)
447.551 +
447.552 +# ------------------------------------------------------------------
447.553 +
447.554 # Default JTREG to run (win32 script works for everybody)
447.555 JTREG = $(JT_HOME)/win32/bin/jtreg
447.556 +# Add any extra options (samevm etc.)
447.557 +JTREG_BASIC_OPTIONS += $(EXTRA_JTREG_OPTIONS)
447.558 +# Only run automatic tests
447.559 +JTREG_BASIC_OPTIONS += -a
447.560 +# Report details on all failed or error tests, times too
447.561 +JTREG_BASIC_OPTIONS += -v:fail,error,time
447.562 +# Retain all files for failing tests
447.563 +JTREG_BASIC_OPTIONS += -retain:fail,error
447.564 +# Ignore tests are not run and completely silent about it
447.565 +JTREG_BASIC_OPTIONS += -ignore:quiet
447.566 +# Multiple by 2 the timeout numbers
447.567 +JTREG_BASIC_OPTIONS += -timeoutFactor:2
447.568 +# Boost the max memory for jtreg to avoid gc thrashing
447.569 +JTREG_BASIC_OPTIONS += -J-Xmx512m
447.570
447.571 -jtreg_tests: prep $(JT_HOME) $(PRODUCT_HOME) $(JTREG)
447.572 - $(RM) $(JTREG).orig
447.573 - cp $(JTREG) $(JTREG).orig
447.574 - $(RM) $(JTREG)
447.575 - sed -e 's@-J\*@-J-*@' $(JTREG).orig > $(JTREG)
447.576 - chmod a+x $(JTREG)
447.577 - ( JT_HOME=$(shell $(GETMIXEDPATH) "$(JT_HOME)"); \
447.578 - export JT_HOME; \
447.579 - $(shell $(GETMIXEDPATH) "$(JTREG)") \
447.580 - -a -v:fail,error \
447.581 - -ignore:quiet \
447.582 - -timeoutFactor:2 \
447.583 - $(EXTRA_JTREG_OPTIONS) \
447.584 - -r:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTreport \
447.585 - -w:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTwork \
447.586 - -jdk:$(shell $(GETMIXEDPATH) "$(PRODUCT_HOME)") \
447.587 - $(JAVA_ARGS:%=-javaoptions:%) \
447.588 - $(JAVA_VM_ARGS:%=-vmoption:%) \
447.589 - $(TESTDIRS) \
447.590 - ) ; $(BUNDLE_UP_AND_EXIT)
447.591 +# Make sure jtreg exists
447.592 +$(JTREG): $(JT_HOME)
447.593 +
447.594 +# Run jtreg
447.595 +jtreg_tests: prep $(PRODUCT_HOME) $(JTREG) $(EXCLUDELIST)
447.596 + @$(EXPAND) $(EXCLUDELIST) \
447.597 + | $(CUT) -d' ' -f1 \
447.598 + | $(SED) -e 's@^@Excluding: @'
447.599 + ( \
447.600 + ( JT_HOME=$(shell $(GETMIXEDPATH) "$(JT_HOME)"); \
447.601 + export JT_HOME; \
447.602 + $(PREP_DISPLAY) && \
447.603 + $(shell $(GETMIXEDPATH) "$(JTREG)") \
447.604 + $(JTREG_BASIC_OPTIONS) \
447.605 + -r:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTreport \
447.606 + -w:$(shell $(GETMIXEDPATH) "$(ABS_TEST_OUTPUT_DIR)")/JTwork \
447.607 + -jdk:$(shell $(GETMIXEDPATH) "$(PRODUCT_HOME)") \
447.608 + -exclude:$(shell $(GETMIXEDPATH) "$(EXCLUDELIST)") \
447.609 + $(JTREG_TEST_OPTIONS) \
447.610 + $(TESTDIRS) \
447.611 + ) ; $(BUNDLE_UP_AND_EXIT) \
447.612 + ) 2>&1 | $(TEE) $(ABS_TEST_OUTPUT_DIR)/output.txt
447.613
447.614 PHONY_LIST += jtreg_tests
447.615
448.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
448.2 +++ b/test/ProblemList.txt Wed Nov 25 11:08:25 2009 -0800
448.3 @@ -0,0 +1,1211 @@
448.4 +###########################################################################
448.5 +#
448.6 +# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
448.7 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
448.8 +#
448.9 +# This code is free software; you can redistribute it and/or modify it
448.10 +# under the terms of the GNU General Public License version 2 only, as
448.11 +# published by the Free Software Foundation. Sun designates this
448.12 +# particular file as subject to the "Classpath" exception as provided
448.13 +# by Sun in the LICENSE file that accompanied this code.
448.14 +#
448.15 +# This code is distributed in the hope that it will be useful, but WITHOUT
448.16 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
448.17 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
448.18 +# version 2 for more details (a copy is included in the LICENSE file that
448.19 +# accompanied this code).
448.20 +#
448.21 +# You should have received a copy of the GNU General Public License version
448.22 +# 2 along with this work; if not, write to the Free Software Foundation,
448.23 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
448.24 +#
448.25 +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
448.26 +# CA 95054 USA or visit www.sun.com if you need additional information or
448.27 +# have any questions.
448.28 +#
448.29 +###########################################################################
448.30 +#
448.31 +# List of tests that should not be run by test/Makefile, for various reasons:
448.32 +# 1. Does not run with jtreg -samevm mode
448.33 +# 2. Causes problems in jtreg -samevm mode for jtreg or tests that follow it
448.34 +# 3. The test is too slow or consumes too many system resources
448.35 +# 4. The test fails when run on any official build systems
448.36 +#
448.37 +# It is possible that a test being on this list is a mistake, and that some
448.38 +# other test in samevm mode caused tests to fail, mistakes happen.
448.39 +#
448.40 +# Tests marked @ignore are not run by test/Makefile, but harmless to be listed.
448.41 +#
448.42 +# Tests that explicitly state "@run main/othervm ...", and are not listed here,
448.43 +# will be run in the same batch as the samevm tests.
448.44 +#
448.45 +# Shell tests are othervm by default.
448.46 +#
448.47 +# List items are testnames followed by labels, all MUST BE commented
448.48 +# as to why they are here and use a label:
448.49 +# generic-all Problems on all platforms
448.50 +# generic-ARCH Where ARCH is one of: sparc, sparcv9, x64, i586, etc.
448.51 +# OSNAME-all Where OSNAME is one of: solaris, linux, windows
448.52 +# OSNAME-ARCH Specific on to one OSNAME and ARCH, e.g. solaris-x64
448.53 +# OSNAME-REV Specific on to one OSNAME and REV, e.g. solaris-5.8
448.54 +#
448.55 +# More than one label is allowed but must be on the same line.
448.56 +#
448.57 +#############################################################################
448.58 +#
448.59 +# Running the tests:
448.60 +# cd test && make JT_HOME=jtreg_home PRODUCT_HOME=jdk_home jdk_all
448.61 +# Or instead of jdk_all, use any of the jdk_* targets.
448.62 +#
448.63 +# Samevm Notes:
448.64 +# * Although some tests may have only been seen to fail on some platforms,
448.65 +# they might be flagged as 'generic-all' because the problem they have
448.66 +# could cause hidden slowdowns on other platforms.
448.67 +# Most samevm problems will be generic-all, but windows usually dislikes
448.68 +# them the most.
448.69 +# Address already in use or connection errors indicate a generic port issue.
448.70 +# (this is not necessarily a samevm issue, but an issue for running the tests
448.71 +# on shared machines, two people or two test runs will collide).
448.72 +# * Samevm problem (windows in particular) is not closing all input/output
448.73 +# * Samevm problem when a test calls setSecurityManager()
448.74 +# * Samevm problem with setHttps*() is used? (not exactly sure here)
448.75 +# * Samevm problem when stuffing system properties with non Strings or anything
448.76 +# * Samevm problem when changing vm settings, or registering any vm actions
448.77 +# * Samevm problems with deleteOnExit(), if it must happen at end of test
448.78 +# * Samevm problems with URLClassLoader? (no details here)
448.79 +# * Samevm problems with dependence on predictable GC or finalizations
448.80 +#
448.81 +# Any of the above problems may mean the test needs to be flagged as "othervm".
448.82 +#
448.83 +#############################################################################
448.84 +#
448.85 +# Fixing the tests:
448.86 +#
448.87 +# Some tests just may need to be run with "othervm", and that can easily be
448.88 +# done my adding a @run line (or modifying any existing @run):
448.89 +# @run main/othervm NameOfMainClass
448.90 +# Make sure this @run follows any use of @library.
448.91 +# Otherwise, if the test is a samevm possibility, make sure the test is
448.92 +# cleaning up after itself, closing all streams, deleting temp files, etc.
448.93 +#
448.94 +# Keep in mind that the bug could be in many places, and even different per
448.95 +# platform, it could be a bug in any one of:
448.96 +# - the testcase
448.97 +# - the jdk (jdk classes, native code, or hotspot)
448.98 +# - the native compiler
448.99 +# - the javac compiler
448.100 +# - the OS (depends on what the testcase does)
448.101 +#
448.102 +# If you managed to really fix one of these tests, here is how you can
448.103 +# remove tests from this list:
448.104 +# 1. Make sure test passes on all platforms with samevm, or mark it othervm
448.105 +# 2. Make sure test passes on all platforms when run with it's entire group
448.106 +# 3. Make sure both VMs are tested, -server and -client, if possible
448.107 +# 4. Make sure you try the -d64 option on Solaris
448.108 +# 5. Use a tool like JPRT or something to verify these results
448.109 +# 6. Delete lines in this file, include the changes with your test changes
448.110 +#
448.111 +# You may need to repeat your testing 2 or even 3 times to verify good
448.112 +# results, some of these samevm failures are not very predictable.
448.113 +#
448.114 +#############################################################################
448.115 +
448.116 +############################################################################
448.117 +
448.118 +# jdk_awt
448.119 +
448.120 +# None of the awt tests are using samevm, might not be worth the effort due
448.121 +# to the vm overhead not being enough to make a difference.
448.122 +# In general, the awt tests are problematic with or without samevm, and there
448.123 +# are issues with using a Xvfb display.
448.124 +
448.125 +# Fails on solaris sparc, timedout? in othervm mode
448.126 +java/awt/event/MouseEvent/AcceptExtraButton/AcceptExtraButton.java generic-all
448.127 +
448.128 +# Causes hang in samevm mode??? Solaris 11 i586
448.129 +java/awt/FullScreen/SetFSWindow/FSFrame.java generic-all
448.130 +
448.131 +# Fails on solaris 11 i586, -client, in othervm mode not sure why
448.132 +java/awt/Component/PrintAllXcheckJNI/PrintAllXcheckJNI.java generic-all
448.133 +java/awt/Focus/CloseDialogActivateOwnerTest/CloseDialogActivateOwnerTest.java generic-all
448.134 +java/awt/FontClass/FontAccess.java generic-all
448.135 +java/awt/Mixing/HWDisappear.java generic-all
448.136 +java/awt/Mixing/MixingInHwPanel.java generic-all
448.137 +java/awt/Mouse/MaximizedFrameTest/MaximizedFrameTest.html generic-all
448.138 +java/awt/Robot/AcceptExtraMouseButtons/AcceptExtraMouseButtons.java generic-all
448.139 +java/awt/Toolkit/SecurityTest/SecurityTest2.java generic-all
448.140 +java/awt/image/mlib/MlibOpsTest.java generic-all
448.141 +
448.142 +# Fails on windows, othervm mode, various errors
448.143 +java/awt/Focus/NonFocusableWindowTest/NonfocusableOwnerTest.java generic-all
448.144 +java/awt/Focus/OwnedWindowFocusIMECrashTest/OwnedWindowFocusIMECrashTest.java generic-all
448.145 +java/awt/FullScreen/NoResizeEventOnDMChangeTest/NoResizeEventOnDMChangeTest.java generic-all
448.146 +java/awt/Mouse/MouseModifiersUnitTest/MouseModifiersUnitTest_Standard.java generic-all
448.147 +java/awt/event/KeyEvent/KeyTyped/CtrlASCII.html generic-all
448.148 +java/awt/font/Threads/FontThread.java generic-all
448.149 +java/awt/print/PrinterJob/PrtException.java generic-all
448.150 +
448.151 +# Fails with windows X64, othervm, -server
448.152 +com/sun/awt/Translucency/WindowOpacity.java generic-all
448.153 +java/awt/EventDispatchThread/HandleExceptionOnEDT/HandleExceptionOnEDT.java generic-all
448.154 +java/awt/EventDispatchThread/LoopRobustness/LoopRobustness.html generic-all
448.155 +java/awt/Focus/AppletInitialFocusTest/AppletInitialFocusTest1.html generic-all
448.156 +java/awt/Focus/FocusEmbeddedFrameTest/FocusEmbeddedFrameTest.java generic-all
448.157 +java/awt/Frame/LayoutOnMaximizeTest/LayoutOnMaximizeTest.java generic-all
448.158 +java/awt/FullScreen/TranslucentWindow/TranslucentWindow.java generic-all
448.159 +java/awt/Mixing/MixingOnShrinkingHWButton.java generic-all
448.160 +java/awt/Mouse/MouseModifiersUnitTest/ExtraButtonDrag.java generic-all
448.161 +
448.162 +############################################################################
448.163 +
448.164 +# jdk_beans
448.165 +
448.166 +# A large set of the beans tests set the security manager, which would seem
448.167 +# to indicate that a large number of them should be "othervm", yet are all
448.168 +# very small tests and could greatly benefit from a samevm test run.
448.169 +# So a large batch of beans tests are currently run with othervm mode.
448.170 +
448.171 +# Linux, some kind of problems with X11 display
448.172 +java/beans/PropertyChangeSupport/Test4682386.java generic-all
448.173 +java/beans/PropertyChangeSupport/TestSynchronization.java generic-all
448.174 +java/beans/Statement/Test4653179.java generic-all
448.175 +
448.176 +# Runs REALLY slow on Solaris sparc for some reason, both -client and -server
448.177 +java/beans/XMLEncoder/Test4625418.java solaris-sparc
448.178 +
448.179 +# Problems with samevm and setting security manager (speculation partially)
448.180 +java/beans/Beans/Test4080522.java generic-all
448.181 +java/beans/EventHandler/Test6277246.java generic-all
448.182 +java/beans/EventHandler/Test6277266.java generic-all
448.183 +java/beans/Introspector/Test6277246.java generic-all
448.184 +java/beans/Introspector/4168475/Test4168475.java generic-all
448.185 +java/beans/Introspector/4520754/Test4520754.java generic-all
448.186 +java/beans/Introspector/6380849/TestBeanInfo.java generic-all
448.187 +java/beans/Introspector/Test4144543.java generic-all
448.188 +
448.189 +# Failed to call method solaris-sparc???
448.190 +java/beans/EventHandler/Test6788531.java generic-all
448.191 +
448.192 +# Jar or class not found???
448.193 +java/beans/XMLEncoder/6329581/Test6329581.java generic-all
448.194 +
448.195 +############################################################################
448.196 +
448.197 +# jdk_io
448.198 +
448.199 +# Many of these tests have a tendency to leave input streams open, which
448.200 +# will cause following tests to be failures when used in samevm mode.
448.201 +
448.202 +# Should be othervm, or corrected for samevm, fails with samevm:
448.203 +java/io/BufferedReader/BigMark.java generic-all
448.204 +java/io/BufferedReader/ReadLineSync.java generic-all
448.205 +
448.206 +# One of these is leaving "a.ser" file open, windows samevm
448.207 +java/io/Serializable/duplicateSerialFields/Setup.java generic-all
448.208 +java/io/Serializable/duplicateSerialFields/Test.java generic-all
448.209 +
448.210 +# One of these leaving foo.ser open, windows samevm problem
448.211 +java/io/Serializable/enum/constantSubclasses/Read.java generic-all
448.212 +java/io/Serializable/enum/constantSubclasses/Write.java generic-all
448.213 +java/io/Serializable/enum/missingConstant/Read.java generic-all
448.214 +java/io/Serializable/enum/missingConstant/Write.java generic-all
448.215 +
448.216 +# This is leaving subtest1.tmp open, windows samevm problem
448.217 +java/io/Serializable/oldTests/AnnotateClass.java generic-all
448.218 +
448.219 +# One or more of these leave a piotest* file open, windows samevm
448.220 +java/io/Serializable/oldTests/ArrayFields.java generic-all
448.221 +java/io/Serializable/oldTests/ArraysOfArrays.java generic-all
448.222 +java/io/Serializable/oldTests/BinaryTree.java generic-all
448.223 +java/io/Serializable/oldTests/CircularList.java generic-all
448.224 +java/io/Serializable/oldTests/SerializeWithException.java generic-all
448.225 +java/io/Serializable/oldTests/SimpleArrays.java generic-all
448.226 +java/io/Serializable/oldTests/WritePrimitive.java generic-all
448.227 +
448.228 +# Missing close on file 0.ser, windows samevm
448.229 +java/io/Serializable/enum/badResolve/Read.java generic-all
448.230 +java/io/Serializable/enum/badResolve/Write.java generic-all
448.231 +
448.232 +# One of these tests is leaving parents.ser open, windows samevm
448.233 +java/io/Serializable/parents/EvolvedClass.java generic-all
448.234 +java/io/Serializable/parents/OriginalClass.java generic-all
448.235 +
448.236 +# One of these tests is leaving file foo.ser and/or bar.ser open, windows samevm
448.237 +java/io/Serializable/fieldTypeString/Read.java generic-all
448.238 +java/io/Serializable/fieldTypeString/Write.java generic-all
448.239 +
448.240 +# One of these tests is leaving tmp.ser file open, windows samevm
448.241 +java/io/Serializable/ClassCastExceptionDetail/Read.java generic-all
448.242 +java/io/Serializable/ClassCastExceptionDetail/Write.java generic-all
448.243 +java/io/Serializable/GetField/Read.java generic-all
448.244 +java/io/Serializable/GetField/Read2.java generic-all
448.245 +java/io/Serializable/GetField/Write.java generic-all
448.246 +java/io/Serializable/PutField/Read.java generic-all
448.247 +java/io/Serializable/PutField/Read2.java generic-all
448.248 +java/io/Serializable/PutField/Write.java generic-all
448.249 +java/io/Serializable/PutField/Write2.java generic-all
448.250 +java/io/Serializable/arraySuidConflict/Read.java generic-all
448.251 +java/io/Serializable/arraySuidConflict/Write.java generic-all
448.252 +java/io/Serializable/backRefCNFException/Read.java generic-all
448.253 +java/io/Serializable/backRefCNFException/Write.java generic-all
448.254 +java/io/Serializable/class/Test.java generic-all
448.255 +java/io/Serializable/evolution/AddedExternField/ReadAddedField.java generic-all
448.256 +java/io/Serializable/evolution/AddedExternField/WriteAddedField.java generic-all
448.257 +java/io/Serializable/evolution/AddedExternField/run.sh generic-all
448.258 +java/io/Serializable/evolution/AddedField/ReadAddedField.java generic-all
448.259 +java/io/Serializable/evolution/AddedField/WriteAddedField.java generic-all
448.260 +java/io/Serializable/evolution/AddedSuperClass/ReadAddedSuperClass.java generic-all
448.261 +java/io/Serializable/evolution/AddedSuperClass/ReadAddedSuperClass2.java generic-all
448.262 +java/io/Serializable/evolution/AddedSuperClass/WriteAddedSuperClass.java generic-all
448.263 +java/io/Serializable/proxy/skipMissing/Read.java generic-all
448.264 +java/io/Serializable/proxy/skipMissing/Write.java generic-all
448.265 +java/io/Serializable/readObjectNoData/Read.java generic-all
448.266 +java/io/Serializable/readObjectNoData/Write.java generic-all
448.267 +java/io/Serializable/skipWriteObject/Read.java generic-all
448.268 +java/io/Serializable/skipWriteObject/Write.java generic-all
448.269 +java/io/Serializable/skippedObjCNFException/Read.java generic-all
448.270 +java/io/Serializable/skippedObjCNFException/Write.java generic-all
448.271 +java/io/Serializable/stopCustomDeserialization/Read.java generic-all
448.272 +java/io/Serializable/stopCustomDeserialization/Write.java generic-all
448.273 +java/io/Serializable/unresolvedClassDesc/Read.java generic-all
448.274 +java/io/Serializable/unresolvedClassDesc/Write.java generic-all
448.275 +java/io/Serializable/unshared/Read.java generic-all
448.276 +java/io/Serializable/unshared/Write.java generic-all
448.277 +java/io/Serializable/wrongReturnTypes/Read.java generic-all
448.278 +java/io/Serializable/wrongReturnTypes/Write.java generic-all
448.279 +
448.280 +# Windows samevm issues? triggers other tests to fail, missing close() on f.txt?
448.281 +java/io/DataInputStream/OpsAfterClose.java generic-all
448.282 +
448.283 +# Windows 32bit samevm failure: RuntimeException: File.getFreeSpace() failed
448.284 +java/io/File/MaxPathLength.java generic-all
448.285 +
448.286 +# Should be othervm, or corrected for samevm, fails with samevm:
448.287 +java/io/File/DeleteOnExit.java generic-all
448.288 +java/io/File/DeleteOnExitLong.java generic-all
448.289 +java/io/File/DeleteOnExitNPE.java generic-all
448.290 +java/io/File/IsHidden.java generic-all
448.291 +java/io/FileDescriptor/FileChannelFDTest.java generic-all
448.292 +java/io/FileDescriptor/Finalize.java generic-all
448.293 +java/io/FileInputStream/FinalizeShdCallClose.java generic-all
448.294 +
448.295 +# Known to cause samevm issues on windows, other tests fail, missing close()?
448.296 +java/io/FileInputStream/OpsAfterClose.java generic-all
448.297 +
448.298 +# Should be othervm, or corrected for samevm, fails with samevm:
448.299 +java/io/FileOutputStream/FinalizeShdCallClose.java generic-all
448.300 +
448.301 +# Known to cause samevm issues on windows, other tests fail, missing close()?
448.302 +java/io/FileOutputStream/OpsAfterClose.java generic-all
448.303 +
448.304 +# Windows samevm issues? triggers other tests to fail, missing close() on f.txt?
448.305 +java/io/InputStream/OpsAfterClose.java generic-all
448.306 +
448.307 +# Missing close() on x.ReadBounds file? Windows samevm issues
448.308 +java/io/InputStream/ReadParams.java generic-all
448.309 +
448.310 +# Known to cause samevm issues on windows, other tests fail, missing close()?
448.311 +java/io/InputStreamReader/GrowAfterEOF.java generic-all
448.312 +
448.313 +# Should be othervm, or corrected for samevm, fails with samevm:
448.314 +java/io/ObjectInputStream/ResolveProxyClass.java generic-all
448.315 +
448.316 +# Not doing a close() on x.ParameterCheck file? windows samevm cascade error
448.317 +java/io/RandomAccessFile/ParameterCheck.java generic-all
448.318 +
448.319 +# Not doing a close on x.ReadLine file? windows cascade samevm problems
448.320 +java/io/RandomAccessFile/ReadLine.java generic-all
448.321 +
448.322 +# Not doing close on file input x.WriteByteChars, windows samevm problems
448.323 +java/io/RandomAccessFile/WriteBytesChars.java generic-all
448.324 +
448.325 +# Not doing close on file input x.WriteUTF, windows samevm problems
448.326 +java/io/RandomAccessFile/WriteUTF.java generic-all
448.327 +
448.328 +# Possibly, not doing a close() on input.txt, windows samevm issues.
448.329 +java/io/RandomAccessFile/skipBytes/SkipBytes.java generic-all
448.330 +java/io/readBytes/MemoryLeak.java generic-all
448.331 +java/io/readBytes/ReadBytesBounds.java generic-all
448.332 +
448.333 +# Missing close on fields.ser, windows samevm
448.334 +java/io/Serializable/checkModifiers/CheckModifiers.java generic-all
448.335 +
448.336 +# Should be othervm, or corrected for samevm, fails with samevm:
448.337 +java/io/Serializable/auditStreamSubclass/AuditStreamSubclass.java generic-all
448.338 +java/io/Serializable/proxy/Basic.java generic-all
448.339 +
448.340 +# Possibly not doing a close() on input.txt, windows samevm issues.
448.341 +java/io/StreamTokenizer/Comment.java generic-all
448.342 +
448.343 +############################################################################
448.344 +
448.345 +# jdk_lang
448.346 +
448.347 +# Some of these tests (like java/lang/management) may just need to be marked
448.348 +# othervm, but that is partially speculation.
448.349 +
448.350 +# Times out on solaris 10 sparc
448.351 +java/lang/ClassLoader/Assert.java generic-all
448.352 +
448.353 +# Fedora 9 X64, RuntimeException: MyThread expected to be blocked on lock, but got null
448.354 +java/lang/management/ThreadMXBean/ThreadStateTest.java generic-all
448.355 +
448.356 +# RuntimeException: Uptime of the JVM is more than 30 minutes (32 minutes).
448.357 +java/lang/management/RuntimeMXBean/UpTime.java generic-all
448.358 +
448.359 +# Times out on solaris sparc occasionally, in samevm mode
448.360 +java/lang/Runtime/exec/ExecWithDir.java generic-all
448.361 +java/lang/ProcessBuilder/Basic.java generic-all
448.362 +
448.363 +# Solaris sparc, samevm, java.lang.Exception: Read from closed pipe hangs
448.364 +java/lang/Runtime/exec/SleepyCat.java generic-all
448.365 +
448.366 +# Need to be marked othervm, or changed to be samevm safe
448.367 +java/lang/annotation/ParameterAnnotations.java generic-all
448.368 +
448.369 +# Need to be marked othervm, or changed to be samevm safe
448.370 +java/lang/ClassLoader/defineClass/DefineClassByteBuffer.java generic-all
448.371 +java/lang/ClassLoader/findSystemClass/Loader.java generic-all
448.372 +
448.373 +# Fedora 9 32bit, -client, samevm, Error while cleaning up threads after test
448.374 +java/lang/management/ThreadMXBean/Locks.java generic-all
448.375 +
448.376 +# Need to be marked othervm, or changed to be samevm safe
448.377 +java/lang/management/ClassLoadingMXBean/LoadCounts.java generic-all
448.378 +java/lang/management/ManagementFactory/MBeanServerMXBeanUnsupportedTest.java generic-all
448.379 +java/lang/management/ManagementFactory/MXBeanProxyTest.java generic-all
448.380 +java/lang/management/ManagementFactory/ThreadMXBeanProxy.java generic-all
448.381 +java/lang/management/MemoryMXBean/CollectionUsageThreshold.java generic-all
448.382 +java/lang/management/MemoryMXBean/GetMBeanInfo.java generic-all
448.383 +java/lang/management/MemoryMXBean/LowMemoryTest.java generic-all
448.384 +java/lang/management/MemoryMXBean/MemoryManagement.java generic-all
448.385 +java/lang/management/MemoryMXBean/MemoryTest.java generic-all
448.386 +java/lang/management/MemoryMXBean/Pending.java generic-all
448.387 +
448.388 +# Problematic on all platforms (even as othervm)
448.389 +java/lang/management/MemoryMXBean/ResetPeakMemoryUsage.java generic-all
448.390 +
448.391 +# Causes jtreg exit samevm issues due to non-String object in system properties
448.392 +java/lang/management/RuntimeMXBean/GetSystemProperties.java generic-all
448.393 +
448.394 +# Need to be marked othervm, or changed to be samevm safe
448.395 +java/lang/management/RuntimeMXBean/PropertiesTest.java generic-all
448.396 +java/lang/management/ThreadMXBean/AllThreadIds.java generic-all
448.397 +java/lang/management/ThreadMXBean/EnableTest.java generic-all
448.398 +java/lang/management/ThreadMXBean/FindMonitorDeadlock.java generic-all
448.399 +java/lang/management/ThreadMXBean/LockingThread.java generic-all
448.400 +java/lang/management/ThreadMXBean/MonitorDeadlock.java generic-all
448.401 +java/lang/management/ThreadMXBean/MyOwnSynchronizer.java generic-all
448.402 +java/lang/management/ThreadMXBean/SharedSynchronizer.java generic-all
448.403 +java/lang/management/ThreadMXBean/SynchronizerLockingThread.java generic-all
448.404 +java/lang/management/ThreadMXBean/ThreadCounts.java generic-all
448.405 +
448.406 +# Need to be marked othervm, or changed to be samevm safe
448.407 +java/lang/reflect/Proxy/Boxing.java generic-all
448.408 +java/lang/reflect/Proxy/ClassRestrictions.java generic-all
448.409 +java/lang/reflect/Proxy/returnTypes/Test.java generic-all
448.410 +
448.411 +# Need to be marked othervm, or changed to be samevm safe
448.412 +java/lang/Runtime/exec/LotsOfOutput.java generic-all
448.413 +java/lang/System/ExitFinalizersAndJIT.java generic-all
448.414 +java/lang/System/finalization/FinThreads.java generic-all
448.415 +java/lang/System/IgnoreNullSecurityManager.java generic-all
448.416 +java/lang/Thread/GenerifyStackTraces.java generic-all
448.417 +java/lang/Thread/StackTraces.java generic-all
448.418 +java/lang/ThreadGroup/Daemon.java generic-all
448.419 +java/lang/ThreadGroup/NullThreadName.java generic-all
448.420 +
448.421 +# Times out on solaris sparc -server
448.422 +java/lang/ThreadLocal/MemoryLeak.java solaris-all
448.423 +
448.424 +# Windows X64, RuntimeException: MyThread expected to have RUNNABLE but got WAITING
448.425 +java/lang/Thread/ThreadStateTest.java generic-all
448.426 +
448.427 +# Timeout on windows 64bit
448.428 +java/lang/ClassLoader/deadlock/TestCrossDelegate.sh generic-all
448.429 +
448.430 +############################################################################
448.431 +
448.432 +# jdk_management
448.433 +
448.434 +# Solaris 10 sparc, NPE from org.omg.stub.javax.management.remote.rmi._RMIConnectionImpl_Tie._invoke
448.435 +javax/management/remote/mandatory/threads/ExecutorTest.java generic-all
448.436 +
448.437 +# Linux 32bit Fedora 9, IllegalStateException
448.438 +javax/management/monitor/RuntimeExceptionTest.java generic-all
448.439 +
448.440 +# Problems with rmi connection, othervm
448.441 +javax/management/remote/mandatory/subjectDelegation/SubjectDelegation2Test.java generic-all
448.442 +
448.443 +# Fails with port already in use
448.444 +sun/management/jmxremote/bootstrap/SSLConfigFilePermissionTest.sh generic-all
448.445 +
448.446 +# Fails with port already in use
448.447 +sun/management/jmxremote/bootstrap/RmiRegistrySslTest.sh generic-all
448.448 +
448.449 +# Windows, connection can't last that long
448.450 +javax/management/eventService/LeaseTest.java generic-all
448.451 +
448.452 +# Linux othervm, X64, java.lang.Exception: Failed: ratio=102.4027795593753
448.453 +javax/management/remote/mandatory/notif/ListenerScaleTest.java generic-all
448.454 +
448.455 +# Windows run seems to have triggered a hotspot gc error (see 6801625)
448.456 +com/sun/management/HotSpotDiagnosticMXBean/DumpHeap.sh generic-all
448.457 +
448.458 +# rmi problem? othervm, java.lang.reflect.UndeclaredThrowableException
448.459 +javax/management/remote/mandatory/subjectDelegation/SubjectDelegation3Test.java generic-all
448.460 +
448.461 +# Linux Fedora 9 32bit NPE in rmi server somehere??? othervm
448.462 +javax/management/remote/mandatory/notif/NotificationBufferDeadlockTest.java generic-all
448.463 +
448.464 +# Times out on solaris sparc, with othervm
448.465 +javax/management/eventService/AddRemoveListenerTest.java generic-all
448.466 +
448.467 +# Linux i586 and x64 -server, timed out waiting for threads to expire? othervm
448.468 +javax/management/eventService/EventClientThreadTest.java generic-all
448.469 +
448.470 +# Linux i586 -server, Expected to receive 20, but got 21, othervm
448.471 +# Fails on Linux X64 -server 20!=21
448.472 +javax/management/eventService/FetchingTest.java generic-all
448.473 +
448.474 +# NPE on windows 2000 i586 -client and -server
448.475 +javax/management/eventService/CustomForwarderTest.java windows-all
448.476 +
448.477 +# Windows i586 failure, callback did not complete
448.478 +javax/management/eventService/LeaseManagerDeadlockTest.java windows-all
448.479 +
448.480 +# Port already in use
448.481 +sun/management/jmxremote/bootstrap/LocalManagementTest.sh generic-all
448.482 +
448.483 +# Failed to initialize connector (also overflowing jtreg io buffers)
448.484 +sun/management/jmxremote/bootstrap/RmiBootstrapTest.sh generic-all
448.485 +sun/management/jmxremote/bootstrap/RmiSslBootstrapTest.sh generic-all
448.486 +
448.487 +# Windows X64, java.lang.IllegalStateException
448.488 +javax/management/monitor/AttributeArbitraryDataTypeTest.java generic-all
448.489 +
448.490 +############################################################################
448.491 +
448.492 +# jdk_math
448.493 +
448.494 +# Problems with rounding add failures on solaris-sparcv9 and -server
448.495 +java/math/BigDecimal/AddTests.java solaris-sparcv9
448.496 +
448.497 +# Problems on windows with samevm, missing inputstream close()?
448.498 +# Also times out on solaris-sparcv9 -server
448.499 +java/math/BigInteger/BigIntegerTest.java generic-all
448.500 +
448.501 +# Should be samevm? But seems problematic with samevm on windows
448.502 +java/math/BigInteger/ModPow65537.java generic-all
448.503 +
448.504 +############################################################################
448.505 +
448.506 +# jdk_misc
448.507 +
448.508 +# On Windows com.sun.java.swing.plaf.gtk does not exist, always fails there
448.509 +com/sun/java/swing/plaf/gtk/Test6635110.java windows-all
448.510 +
448.511 +# Need to be marked othervm, or changed to be samevm safe
448.512 +com/sun/jndi/ldap/ReadTimeoutTest.java generic-all
448.513 +com/sun/jndi/rmi/registry/RegistryContext/UnbindIdempotent.java generic-all
448.514 +
448.515 +# Need to be marked othervm, or changed to be samevm safe
448.516 +com/sun/org/apache/xml/internal/security/transforms/ClassLoaderTest.java generic-all
448.517 +
448.518 +# Solaris sparc and others, exception in initializer
448.519 +javax/imageio/CachePremissionsTest/CachePermissionsTest.java generic-all
448.520 +
448.521 +# Leaves file rgba_* open, fails with windows samevm
448.522 +javax/imageio/plugins/png/PngOutputTypeTest.java generic-all
448.523 +
448.524 +# Suspect test.png file is left open, windows samevm problems
448.525 +javax/imageio/plugins/png/ITXtTest.java generic-all
448.526 +
448.527 +# Solaris sparc and others, failed to compile testcase
448.528 +javax/imageio/metadata/DOML3Node.java generic-all
448.529 +
448.530 +# One of these tests is leaving file IMGP1001.JPG open, windows samevm
448.531 +javax/imageio/plugins/jpeg/ConcurrentReadingTest.java generic-all
448.532 +javax/imageio/plugins/jpeg/ReadingInterruptionTest.java generic-all
448.533 +
448.534 +# One of these files is missing a close on writer_* files, windows samevm
448.535 +javax/imageio/plugins/jpeg/ConcurrentWritingTest.java generic-all
448.536 +javax/imageio/plugins/jpeg/WritingInterruptionTest.java generic-all
448.537 +
448.538 +# Leaving file test.jpg open, windows samevm
448.539 +javax/imageio/plugins/jpeg/ReadAsGrayTest.java generic-all
448.540 +
448.541 +# Missing close on file wbmp*, windows samevm
448.542 +javax/imageio/plugins/wbmp/CanDecodeTest.java generic-all
448.543 +
448.544 +# Exclude all javax/print tests, even if they passed, they may need samevm work
448.545 +
448.546 +# Times out on solaris-sparc, sparcv9, x64 -server, some on i586 -client
448.547 +javax/print/attribute/autosense/PrintAutoSenseData.java generic-all
448.548 +javax/print/attribute/Chroma.java generic-all
448.549 +javax/print/attribute/CollateAttr.java generic-all
448.550 +javax/print/attribute/PSCopiesFlavorTest.java generic-all
448.551 +javax/print/LookupServices.java generic-all
448.552 +javax/print/TestRaceCond.java generic-all
448.553 +
448.554 +# These tests really require a printer (might all be windows only tests?)
448.555 +javax/print/CheckDupFlavor.java generic-all
448.556 +javax/print/PrintSE/PrintSE.sh generic-all
448.557 +javax/print/attribute/ChromaticityValues.java generic-all
448.558 +javax/print/attribute/GetCopiesSupported.java generic-all
448.559 +javax/print/attribute/SidesPageRangesTest.java generic-all
448.560 +javax/print/attribute/SupportedPrintableAreas.java generic-all
448.561 +
448.562 +# Only print test left, excluding just because all print tests have been
448.563 +javax/print/attribute/MediaMappingsTest.java generic-all
448.564 +
448.565 +############################################################################
448.566 +
448.567 +# jdk_net
448.568 +
448.569 +# Suspect many of these tests auffer from using fixed ports, no concrete
448.570 +# evidence.
448.571 +
448.572 +# Fails on OpenSolaris, BindException unexpected
448.573 +java/net/BindException/Test.java generic-all
448.574 +
448.575 +# Fails on OpenSolaris, times out
448.576 +java/net/MulticastSocket/SetOutgoingIf.java generic-all
448.577 +
448.578 +# Timed out on Solaris 10 X86.
448.579 +com/sun/net/httpserver/Test3.java generic-all
448.580 +
448.581 +# Exception in test on windows
448.582 +com/sun/net/httpserver/bugs/B6373555.java windows-all
448.583 +
448.584 +# One of these pollutes the samevm on Linux, too many open files, kills jtreg
448.585 +com/sun/net/httpserver/bugs/B6339483.java generic-all
448.586 +com/sun/net/httpserver/bugs/B6341616.java generic-all
448.587 +
448.588 +# Suspects in cascading samevm problem, solaris 11 i586 (needs othervm?)
448.589 +# Suspect use of setHttps*()?
448.590 +com/sun/net/httpserver/SelCacheTest.java generic-all
448.591 +com/sun/net/httpserver/Test1.java generic-all
448.592 +com/sun/net/httpserver/Test12.java generic-all
448.593 +com/sun/net/httpserver/Test13.java generic-all
448.594 +com/sun/net/httpserver/Test6a.java generic-all
448.595 +com/sun/net/httpserver/Test7a.java generic-all
448.596 +com/sun/net/httpserver/Test8a.java generic-all
448.597 +com/sun/net/httpserver/Test9.java generic-all
448.598 +com/sun/net/httpserver/Test9a.java generic-all
448.599 +
448.600 +# 10,000 connections, fails on Linux and makes tests&jtreg fail with samevm
448.601 +com/sun/net/httpserver/bugs/B6361557.java generic-all
448.602 +
448.603 +# Address already in use with samevm? Always? Solaris sparc, probably ports
448.604 +java/net/Authenticator/B4933582.sh generic-all
448.605 +java/net/DatagramSocket/SendSize.java generic-all
448.606 +
448.607 +# Solaris 11: exception wrong address???
448.608 +java/net/Inet6Address/B6558853.java generic-all
448.609 +
448.610 +# Not closing stream on file i6a1, windows samevm problem
448.611 +java/net/Inet6Address/serialize/Serialize.java generic-all
448.612 +
448.613 +# Linux x64 fails "network unreachable"?
448.614 +java/net/ipv6tests/TcpTest.java generic-all
448.615 +
448.616 +# Linux i586, fails with unexpected output
448.617 +java/net/MulticastSocket/NoLoopbackPackets.java linux-i586
448.618 +
448.619 +# Times out on windows x64, fails with samevm on solaris 11 i586
448.620 +java/net/ServerSocket/AcceptCauseFileDescriptorLeak.java generic-all
448.621 +
448.622 +# Address already in use
448.623 +java/net/DatagramSocket/DatagramTimeout.java generic-all
448.624 +
448.625 +# Fails on windows, takes too long and fails
448.626 +# Solaris 10 sparcv9, samevm, java.lang.Exception: Takes too long. Dead lock
448.627 +java/net/Socket/DeadlockTest.java generic-all
448.628 +
448.629 +# Linux i586 address already in use or connection error, samevm issues
448.630 +java/net/Socket/AccurateTimeout.java generic-all
448.631 +java/net/Socket/asyncClose/BrokenPipe.java generic-all
448.632 +java/net/Socket/CloseAvailable.java generic-all
448.633 +java/net/Socket/FDClose.java generic-all
448.634 +
448.635 +# Linux X64 address already in use, samevm issues
448.636 +java/net/Socket/LingerTest.java generic-all
448.637 +java/net/Socket/LinkLocal.java generic-all
448.638 +java/net/Socket/NullHost.java generic-all
448.639 +java/net/Socket/ProxyCons.java generic-all
448.640 +java/net/Socket/ReadTimeout.java generic-all
448.641 +
448.642 +# Linux X64 address already in use, samevm issues
448.643 +java/net/Socket/SetReceiveBufferSize.java generic-all
448.644 +
448.645 +# Linux i586 address already in use or connection error, samevm issues
448.646 +java/net/Socket/setReuseAddress/Basic.java generic-all
448.647 +java/net/Socket/setReuseAddress/Restart.java generic-all
448.648 +
448.649 +# Linux X64 address already in use, samevm issues
448.650 +java/net/Socket/SetSoLinger.java generic-all
448.651 +
448.652 +# Address already in use, windows samevm
448.653 +java/net/Socket/Timeout.java generic-all
448.654 +
448.655 +# Linux X64 address already in use, samevm issues
448.656 +java/net/Socket/ShutdownBoth.java generic-all
448.657 +java/net/Socket/SoTimeout.java generic-all
448.658 +java/net/Socket/TestClose.java generic-all
448.659 +java/net/Socket/UrgentDataTest.java generic-all
448.660 +java/net/SocketInputStream/SocketClosedException.java generic-all
448.661 +java/net/SocketInputStream/SocketTimeout.java generic-all
448.662 +
448.663 +# Linux i586, address already in use or timeout, samevm issues
448.664 +java/net/URLConnection/B5052093.java generic-all
448.665 +java/net/URLConnection/contentHandler/UserContentHandler.java generic-all
448.666 +java/net/URLConnection/DisconnectAfterEOF.java generic-all
448.667 +java/net/URLConnection/HandleContentTypeWithAttrs.java generic-all
448.668 +java/net/URLConnection/Responses.java generic-all
448.669 +java/net/URLConnection/TimeoutTest.java generic-all
448.670 +java/net/URLConnection/ZeroContentLength.java generic-all
448.671 +
448.672 +# Solaris 11 i586 fails with samevm, not sure why
448.673 +java/net/Authenticator/B4769350.java generic-all
448.674 +java/net/HttpURLConnection/HttpResponseCode.java generic-all
448.675 +java/net/ResponseCache/B6181108.java generic-all
448.676 +java/net/ResponseCache/ResponseCacheTest.java generic-all
448.677 +java/net/URL/GetContent.java generic-all
448.678 +java/net/URL/TestIPv6Addresses.java generic-all
448.679 +java/net/URLClassLoader/HttpTest.java generic-all
448.680 +java/net/URLConnection/HttpContinueStackOverflow.java generic-all
448.681 +java/net/URLConnection/Redirect307Test.java generic-all
448.682 +java/net/URLConnection/RedirectLimit.java generic-all
448.683 +java/net/URLConnection/ResendPostBody.java generic-all
448.684 +java/net/URL/OpenStream.java generic-all
448.685 +java/net/URLClassLoader/ClassLoad.java generic-all
448.686 +java/net/URLConnection/SetIfModifiedSince.java generic-all
448.687 +java/net/URLConnection/URLConnectionHeaders.java generic-all
448.688 +
448.689 +# Linux i586 Connection refused or address already in use, samevm issues
448.690 +sun/net/ftp/B6427768.java generic-all
448.691 +sun/net/ftp/FtpGetContent.java generic-all
448.692 +sun/net/ftp/FtpURL.java generic-all
448.693 +
448.694 +# Failed on solaris 10 i586, Exception: should have gotten HttpRetryException?
448.695 +sun/net/www/http/ChunkedOutputStream/Test.java generic-all
448.696 +
448.697 +# Trouble cleaning up threads in samevm mode on solaris 11 i586
448.698 +sun/net/www/http/HttpClient/ProxyTest.java generic-all
448.699 +sun/net/www/http/ChunkedInputStream/ChunkedEncodingTest.java generic-all
448.700 +sun/net/www/http/ChunkedInputStream/ChunkedEncodingWithProgressMonitorTest.java generic-all
448.701 +sun/net/www/http/HttpClient/B6726695.java generic-all
448.702 +sun/net/www/http/HttpClient/MultiThreadTest.java generic-all
448.703 +sun/net/www/http/KeepAliveCache/KeepAliveTimerThread.java generic-all
448.704 +
448.705 +# Connection refused, windows samevm
448.706 +sun/net/www/protocol/http/DigestTest.java generic-all
448.707 +
448.708 +############################################################################
448.709 +
448.710 +# jdk_nio
448.711 +
448.712 +# Suspect many of these tests auffer from using fixed ports, no concrete
448.713 +# evidence.
448.714 +
448.715 +# Fails on OpenSolaris, IllegalStateException: Cannot add or remove addresses
448.716 +# from a channel that is bound to the wildcard address
448.717 +com/sun/nio/sctp/SctpChannel/Bind.java generic-all
448.718 +
448.719 +# Failed on OpenSolaris, java.lang.AssertionError: Unknown event type
448.720 +com/sun/nio/sctp/SctpChannel/Receive.java generic-all
448.721 +
448.722 +# Triggers a hotspot crash on Fedora 9 32bit -server and Windows X64 samevm
448.723 +sun/nio/cs/TestUTF8.java generic-all
448.724 +
448.725 +# Solaris sparc, socket timeout
448.726 +java/nio/channels/spi/SelectorProvider/inheritedChannel/run_tests.sh generic-all
448.727 +
448.728 +# Runtime exception on windows X64, samevm mode
448.729 +java/nio/channels/Selector/WakeupNow.java generic-all
448.730 +
448.731 +# Occasional errors, solarix x86, address already in use, othervm mode
448.732 +java/nio/channels/Selector/SelectorTest.java generic-all
448.733 +
448.734 +# Fails on Linux Fedora 9 X64
448.735 +sun/nio/cs/FindDecoderBugs.java generic-all
448.736 +
448.737 +# Solaris 11 gave assert error and "connection refused", samevm issues?
448.738 +com/sun/nio/sctp/SctpServerChannel/NonBlockingAccept.java generic-all
448.739 +
448.740 +# Fails with othervm on solaris 11 i586
448.741 +com/sun/nio/sctp/SctpChannel/CommUp.java generic-all
448.742 +com/sun/nio/sctp/SctpChannel/Connect.java generic-all
448.743 +com/sun/nio/sctp/SctpMultiChannel/Branch.java generic-all
448.744 +com/sun/nio/sctp/SctpMultiChannel/Send.java generic-all
448.745 +com/sun/nio/sctp/SctpMultiChannel/SocketOptionTests.java generic-all
448.746 +
448.747 +# Linux 64bit failures. too many files open
448.748 +java/nio/channels/Selector/HelperSlowToDie.java generic-all
448.749 +
448.750 +# Timeouts etc. on Window
448.751 +java/nio/channels/AsyncCloseAndInterrupt.java windows-all
448.752 +
448.753 +# Gets java.lang.ExceptionInInitializerError on windows: (Windows 2000 only?)
448.754 +java/nio/channels/AsynchronousChannelGroup/Basic.java windows-5.0
448.755 +java/nio/channels/AsynchronousChannelGroup/GroupOfOne.java windows-5.0
448.756 +java/nio/channels/AsynchronousChannelGroup/Identity.java windows-5.0
448.757 +java/nio/channels/AsynchronousChannelGroup/Restart.java windows-5.0
448.758 +java/nio/channels/AsynchronousDatagramChannel/Basic.java windows-5.0
448.759 +java/nio/channels/AsynchronousFileChannel/Lock.java windows-5.0
448.760 +java/nio/channels/AsynchronousServerSocketChannel/Basic.java windows-5.0
448.761 +java/nio/channels/AsynchronousServerSocketChannel/WithSecurityManager.java windows-5.0
448.762 +java/nio/channels/AsynchronousSocketChannel/Basic.java windows-5.0
448.763 +java/nio/channels/AsynchronousSocketChannel/DieBeforeComplete.java windows-5.0
448.764 +java/nio/channels/AsynchronousSocketChannel/Leaky.java windows-5.0
448.765 +java/nio/channels/AsynchronousSocketChannel/StressLoopback.java windows-5.0
448.766 +java/nio/channels/Channels/Basic2.java windows-5.0
448.767 +
448.768 +# Solaris sparc timeout
448.769 +java/nio/channels/DatagramChannel/Connect.java generic-all
448.770 +
448.771 +# Solaris i586 timeouts
448.772 +java/nio/channels/DatagramChannel/EmptyBuffer.java solaris-all
448.773 +
448.774 +# Failed loopback connection? On windows 32bit?
448.775 +# Considered a stress test, can consume all resources.
448.776 +java/nio/channels/Selector/LotsOfChannels.java generic-all
448.777 +
448.778 +# Solaris sparcv9, just fails with exception
448.779 +java/nio/channels/Selector/OpRead.java solaris-sparc
448.780 +
448.781 +# Windows i586 client, crashed hotspot? Unpredictable
448.782 +# Considered a stress test, can consume all resources.
448.783 +java/nio/channels/Selector/RegAfterPreClose.java generic-all
448.784 +
448.785 +# Solaris i586, cannot assign address, samevm issues
448.786 +java/nio/channels/Selector/SelectorLimit.java generic-all
448.787 +
448.788 +# Socket timeout windows X64
448.789 +java/nio/channels/ServerSocketChannel/AdaptServerSocket.java windows-all
448.790 +
448.791 +# Timeouts etc. on Window
448.792 +java/nio/channels/SocketChannel/ConnectState.java windows-all
448.793 +java/nio/channels/SocketChannel/FinishConnect.java windows-all
448.794 +
448.795 +# Need to be marked othervm, or changed to be samevm safe
448.796 +java/nio/channels/SocketChannel/OpenLeak.java generic-all
448.797 +
448.798 +# Gets java.net.BindException alot (static port number?)
448.799 +java/nio/channels/SocketChannel/VectorIO.java generic-all
448.800 +
448.801 +# Solaris i586 java.net.BindExceptions
448.802 +java/nio/channels/SocketChannel/VectorParams.java solaris-all
448.803 +
448.804 +# Linux i586 address already in use, samevm issues
448.805 +java/nio/channels/SocketChannel/Write.java generic-all
448.806 +
448.807 +# Fails on all platforms due to overlap of JDK jar file contents:
448.808 +sun/nio/cs/Test4200310.sh generic-all
448.809 +
448.810 +# Depends on motif packages that do not exist all the time:
448.811 +sun/nio/cs/TestX11CNS.java generic-all
448.812 +
448.813 +############################################################################
448.814 +
448.815 +# jdk_rmi
448.816 +
448.817 +# Port already in use, fails on sparc, othervm
448.818 +java/rmi/reliability/benchmark/runRmiBench.sh generic-all
448.819 +
448.820 +# Already in use port issues? othervm solaris
448.821 +java/rmi/activation/rmidViaInheritedChannel/InheritedChannelNotServerSocket.java generic-all
448.822 +java/rmi/activation/rmidViaInheritedChannel/RmidViaInheritedChannel.java generic-all
448.823 +
448.824 +# Address already in use, othervm mode, solaris
448.825 +java/rmi/activation/Activatable/elucidateNoSuchMethod/ElucidateNoSuchMethod.java generic-all
448.826 +java/rmi/activation/Activatable/forceLogSnapshot/ForceLogSnapshot.java generic-all
448.827 +
448.828 +# Registry already running on port, solaris
448.829 +java/rmi/Naming/legalRegistryNames/LegalRegistryNames.java generic-all
448.830 +
448.831 +# Fails on Linux 32 and 64bit -server?, impl not garbage collected???
448.832 +java/rmi/transport/pinLastArguments/PinLastArguments.java generic-all
448.833 +
448.834 +# Times out on solaris sparc
448.835 +java/rmi/server/RemoteServer/AddrInUse.java generic-all
448.836 +
448.837 +# Connection error on Windows i586 -server
448.838 +# Also connection errors in othervm on Solaris 10 sparc, same port???
448.839 +sun/rmi/transport/tcp/DeadCachedConnection.java generic-all
448.840 +
448.841 +# Connection errors in othervm on Solaris 10 sparc, same port???
448.842 +java/rmi/activation/Activatable/checkActivateRef/CheckActivateRef.java generic-all
448.843 +java/rmi/activation/Activatable/checkAnnotations/CheckAnnotations.java generic-all
448.844 +java/rmi/activation/Activatable/checkImplClassLoader/CheckImplClassLoader.java generic-all
448.845 +java/rmi/activation/Activatable/checkRegisterInLog/CheckRegisterInLog.java generic-all
448.846 +java/rmi/activation/Activatable/createPrivateActivable/CreatePrivateActivatable.java generic-all
448.847 +java/rmi/activation/Activatable/downloadParameterClass/DownloadParameterClass.java generic-all
448.848 +java/rmi/activation/Activatable/extLoadedImpl/ext.sh generic-all
448.849 +java/rmi/activation/Activatable/inactiveGroup/InactiveGroup.java generic-all
448.850 +java/rmi/activation/Activatable/lookupActivationSystem/LookupActivationSystem.java generic-all
448.851 +java/rmi/activation/Activatable/nestedActivate/NestedActivate.java generic-all
448.852 +java/rmi/activation/Activatable/restartCrashedService/RestartCrashedService.java generic-all
448.853 +java/rmi/activation/Activatable/restartLatecomer/RestartLatecomer.java generic-all
448.854 +java/rmi/activation/Activatable/shutdownGracefully/ShutdownGracefully.java generic-all
448.855 +java/rmi/activation/Activatable/unregisterInactive/UnregisterInactive.java generic-all
448.856 +java/rmi/activation/ActivateFailedException/activateFails/ActivateFails.java generic-all
448.857 +java/rmi/activation/ActivationGroup/downloadActivationGroup/DownloadActivationGroup.java generic-all
448.858 +java/rmi/activation/ActivationSystem/activeGroup/IdempotentActiveGroup.java generic-all
448.859 +java/rmi/reliability/juicer/AppleUserImpl.java generic-all
448.860 +java/rmi/server/RMISocketFactory/useSocketFactory/unicast/UseCustomSocketFactory.java generic-all
448.861 +java/rmi/server/UnicastRemoteObject/keepAliveDuringCall/KeepAliveDuringCall.java generic-all
448.862 +java/rmi/transport/handshakeTimeout/HandshakeTimeout.java generic-all
448.863 +java/rmi/activation/Activatable/restartService/RestartService.java generic-all
448.864 +java/rmi/activation/ActivationSystem/modifyDescriptor/ModifyDescriptor.java generic-all
448.865 +java/rmi/activation/ActivationSystem/stubClassesPermitted/StubClassesPermitted.java generic-all
448.866 +java/rmi/activation/ActivationSystem/unregisterGroup/UnregisterGroup.java generic-all
448.867 +java/rmi/activation/CommandEnvironment/SetChildEnv.java generic-all
448.868 +java/rmi/registry/classPathCodebase/ClassPathCodebase.java generic-all
448.869 +java/rmi/registry/reexport/Reexport.java generic-all
448.870 +java/rmi/server/Unreferenced/finiteGCLatency/FiniteGCLatency.java generic-all
448.871 +java/rmi/server/Unreferenced/leaseCheckInterval/LeaseCheckInterval.java generic-all
448.872 +java/rmi/server/Unreferenced/unreferencedContext/UnreferencedContext.java generic-all
448.873 +java/rmi/server/useCustomRef/UseCustomRef.java generic-all
448.874 +java/rmi/transport/checkFQDN/CheckFQDN.java generic-all
448.875 +java/rmi/transport/checkLeaseInfoLeak/CheckLeaseLeak.java generic-all
448.876 +java/rmi/server/RMISocketFactory/useSocketFactory/activatable/UseCustomSocketFactory.java generic-all
448.877 +java/rmi/server/RMISocketFactory/useSocketFactory/registry/UseCustomSocketFactory.java generic-all
448.878 +java/rmi/server/UnicastRemoteObject/unexportObject/UnexportLeak.java generic-all
448.879 +
448.880 +############################################################################
448.881 +
448.882 +# jdk_security
448.883 +
448.884 +# Run too slow on Solaris 10 sparc
448.885 +sun/security/ssl/com/sun/net/ssl/internal/ssl/InputRecord/SSLSocketTimeoutNulls.java solaris-sparc
448.886 +sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ClientTimeout.java solaris-sparc
448.887 +sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/ServerTimeout.java solaris-sparc
448.888 +sun/security/ssl/sun/net/www/protocol/https/HttpsURLConnection/ReadTimeout.java solaris-sparc
448.889 +sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/NotifyHandshakeTest.sh solaris-sparc
448.890 +sun/security/tools/keytool/AltProviderPath.sh solaris-sparc
448.891 +
448.892 +# Solaris 10 sparc, passed/failed confusion? java.security.ProviderException: update() failed
448.893 +sun/security/ssl/com/sun/net/ssl/internal/ssl/SSLSocketImpl/AsyncSSLSocketClose.java generic-all
448.894 +
448.895 +# Seem really slow on Solaris sparc, being excluded just for timing reasons
448.896 +sun/security/tools/jarsigner/AlgOptions.sh solaris-sparc
448.897 +sun/security/tools/jarsigner/nameclash.sh solaris-sparc
448.898 +sun/security/krb5/auto/basic.sh solaris-sparc
448.899 +sun/security/provider/PolicyFile/getinstance/getinstance.sh solaris-sparc
448.900 +sun/security/tools/jarsigner/samename.sh solaris-sparc
448.901 +
448.902 +# Timed out, Solaris 10 64bit sparcv9
448.903 +com/sun/crypto/provider/Cipher/DES/PaddingTest.java generic-all
448.904 +
448.905 +# Othervm, sparc, NoRouteToHostException: Cannot assign requested address
448.906 +sun/security/ssl/javax/net/ssl/NewAPIs/SessionCacheSizeTests.java generic-all
448.907 +
448.908 +# ProviderException: sun.security.pkcs11.wrapper.PKCS11Exception: CKR_DEVICE_ERROR
448.909 +# Does not seem to run on windows machines? dll missing?
448.910 +sun/security/pkcs11/rsa/TestKeyPairGenerator.java generic-all
448.911 +
448.912 +# Times out on windows X64, othervm mode
448.913 +# Solaris sparc and sparcv9 -server, timeout
448.914 +sun/security/ssl/javax/net/ssl/NewAPIs/SessionTimeOutTests.java generic-all
448.915 +
448.916 +# Failed on solaris 10 sparc, othervm mode, "js.jks: No such file or directory"
448.917 +# Also, cannot verify signature on solaris i586 -server
448.918 +sun/security/tools/jarsigner/concise_jarsigner.sh generic-all
448.919 +
448.920 +# Various failures on Linux Fedora 9 X64, othervm mode
448.921 +lib/security/cacerts/VerifyCACerts.java generic-all
448.922 +sun/security/ssl/javax/net/ssl/NewAPIs/SSLEngine/TestAllSuites.java generic-all
448.923 +sun/security/ssl/sanity/ciphersuites/CheckCipherSuites.java generic-all
448.924 +sun/security/tools/jarsigner/oldsig.sh generic-all
448.925 +
448.926 +# Various failures on Linux Fedora 9 X64, othervm mode
448.927 +# Does not seem to run on windows machines? dll missing?
448.928 +sun/security/ssl/sanity/interop/ClientJSSEServerJSSE.java generic-all
448.929 +
448.930 +# Linux i586 -server, buffer too short to hold shared secret?
448.931 +com/sun/crypto/provider/KeyAgreement/DHKeyAgreement2.java generic-all
448.932 +
448.933 +# Solaris sparcv9: Failed to parse input emptysubject.jks: No such file or directory
448.934 +sun/security/tools/keytool/emptysubject.sh generic-all
448.935 +
448.936 +# Timeout on solaris-sparcv9 or exception thrown
448.937 +com/sun/crypto/provider/Cipher/RSA/TestOAEP_KAT.java solaris-all
448.938 +
448.939 +# File 6535697.test input stream left open? windows samevm
448.940 +java/security/cert/CertificateFactory/openssl/OpenSSLCert.java generic-all
448.941 +
448.942 +# Leaving file open: SerialVersion.current, windows samevm
448.943 +java/security/BasicPermission/SerialVersion.java generic-all
448.944 +
448.945 +# Solaris 11 i586, these all fail with samevm, need to be othervm???
448.946 +java/security/BasicPermission/NullOrEmptyName.java generic-all
448.947 +
448.948 +# Suspect missing close() on file PermClass.current, windows samevm cascade
448.949 +java/security/BasicPermission/PermClass.java generic-all
448.950 +
448.951 +# Solaris 11 i586, these all fail with samevm, need to be othervm???
448.952 +java/security/KeyPairGenerator/Failover.java generic-all
448.953 +java/security/Provider/DefaultPKCS11.java generic-all
448.954 +java/security/SecureClassLoader/DefineClassByteBuffer.java generic-all
448.955 +java/security/SecureRandom/GetAlgorithm.java generic-all
448.956 +java/security/Security/removing/RemoveProviders.java generic-all
448.957 +java/security/Signature/ByteBuffers.java generic-all
448.958 +java/security/Signature/NONEwithRSA.java generic-all
448.959 +java/security/Signature/SignWithOutputBuffer.java generic-all
448.960 +java/security/Signature/TestInitSignWithMyOwnRandom.java generic-all
448.961 +java/security/UnresolvedPermission/AccessorMethods.java generic-all
448.962 +java/security/UnresolvedPermission/Equals.java generic-all
448.963 +
448.964 +# Do not seem to run on windows machines? dll missing?
448.965 +sun/security/krb5/auto/IgnoreChannelBinding.java windows-all
448.966 +
448.967 +# Fails on OpenSolaris, missing classes, slow on Solaris sparc
448.968 +sun/security/ec/TestEC.java generic-all
448.969 +
448.970 +# Problems with windows x64
448.971 +sun/security/mscapi/IsSunMSCAPIAvailable.sh windows-x64
448.972 +sun/security/mscapi/RSAEncryptDecrypt.sh windows-x64
448.973 +
448.974 +# Do not seem to run on windows machines? dll missing?
448.975 +sun/security/pkcs11/Cipher/ReinitCipher.java windows-all
448.976 +sun/security/pkcs11/Cipher/TestRSACipher.java windows-all
448.977 +sun/security/pkcs11/Cipher/TestRSACipherWrap.java windows-all
448.978 +sun/security/pkcs11/Cipher/TestSymmCiphers.java windows-all
448.979 +sun/security/pkcs11/Cipher/TestSymmCiphersNoPad.java windows-all
448.980 +
448.981 +# Do not seem to run on windows machines? dll missing?
448.982 +sun/security/pkcs11/ec/ReadCertificates.java windows-all
448.983 +sun/security/pkcs11/ec/ReadPKCS12.java windows-all
448.984 +sun/security/pkcs11/ec/TestCurves.java windows-all
448.985 +sun/security/pkcs11/ec/TestECDH.java windows-all
448.986 +sun/security/pkcs11/ec/TestECDSA.java windows-all
448.987 +sun/security/pkcs11/ec/TestECGenSpec.java windows-all
448.988 +sun/security/pkcs11/ec/TestKeyFactory.java windows-all
448.989 +sun/security/pkcs11/fips/TrustManagerTest.java windows-all
448.990 +
448.991 +# Do not seem to run on windows machines? dll missing?
448.992 +sun/security/pkcs11/KeyAgreement/TestShort.java windows-all
448.993 +sun/security/pkcs11/KeyGenerator/DESParity.java windows-all
448.994 +
448.995 +# Exception in test solaris-sparc -client -server, no windows
448.996 +sun/security/pkcs11/KeyGenerator/TestKeyGenerator.java windows-all solaris-all
448.997 +
448.998 +# Do not seem to run on windows machines? dll missing?
448.999 +sun/security/pkcs11/KeyStore/Basic.sh windows-all
448.1000 +sun/security/pkcs11/KeyStore/ClientAuth.sh windows-all
448.1001 +
448.1002 +# Solaris sparc client, fails to compile?
448.1003 +sun/security/pkcs11/KeyStore/SecretKeysBasic.sh solaris-all
448.1004 +
448.1005 +# Do not seem to run on windows machines? dll missing?
448.1006 +sun/security/pkcs11/Mac/ReinitMac.java windows-all
448.1007 +sun/security/pkcs11/MessageDigest/ByteBuffers.java windows-all
448.1008 +sun/security/pkcs11/MessageDigest/DigestKAT.java windows-all
448.1009 +sun/security/pkcs11/MessageDigest/ReinitDigest.java windows-all
448.1010 +sun/security/pkcs11/Provider/ConfigQuotedString.sh windows-all
448.1011 +sun/security/pkcs11/Provider/Login.sh windows-all
448.1012 +sun/security/pkcs11/rsa/KeyWrap.java windows-all
448.1013 +sun/security/pkcs11/rsa/TestCACerts.java windows-all
448.1014 +sun/security/pkcs11/rsa/TestKeyFactory.java windows-all
448.1015 +sun/security/pkcs11/rsa/TestSignatures.java windows-all
448.1016 +sun/security/pkcs11/SampleTest.java windows-all
448.1017 +sun/security/pkcs11/Secmod/AddPrivateKey.java windows-all
448.1018 +sun/security/pkcs11/Secmod/AddTrustedCert.java windows-all
448.1019 +sun/security/pkcs11/Secmod/Crypto.java windows-all
448.1020 +sun/security/pkcs11/Secmod/GetPrivateKey.java windows-all
448.1021 +sun/security/pkcs11/Secmod/JksSetPrivateKey.java windows-all
448.1022 +sun/security/pkcs11/Secmod/TrustAnchors.java windows-all
448.1023 +sun/security/pkcs11/SecureRandom/Basic.java windows-all
448.1024 +sun/security/pkcs11/Serialize/SerializeProvider.java windows-all
448.1025 +sun/security/pkcs11/Signature/ByteBuffers.java windows-all
448.1026 +sun/security/pkcs11/Signature/ReinitSignature.java windows-all
448.1027 +sun/security/pkcs11/Signature/TestDSA.java windows-all
448.1028 +sun/security/pkcs11/tls/TestKeyMaterial.java windows-all
448.1029 +sun/security/pkcs11/tls/TestMasterSecret.java windows-all
448.1030 +sun/security/pkcs11/tls/TestPremaster.java windows-all
448.1031 +sun/security/pkcs11/tls/TestPRF.java windows-all
448.1032 +
448.1033 +# Fails on OpenSolaris java.net.BindException: Address already in use
448.1034 +sun/security/pkcs11/sslecc/ClientJSSEServerJSSE.java generic-all
448.1035 +
448.1036 +# Timeout on solaris-sparcv9 or ArrayIndexOutOfBoundsException?
448.1037 +sun/security/rsa/TestKeyPairGeneratorLength.java solaris-all
448.1038 +sun/security/rsa/TestSignatures.java solaris-all
448.1039 +
448.1040 +# Timeout on solaris-sparc and i586 and x64, -client and -server
448.1041 +sun/security/ssl/com/sun/net/ssl/internal/ssl/InputRecord/InterruptedIO.java solaris-all
448.1042 +
448.1043 +# Do not seem to run on windows machines? dll missing?
448.1044 +sun/security/tools/jarsigner/emptymanifest.sh windows-all
448.1045 +
448.1046 +# Files does not exist or no encoding? solaris-sparcv9
448.1047 +sun/security/tools/keytool/importreadall.sh solaris-all
448.1048 +sun/security/tools/keytool/selfissued.sh solaris-all
448.1049 +
448.1050 +############################################################################
448.1051 +
448.1052 +# jdk_swing (not using samevm)
448.1053 +
448.1054 +# Fails on solaris 10 sparc, throws RuntimeException that just says "failed"
448.1055 +javax/swing/JLabel/6501991/bug6501991.java generic-all
448.1056 +
448.1057 +# Fails on solaris 11 i586, with othervm
448.1058 +javax/swing/JFileChooser/6570445/bug6570445.java generic-all
448.1059 +javax/swing/JFileChooser/6738668/bug6738668.java generic-all
448.1060 +javax/swing/JPopupMenu/6675802/bug6675802.java generic-all
448.1061 +javax/swing/system/6799345/TestShutdown.java generic-all
448.1062 +
448.1063 +############################################################################
448.1064 +
448.1065 +# jdk_text
448.1066 +
448.1067 +# Linux x64 occasional errors, no details
448.1068 +java/text/Bidi/Bug6665028.java linux-x64
448.1069 +
448.1070 +############################################################################
448.1071 +
448.1072 +# jdk_tools
448.1073 +
448.1074 +# Some of the tools tests kind of require "othervm" or if they don't will
448.1075 +# always be firing up another VM anyway due to the nature of tools testing.
448.1076 +# So most if not all tools tests are now being run with "othervm" mode.
448.1077 +# Some of these tools tests have a tendency to use fixed ports, bad idea.
448.1078 +
448.1079 +# Solaris 10 client x86, java.lang.IndexOutOfBoundsException resumer Interrupted
448.1080 +com/sun/jdi/SimulResumerTest.java generic-all
448.1081 +
448.1082 +# Output of jps differs from expected output.
448.1083 +# Invalid argument count on solaris-sparc and x64
448.1084 +sun/tools/jstatd/jstatdPort.sh generic-all
448.1085 +
448.1086 +# othervm mode, Could not synchronize with target
448.1087 +sun/tools/jps/jps-l_1.sh generic-all
448.1088 +sun/tools/jps/jps-l_2.sh generic-all
448.1089 +sun/tools/jps/jps-lm.sh generic-all
448.1090 +sun/tools/jps/jps-Vvml_2.sh generic-all
448.1091 +sun/tools/jps/jps-m_2.sh generic-all
448.1092 +
448.1093 +# Server name error, port 2098 problem?
448.1094 +sun/tools/jstatd/jstatdServerName.sh generic-all
448.1095 +
448.1096 +# Solaris, handshake failed, othervm mode
448.1097 +com/sun/jdi/RedefineException.sh generic-all
448.1098 +
448.1099 +# These tests fail on solaris sparc, all the time
448.1100 +com/sun/servicetag/DeleteServiceTag.java generic-all
448.1101 +com/sun/servicetag/DuplicateNotFound.java generic-all
448.1102 +com/sun/servicetag/FindServiceTags.java generic-all
448.1103 +com/sun/servicetag/InstanceUrnCheck.java generic-all
448.1104 +com/sun/servicetag/InvalidRegistrationData.java generic-all
448.1105 +com/sun/servicetag/InvalidServiceTag.java generic-all
448.1106 +com/sun/servicetag/JavaServiceTagTest.java generic-all
448.1107 +com/sun/servicetag/JavaServiceTagTest1.java generic-all
448.1108 +com/sun/servicetag/NewRegistrationData.java generic-all
448.1109 +com/sun/servicetag/SystemRegistryTest.java generic-all
448.1110 +com/sun/servicetag/TestLoadFromXML.java generic-all
448.1111 +com/sun/servicetag/UpdateServiceTagTest.java generic-all
448.1112 +com/sun/servicetag/ValidRegistrationData.java generic-all
448.1113 +
448.1114 +# Problems on windows, jmap.exe hangs?
448.1115 +com/sun/tools/attach/BasicTests.sh windows-all
448.1116 +
448.1117 +# Fails on Solaris 10 sparc, in othervm mode, throws unexpected exception
448.1118 +sun/jvmstat/monitor/MonitoredVm/CR6672135.java generic-all
448.1119 +
448.1120 +# Unexpected Monitor Exception, solaris sparc -client
448.1121 +sun/jvmstat/monitor/MonitoredVm/MonitorVmStartTerminate.sh generic-all
448.1122 +
448.1123 +# Probably should be samevm, but seem to cause errors even in othervm at times
448.1124 +sun/tools/jhat/HatHeapDump1Test.java generic-all
448.1125 +
448.1126 +# Problems on windows, jmap.exe hangs? (these run jmap)
448.1127 +sun/tools/jmap/Basic.sh windows-all
448.1128 +
448.1129 +# Invalid argument count on solaris-sparc and x64
448.1130 +sun/tools/jstatd/jstatdDefaults.sh solaris-all
448.1131 +
448.1132 +# Solaris sparcv9, jps output does not match, x64 different
448.1133 +sun/tools/jstatd/jstatdExternalRegistry.sh solaris-all
448.1134 +
448.1135 +# Probably should be samevm, but seem to cause errors even in othervm at times
448.1136 +sun/tools/native2ascii/NativeErrors.java generic-all
448.1137 +
448.1138 +# Solaris 10 sparc 32bit -client, java.lang.AssertionError: Some tests failed
448.1139 +tools/jar/JarEntryTime.java generic-all
448.1140 +
448.1141 +# Times out on sparc?
448.1142 +tools/launcher/VersionCheck.java generic-all
448.1143 +
448.1144 +# These tests fail on solaris sparc, all the time
448.1145 +tools/jar/ChangeDir.java generic-all
448.1146 +
448.1147 +# Cannot write jar
448.1148 +# Also, possible problems on windows, jmap.exe hangs?
448.1149 +tools/jar/index/MetaInf.java windows-all
448.1150 +
448.1151 +############################################################################
448.1152 +
448.1153 +# jdk_util
448.1154 +
448.1155 +# Assert error, failures, on Linux Fedora 9 -server
448.1156 +# Windows samevm failure, assert error "Passed = 134, failed = 2"
448.1157 +java/util/Arrays/ArrayObjectMethods.java generic-all
448.1158 +
448.1159 +# Windows 2000, -client, samevm, java.lang.Error: Completed != 2
448.1160 +java/util/concurrent/locks/ReentrantLock/CancelledLockLoops.java generic-all
448.1161 +
448.1162 +# Windows X64, Executor Stuck samevm mode:
448.1163 +java/util/concurrent/FutureTask/BlockingTaskExecutor.java generic-all
448.1164 +
448.1165 +# Problems on windows, jmap.exe hangs? (these run jmap), fails on Solaris 10 x86
448.1166 +java/util/concurrent/locks/Lock/TimedAcquireLeak.java generic-all
448.1167 +
448.1168 +# Solaris sparc client, some failures, "1 not equal to 3"?
448.1169 +# also Linux problems with samevm mode, -server linux i586? 1 not equal to 3?
448.1170 +java/util/concurrent/Executors/AutoShutdown.java generic-all
448.1171 +
448.1172 +# Fails on solaris-sparc -server (Set not equal to copy. 1)
448.1173 +java/util/EnumSet/EnumSetBash.java solaris-sparc
448.1174 +
448.1175 +# Failing to close an input stream? "foo", triggers samevm windows failures
448.1176 +java/util/Formatter/Constructors.java generic-all
448.1177 +
448.1178 +# Need to be marked othervm, or changed to be samevm safe
448.1179 +java/util/Locale/Bug4175998Test.java generic-all
448.1180 +java/util/Locale/Bug4184873Test.java generic-all
448.1181 +java/util/Locale/LocaleTest.java generic-all
448.1182 +
448.1183 +# Need to be marked othervm, or changed to be samevm safe
448.1184 +java/util/logging/GetGlobalTest.java generic-all
448.1185 +java/util/logging/LoggerSubclass.java generic-all
448.1186 +java/util/logging/LoggingDeadlock.java generic-all
448.1187 +java/util/logging/LoggingDeadlock2.java generic-all
448.1188 +java/util/logging/LoggingMXBeanTest.java generic-all
448.1189 +java/util/logging/LoggingMXBeanTest2.java generic-all
448.1190 +java/util/logging/LoggingNIOChange.java generic-all
448.1191 +java/util/logging/ParentLoggersTest.java generic-all
448.1192 +
448.1193 +# Need to be marked othervm, or changed to be samevm safe
448.1194 +java/util/ResourceBundle/Bug4168625Test.java generic-all
448.1195 +java/util/ResourceBundle/Bug6359330.java generic-all
448.1196 +java/util/ResourceBundle/TestBug4179766.java generic-all
448.1197 +
448.1198 +# Need to be marked othervm, or changed to be samevm safe
448.1199 +java/util/WeakHashMap/GCDuringIteration.java generic-all
448.1200 +
448.1201 +# Possible missing input stream close()? Causes samevm issues on windows
448.1202 +java/util/zip/InfoZip.java generic-all
448.1203 +
448.1204 +# Missing a close() on file Test0.zip? windows samevm cascade problem
448.1205 +java/util/zip/ZipFile/Comment.java generic-all
448.1206 +
448.1207 +# Suspect missing close() on bad*.zip files, windows cascade errors with samevm
448.1208 +java/util/zip/ZipFile/CorruptedZipFiles.java generic-all
448.1209 +
448.1210 +# Should be samevm but causes problems with samevm, no details:
448.1211 +java/util/zip/ZipFile/ManyEntries.java generic-all
448.1212 +
448.1213 +############################################################################
448.1214 +
449.1 --- a/test/com/sun/jdi/ShellScaffold.sh Mon Nov 23 10:04:47 2009 +0000
449.2 +++ b/test/com/sun/jdi/ShellScaffold.sh Wed Nov 25 11:08:25 2009 -0800
449.3 @@ -307,7 +307,7 @@
449.4 #The alternative would be to use /usr/bin/pargs [pid] to get
449.5 #all the args for a process, splice them back into one
449.6 #long string, then grep.
449.7 - UU=`/usr/bin/id -un`
449.8 + UU=`/usr/xpg4/bin/id -u -n`
449.9 psCmd="pgrep -f -l -U $UU"
449.10 else
449.11 ulimit -c 0
450.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
450.2 +++ b/test/com/sun/management/HotSpotDiagnosticMXBean/SetAllVMOptions.java Wed Nov 25 11:08:25 2009 -0800
450.3 @@ -0,0 +1,65 @@
450.4 +/*
450.5 + * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
450.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
450.7 + *
450.8 + * This code is free software; you can redistribute it and/or modify it
450.9 + * under the terms of the GNU General Public License version 2 only, as
450.10 + * published by the Free Software Foundation.
450.11 + *
450.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
450.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
450.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
450.15 + * version 2 for more details (a copy is included in the LICENSE file that
450.16 + * accompanied this code).
450.17 + *
450.18 + * You should have received a copy of the GNU General Public License version
450.19 + * 2 along with this work; if not, write to the Free Software Foundation,
450.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
450.21 + *
450.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
450.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
450.24 + * have any questions.
450.25 + */
450.26 +
450.27 +/*
450.28 + * @test
450.29 + * @bug 6858708
450.30 + * @summary Basic Test for HotSpotDiagnosticMXBean.setVMOption()
450.31 + * @author Tomas Hurka, Daniel Fuchs
450.32 + *
450.33 + * @run main SetAllVMOptions
450.34 + */
450.35 +
450.36 +import com.sun.management.HotSpotDiagnosticMXBean;
450.37 +import com.sun.management.VMOption;
450.38 +import java.lang.management.ManagementFactory;
450.39 +import java.util.List;
450.40 +import javax.management.MBeanServer;
450.41 +
450.42 +public class SetAllVMOptions {
450.43 + private static String HOTSPOT_DIAGNOSTIC_MXBEAN_NAME =
450.44 + "com.sun.management:type=HotSpotDiagnostic";
450.45 +
450.46 + public static void main(String[] args) throws Exception {
450.47 + List<HotSpotDiagnosticMXBean> list =
450.48 + ManagementFactory.getPlatformMXBeans(HotSpotDiagnosticMXBean.class);
450.49 + HotSpotDiagnosticMXBean mbean = list.get(0);
450.50 + setAllVMOptions(mbean);
450.51 +
450.52 + MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
450.53 + mbean = ManagementFactory.newPlatformMXBeanProxy(mbs,
450.54 + HOTSPOT_DIAGNOSTIC_MXBEAN_NAME,
450.55 + HotSpotDiagnosticMXBean.class);
450.56 + setAllVMOptions(mbean);
450.57 + }
450.58 +
450.59 + private static void setAllVMOptions(HotSpotDiagnosticMXBean mbean) {
450.60 + List<VMOption> options = mbean.getDiagnosticOptions();
450.61 + for (VMOption opt : options) {
450.62 + String name = opt.getName();
450.63 + String val = opt.getValue();
450.64 + System.out.println("option: "+name+"="+val);
450.65 + mbean.setVMOption(name,val);
450.66 + }
450.67 + }
450.68 +}
451.1 --- a/test/demo/jvmti/DemoRun.java Mon Nov 23 10:04:47 2009 +0000
451.2 +++ b/test/demo/jvmti/DemoRun.java Wed Nov 25 11:08:25 2009 -0800
451.3 @@ -145,7 +145,7 @@
451.4 */
451.5 int nvm_options = 0;
451.6 if ( vm_options != null ) nvm_options = vm_options.length;
451.7 - String cmd[] = new String[1 + (d64?1:0) + 5 + nvm_options];
451.8 + String cmd[] = new String[1 + (d64?1:0) + 7 + nvm_options];
451.9 String cmdLine;
451.10 int exitStatus;
451.11 int i,j;
451.12 @@ -154,6 +154,10 @@
451.13 cmdLine = "";
451.14 cmdLine += (cmd[i++] = java);
451.15 cmdLine += " ";
451.16 + cmdLine += (cmd[i++] = "-cp");
451.17 + cmdLine += " ";
451.18 + cmdLine += (cmd[i++] = cdir);
451.19 + cmdLine += " ";
451.20 cmdLine += (cmd[i++] = "-Dtest.classes=" + cdir);
451.21 if ( d64 ) {
451.22 cmdLine += " ";
452.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
452.2 +++ b/test/java/awt/Container/ValidateRoot/InvalidateMustRespectValidateRoots.java Wed Nov 25 11:08:25 2009 -0800
452.3 @@ -0,0 +1,114 @@
452.4 +/*
452.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
452.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
452.7 + *
452.8 + * This code is free software; you can redistribute it and/or modify it
452.9 + * under the terms of the GNU General Public License version 2 only, as
452.10 + * published by the Free Software Foundation.
452.11 + *
452.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
452.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
452.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
452.15 + * version 2 for more details (a copy is included in the LICENSE file that
452.16 + * accompanied this code).
452.17 + *
452.18 + * You should have received a copy of the GNU General Public License version
452.19 + * 2 along with this work; if not, write to the Free Software Foundation,
452.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
452.21 + *
452.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
452.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
452.24 + * have any questions.
452.25 + */
452.26 +
452.27 +/*
452.28 + @test
452.29 + @bug 6852592
452.30 + @summary invalidate() must stop when it encounters a validate root
452.31 + @author anthony.petrov@sun.com
452.32 + @run main InvalidateMustRespectValidateRoots
452.33 +*/
452.34 +
452.35 +import javax.swing.*;
452.36 +import java.awt.event.*;
452.37 +
452.38 +public class InvalidateMustRespectValidateRoots {
452.39 + private static volatile JRootPane rootPane;
452.40 +
452.41 + public static void main(String args[]) throws Exception {
452.42 + SwingUtilities.invokeAndWait(new Runnable() {
452.43 + public void run() {
452.44 + // The JRootPane is a validate root. We'll check if
452.45 + // invalidate() stops on the root pane, or goes further
452.46 + // up to the frame.
452.47 + JFrame frame = new JFrame();
452.48 + final JButton button = new JButton();
452.49 +
452.50 + frame.add(button);
452.51 +
452.52 + // To enable running the test manually: use the Ctrl-Shift-F1
452.53 + // to print the component hierarchy to the console
452.54 + button.addActionListener(new ActionListener() {
452.55 + public void actionPerformed(ActionEvent ev) {
452.56 + if (button.isValid()) {
452.57 + button.invalidate();
452.58 + } else {
452.59 + button.revalidate();
452.60 + }
452.61 + }
452.62 + });
452.63 +
452.64 + rootPane = frame.getRootPane();
452.65 +
452.66 + // Now the component hierarchy looks like:
452.67 + // frame
452.68 + // --> rootPane
452.69 + // --> layered pane
452.70 + // --> content pane
452.71 + // --> button
452.72 +
452.73 + // Make all components valid first via showing the frame
452.74 + // We have to make the frame visible. Otherwise revalidate() is
452.75 + // useless (see RepaintManager.addInvalidComponent()).
452.76 + frame.pack(); // To enable running this test manually
452.77 + frame.setVisible(true);
452.78 +
452.79 + if (!frame.isValid()) {
452.80 + throw new RuntimeException(
452.81 + "setVisible(true) failed to validate the frame");
452.82 + }
452.83 +
452.84 + // Now invalidate the button
452.85 + button.invalidate();
452.86 +
452.87 + // Check if the 'valid' status is what we expect it to be
452.88 + if (rootPane.isValid()) {
452.89 + throw new RuntimeException(
452.90 + "invalidate() failed to invalidate the root pane");
452.91 + }
452.92 +
452.93 + if (!frame.isValid()) {
452.94 + throw new RuntimeException(
452.95 + "invalidate() invalidated the frame");
452.96 + }
452.97 +
452.98 + // Now validate the hierarchy again
452.99 + button.revalidate();
452.100 +
452.101 + // Now let the validation happen on the EDT
452.102 + }
452.103 + });
452.104 +
452.105 + Thread.sleep(1000);
452.106 +
452.107 + SwingUtilities.invokeAndWait(new Runnable() {
452.108 + public void run() {
452.109 + // Check if the root pane finally became valid
452.110 + if (!rootPane.isValid()) {
452.111 + throw new RuntimeException(
452.112 + "revalidate() failed to validate the hierarchy");
452.113 + }
452.114 + }
452.115 + });
452.116 + }
452.117 +}
453.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
453.2 +++ b/test/java/awt/GraphicsDevice/CloneConfigsTest.java Wed Nov 25 11:08:25 2009 -0800
453.3 @@ -0,0 +1,118 @@
453.4 +/*
453.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
453.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
453.7 + *
453.8 + * This code is free software; you can redistribute it and/or modify it
453.9 + * under the terms of the GNU General Public License version 2 only, as
453.10 + * published by the Free Software Foundation.
453.11 + *
453.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
453.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
453.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
453.15 + * version 2 for more details (a copy is included in the LICENSE file that
453.16 + * accompanied this code).
453.17 + *
453.18 + * You should have received a copy of the GNU General Public License version
453.19 + * 2 along with this work; if not, write to the Free Software Foundation,
453.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
453.21 + *
453.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
453.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
453.24 + * have any questions.
453.25 + */
453.26 +
453.27 +/*
453.28 + * @test
453.29 + * @bug 6822057
453.30 + *
453.31 + * @summary Test verifies that list of supported graphics configurations
453.32 + * can not be changed via modification of elements of an array
453.33 + * returned by getConfiguration() method.
453.34 + *
453.35 + * @run main CloneConfigsTest
453.36 + * @run main/othervm -Dsun.java2d.opengl=True CloneConfigsTest
453.37 + * @run main/othervm -Dsun.java2d.d3d=true CloneConfigsTest
453.38 + * @run main/othervm -Dsun.java2d.noddraw=true CloneConfigsTest
453.39 + */
453.40 +
453.41 +import java.awt.GraphicsConfiguration;
453.42 +import java.awt.GraphicsDevice;
453.43 +import java.awt.GraphicsEnvironment;
453.44 +import java.awt.Rectangle;
453.45 +import java.awt.geom.AffineTransform;
453.46 +import java.awt.image.BufferedImage;
453.47 +import java.awt.image.ColorModel;
453.48 +
453.49 +public class CloneConfigsTest {
453.50 +
453.51 + public static void main(String[] args) {
453.52 + GraphicsEnvironment env =
453.53 + GraphicsEnvironment.getLocalGraphicsEnvironment();
453.54 +
453.55 + GraphicsDevice[] devices = env.getScreenDevices();
453.56 +
453.57 + GraphicsConfiguration c = new TestConfig();
453.58 +
453.59 + for (GraphicsDevice gd : devices) {
453.60 + System.out.println("Device: " + gd);
453.61 +
453.62 + GraphicsConfiguration[] configs = gd.getConfigurations();
453.63 +
453.64 + for (int i = 0; i < configs.length; i++) {
453.65 + GraphicsConfiguration gc = configs[i];
453.66 + System.out.println("\tConfig: " + gc);
453.67 +
453.68 + configs[i] = c;
453.69 + }
453.70 +
453.71 + // verify whether array of configs was modified
453.72 + configs = gd.getConfigurations();
453.73 + for (GraphicsConfiguration gc : configs) {
453.74 + if (gc == c) {
453.75 + throw new RuntimeException("Test failed.");
453.76 + }
453.77 + }
453.78 + System.out.println("Test passed.");
453.79 + }
453.80 + }
453.81 +
453.82 + private static class TestConfig extends GraphicsConfiguration {
453.83 +
453.84 + @Override
453.85 + public GraphicsDevice getDevice() {
453.86 + throw new UnsupportedOperationException("Not supported yet.");
453.87 + }
453.88 +
453.89 + @Override
453.90 + public BufferedImage createCompatibleImage(int width, int height) {
453.91 + throw new UnsupportedOperationException("Not supported yet.");
453.92 + }
453.93 +
453.94 + @Override
453.95 + public ColorModel getColorModel() {
453.96 + throw new UnsupportedOperationException("Not supported yet.");
453.97 + }
453.98 +
453.99 + @Override
453.100 + public ColorModel getColorModel(int transparency) {
453.101 + throw new UnsupportedOperationException("Not supported yet.");
453.102 + }
453.103 +
453.104 + @Override
453.105 + public AffineTransform getDefaultTransform() {
453.106 + throw new UnsupportedOperationException("Not supported yet.");
453.107 + }
453.108 +
453.109 + @Override
453.110 + public AffineTransform getNormalizingTransform() {
453.111 + throw new UnsupportedOperationException("Not supported yet.");
453.112 + }
453.113 +
453.114 + @Override
453.115 + public Rectangle getBounds() {
453.116 + throw new UnsupportedOperationException("Not supported yet.");
453.117 + }
453.118 +
453.119 + }
453.120 +
453.121 +}
454.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
454.2 +++ b/test/java/awt/event/InvocationEvent/InvocationEventTest.java Wed Nov 25 11:08:25 2009 -0800
454.3 @@ -0,0 +1,68 @@
454.4 +/*
454.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
454.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
454.7 + *
454.8 + * This code is free software; you can redistribute it and/or modify it
454.9 + * under the terms of the GNU General Public License version 2 only, as
454.10 + * published by the Free Software Foundation.
454.11 + *
454.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
454.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
454.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
454.15 + * version 2 for more details (a copy is included in the LICENSE file that
454.16 + * accompanied this code).
454.17 + *
454.18 + * You should have received a copy of the GNU General Public License version
454.19 + * 2 along with this work; if not, write to the Free Software Foundation,
454.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
454.21 + *
454.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
454.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
454.24 + * have any questions.
454.25 + */
454.26 +
454.27 +/*
454.28 + @test
454.29 + @bug 6852111
454.30 + @summary Unhandled 'spurious wakeup' in java.awt.EventQueue.invokeAndWait()
454.31 + @author dmitry.cherepanov@sun.com: area=awt.event
454.32 + @run main InvocationEventTest
454.33 +*/
454.34 +
454.35 +/**
454.36 + * InvocationEventTest.java
454.37 + *
454.38 + * summary: Tests new isDispatched method of the InvocationEvent class
454.39 + */
454.40 +
454.41 +import java.awt.*;
454.42 +import java.awt.event.*;
454.43 +
454.44 +public class InvocationEventTest
454.45 +{
454.46 + public static void main(String []s) throws Exception
454.47 + {
454.48 + Toolkit tk = Toolkit.getDefaultToolkit();
454.49 + Runnable runnable = new Runnable() {
454.50 + public void run() {
454.51 + }
454.52 + };
454.53 + Object lock = new Object();
454.54 + InvocationEvent event = new InvocationEvent(tk, runnable, lock, true);
454.55 +
454.56 + if (event.isDispatched()) {
454.57 + throw new RuntimeException(" Initially, the event shouldn't be dispatched ");
454.58 + }
454.59 +
454.60 + synchronized(lock) {
454.61 + tk.getSystemEventQueue().postEvent(event);
454.62 + while(!event.isDispatched()) {
454.63 + lock.wait();
454.64 + }
454.65 + }
454.66 +
454.67 + if(!event.isDispatched()) {
454.68 + throw new RuntimeException(" Finally, the event should be dispatched ");
454.69 + }
454.70 + }
454.71 +}
455.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
455.2 +++ b/test/java/awt/font/NumericShaper/EqualsTest.java Wed Nov 25 11:08:25 2009 -0800
455.3 @@ -0,0 +1,65 @@
455.4 +/*
455.5 + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
455.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
455.7 + *
455.8 + * This code is free software; you can redistribute it and/or modify it
455.9 + * under the terms of the GNU General Public License version 2 only, as
455.10 + * published by the Free Software Foundation.
455.11 + *
455.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
455.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
455.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
455.15 + * version 2 for more details (a copy is included in the LICENSE file that
455.16 + * accompanied this code).
455.17 + *
455.18 + * You should have received a copy of the GNU General Public License version
455.19 + * 2 along with this work; if not, write to the Free Software Foundation,
455.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
455.21 + *
455.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
455.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
455.24 + * have any questions.
455.25 + */
455.26 +
455.27 +/*
455.28 + * @test
455.29 + * @bug 6842557
455.30 + * @summary confirm that an instance which is created with new Enum ranges is
455.31 + * equivalent to another instance which is created with equivalent traditional
455.32 + * ranges or the same Enum ranges.
455.33 + */
455.34 +
455.35 +import java.awt.font.NumericShaper;
455.36 +import java.util.EnumSet;
455.37 +import static java.awt.font.NumericShaper.*;
455.38 +
455.39 +public class EqualsTest {
455.40 + public static void main(String[] args) {
455.41 + NumericShaper ns1 = getContextualShaper(ARABIC | TAMIL, TAMIL);
455.42 + NumericShaper ns2 = getContextualShaper(
455.43 + EnumSet.of(Range.ARABIC, Range.TAMIL),
455.44 + Range.TAMIL);
455.45 + NumericShaper ns3 = getContextualShaper(
455.46 + EnumSet.of(Range.ARABIC, Range.TAMIL),
455.47 + Range.TAMIL);
455.48 + NumericShaper ns4 = getContextualShaper(
455.49 + EnumSet.of(Range.ARABIC, Range.TAMIL),
455.50 + Range.ARABIC);
455.51 +
455.52 + if (!ns1.equals(ns2)) {
455.53 + throw new RuntimeException("ns1 != ns2: ns1=" + ns1 + ", ns2=" + ns2);
455.54 + }
455.55 + if (!ns2.equals(ns1)) {
455.56 + throw new RuntimeException("ns2 != ns1: ns1=" + ns1 + ", ns2=" + ns2);
455.57 + }
455.58 + if (!ns2.equals(ns3)) {
455.59 + throw new RuntimeException("ns2 != ns3: ns2=" + ns2 + ", ns3=" + ns3);
455.60 + }
455.61 + if (ns1.equals(ns4)) {
455.62 + throw new RuntimeException("ns1 == ns4: ns1=" + ns1 + ", ns4=" + ns4);
455.63 + }
455.64 + if (ns2.equals(ns4)) {
455.65 + throw new RuntimeException("ns2 == ns4: ns2=" + ns2 + ", ns4=" + ns4);
455.66 + }
455.67 + }
455.68 +}
456.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
456.2 +++ b/test/java/awt/font/NumericShaper/MTTest.java Wed Nov 25 11:08:25 2009 -0800
456.3 @@ -0,0 +1,134 @@
456.4 +/*
456.5 + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
456.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
456.7 + *
456.8 + * This code is free software; you can redistribute it and/or modify it
456.9 + * under the terms of the GNU General Public License version 2 only, as
456.10 + * published by the Free Software Foundation.
456.11 + *
456.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
456.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
456.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
456.15 + * version 2 for more details (a copy is included in the LICENSE file that
456.16 + * accompanied this code).
456.17 + *
456.18 + * You should have received a copy of the GNU General Public License version
456.19 + * 2 along with this work; if not, write to the Free Software Foundation,
456.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
456.21 + *
456.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
456.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
456.24 + * have any questions.
456.25 + */
456.26 +
456.27 +/*
456.28 + * @test
456.29 + * @bug 6843181
456.30 + * @summary Confirm that NumericShaper is thread-safe.
456.31 + * @run main/timeout=300/othervm MTTest
456.32 + */
456.33 +
456.34 +import java.awt.font.NumericShaper;
456.35 +import java.util.Arrays;
456.36 +import java.util.EnumSet;
456.37 +import static java.awt.font.NumericShaper.*;
456.38 +
456.39 +public class MTTest {
456.40 + static volatile boolean runrun = true;
456.41 + static volatile boolean err = false;
456.42 +
456.43 + final static String text = "-123 (English) 456.00 (Arabic) \u0641\u0642\u0643 -789 (Thai) \u0e01\u0e33 01.23";
456.44 + static char[] t1, t2;
456.45 + static NumericShaper ns1, ns2, ns3, ns4;
456.46 +
456.47 + public static void main(String[] args) {
456.48 + System.out.println(" original: " + text);
456.49 + ns1 = getContextualShaper(EnumSet.of(Range.ARABIC), Range.ARABIC);
456.50 + t1 = text.toCharArray();
456.51 + ns1.shape(t1, 0, t1.length);
456.52 + System.out.println("expected t1: " + String.valueOf(t1));
456.53 +
456.54 + ns2 = getContextualShaper(EnumSet.of(Range.THAI), Range.THAI);
456.55 + t2 = text.toCharArray();
456.56 + ns2.shape(t2, 0, t2.length);
456.57 + System.out.println("expected t2: " + String.valueOf(t2));
456.58 +
456.59 + ns3 = getContextualShaper(ARABIC, ARABIC);
456.60 + ns4 = getContextualShaper(THAI, THAI);
456.61 +
456.62 + Thread th1 = new Thread(new Work(ns1, t1));
456.63 + Thread th2 = new Thread(new Work(ns2, t2));
456.64 + Thread th3 = new Thread(new Work(ns1, t1));
456.65 + Thread th4 = new Thread(new Work(ns2, t2));
456.66 + Thread th5 = new Thread(new Work(ns3, t1));
456.67 + Thread th6 = new Thread(new Work(ns4, t2));
456.68 + Thread th7 = new Thread(new Work(ns3, t1));
456.69 + Thread th8 = new Thread(new Work(ns4, t2));
456.70 +
456.71 + th1.start();
456.72 + th2.start();
456.73 + th3.start();
456.74 + th4.start();
456.75 + th5.start();
456.76 + th6.start();
456.77 + th7.start();
456.78 + th8.start();
456.79 +
456.80 + try {
456.81 + for (int i = 0; runrun && i < 180; i++) {
456.82 + Thread.sleep(1000); // 1 seconds
456.83 + }
456.84 + runrun = false;
456.85 + th1.join();
456.86 + th2.join();
456.87 + th3.join();
456.88 + th4.join();
456.89 + th5.join();
456.90 + th6.join();
456.91 + th7.join();
456.92 + th8.join();
456.93 + }
456.94 + catch (InterruptedException e) {
456.95 + }
456.96 +
456.97 + if (err) {
456.98 + throw new RuntimeException("Thread-safe test failed.");
456.99 + }
456.100 + }
456.101 +
456.102 + private static class Work implements Runnable {
456.103 + NumericShaper ns;
456.104 + char[] expectedText;
456.105 +
456.106 + Work(NumericShaper ns, char[] expectedText) {
456.107 + this.ns = ns;
456.108 + this.expectedText = expectedText;
456.109 +
456.110 + }
456.111 +
456.112 + public void run() {
456.113 + int count = 0;
456.114 + while (runrun) {
456.115 + char[] t = text.toCharArray();
456.116 + try {
456.117 + count++;
456.118 + ns.shape(t, 0, t.length);
456.119 + } catch (Exception e) {
456.120 + System.err.println("Error: Unexpected exception: " + e);
456.121 + runrun = false;
456.122 + err = true;
456.123 + return;
456.124 + }
456.125 + if (!Arrays.equals(t, expectedText)) {
456.126 + System.err.println("Error: shape() returned unexpected value: ");
456.127 + System.err.println("count = " + count);
456.128 + System.err.println(" expected: " + String.valueOf(expectedText));
456.129 + System.err.println(" got: " + String.valueOf(t));
456.130 + runrun = false;
456.131 + err = true;
456.132 + return;
456.133 + }
456.134 + }
456.135 + }
456.136 + }
456.137 +}
457.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
457.2 +++ b/test/java/awt/font/NumericShaper/ShapingTest.java Wed Nov 25 11:08:25 2009 -0800
457.3 @@ -0,0 +1,105 @@
457.4 +/*
457.5 + * Copyright (c) 2009 Sun Microsystems, Inc. All Rights Reserved.
457.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
457.7 + *
457.8 + * This code is free software; you can redistribute it and/or modify it
457.9 + * under the terms of the GNU General Public License version 2 only, as
457.10 + * published by the Free Software Foundation.
457.11 + *
457.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
457.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
457.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
457.15 + * version 2 for more details (a copy is included in the LICENSE file that
457.16 + * accompanied this code).
457.17 + *
457.18 + * You should have received a copy of the GNU General Public License version
457.19 + * 2 along with this work; if not, write to the Free Software Foundation,
457.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
457.21 + *
457.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
457.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
457.24 + * have any questions.
457.25 + */
457.26 +
457.27 +/*
457.28 + * @test
457.29 + * @bug 6842557
457.30 + * @summary confirm that shaping works as expected. (Mainly for new characters which were added in Unicode 5)
457.31 + * used where appropriate.
457.32 + */
457.33 +
457.34 +import java.awt.font.NumericShaper;
457.35 +import java.util.EnumSet;
457.36 +import static java.awt.font.NumericShaper.*;
457.37 +
457.38 +public class ShapingTest {
457.39 + public static void main(String[] args) {
457.40 + NumericShaper ns_old = getContextualShaper(ARABIC | TAMIL | ETHIOPIC,
457.41 + EUROPEAN);
457.42 + NumericShaper ns_new = getContextualShaper(EnumSet.of(
457.43 + Range.ARABIC, Range.TAMIL, Range.ETHIOPIC),
457.44 + Range.EUROPEAN);
457.45 +
457.46 + boolean err = false;
457.47 +
457.48 + String[][] data = {
457.49 + // Arabic "October 10"
457.50 + {"\u0623\u0643\u062a\u0648\u0628\u0631 10",
457.51 + "\u0623\u0643\u062a\u0648\u0628\u0631 \u0661\u0660"},
457.52 +
457.53 + // Tamil "Year 2009"
457.54 + {"\u0b86\u0ba3\u0bcd\u0b9f\u0bc1 2009",
457.55 + "\u0b86\u0ba3\u0bcd\u0b9f\u0bc1 \u0be8\u0be6\u0be6\u0bef"},
457.56 + // "\u0be800\u0bef is returned by pre-JDK7 because Tamil zero was not
457.57 + // included in Unicode 4.0.0.
457.58 +
457.59 + // Ethiopic "Syllable<HA> 2009"
457.60 + {"\u1200 2009",
457.61 + "\u1200 \u136a00\u1371"},
457.62 + // Ethiopic zero doesn't exist even in Unicode 5.1.0.
457.63 + };
457.64 +
457.65 + for (int i = 0; i < data.length; i++) {
457.66 + String expected = data[i][1];
457.67 +
457.68 + char[] text = data[i][0].toCharArray();
457.69 + ns_old.shape(text, 0, text.length);
457.70 + String got = new String(text);
457.71 +
457.72 + if (!expected.equals(got)) {
457.73 + err = true;
457.74 + System.err.println("Error with traditional range.");
457.75 + System.err.println(" text = " + data[i][0]);
457.76 + System.err.println(" got = " + got);
457.77 + System.err.println(" expected = " + expected);
457.78 + } else {
457.79 + System.err.println("OK with traditional range.");
457.80 + System.err.println(" text = " + data[i][0]);
457.81 + System.err.println(" got = " + got);
457.82 + System.err.println(" expected = " + expected);
457.83 + }
457.84 +
457.85 + text = data[i][0].toCharArray();
457.86 + ns_new.shape(text, 0, text.length);
457.87 + got = new String(text);
457.88 +
457.89 + if (!expected.equals(got)) {
457.90 + err = true;
457.91 + System.err.println("Error with new Enum range.");
457.92 + System.err.println(" text = " + data[i][0]);
457.93 + System.err.println(" got = " + got);
457.94 + System.err.println(" expected = " + expected);
457.95 + } else {
457.96 + System.err.println("OK with new Enum range.");
457.97 + System.err.println(" text = " + data[i][0]);
457.98 + System.err.println(" got = " + got);
457.99 + System.err.println(" expected = " + expected);
457.100 + }
457.101 + }
457.102 +
457.103 + if (err) {
457.104 + throw new RuntimeException("shape() returned unexpected value.");
457.105 + }
457.106 + }
457.107 +
457.108 +}
458.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
458.2 +++ b/test/java/lang/ClassLoader/UninitializedParent.java Wed Nov 25 11:08:25 2009 -0800
458.3 @@ -0,0 +1,68 @@
458.4 +/*
458.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
458.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
458.7 + *
458.8 + * This code is free software; you can redistribute it and/or modify it
458.9 + * under the terms of the GNU General Public License version 2 only, as
458.10 + * published by the Free Software Foundation.
458.11 + *
458.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
458.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
458.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
458.15 + * version 2 for more details (a copy is included in the LICENSE file that
458.16 + * accompanied this code).
458.17 + *
458.18 + * You should have received a copy of the GNU General Public License version
458.19 + * 2 along with this work; if not, write to the Free Software Foundation,
458.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
458.21 + *
458.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
458.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
458.24 + * have any questions.
458.25 + */
458.26 +
458.27 +/*
458.28 + * @test
458.29 + * @bug 6636650
458.30 + * @summary Uninitialized class loaders should not be a parent of other
458.31 + * class loaders.
458.32 + */
458.33 +
458.34 +
458.35 +import java.net.*;
458.36 +
458.37 +public class UninitializedParent {
458.38 + private static ClassLoader loader;
458.39 + public static void main(String[] args) throws Exception {
458.40 + System.setSecurityManager(new SecurityManager());
458.41 +
458.42 + // Create an uninitialized class loader
458.43 + try {
458.44 + new ClassLoader(null) {
458.45 + @Override
458.46 + protected void finalize() {
458.47 + loader = this;
458.48 + }
458.49 + };
458.50 + } catch (SecurityException exc) {
458.51 + // Expected
458.52 + }
458.53 + System.gc();
458.54 + System.runFinalization();
458.55 +
458.56 + // if 'loader' isn't null, need to ensure that it can't be used as
458.57 + // parent
458.58 + if (loader != null) {
458.59 + try {
458.60 + // Create a class loader with 'loader' being the parent
458.61 + URLClassLoader child = URLClassLoader.newInstance
458.62 + (new URL[0], loader);
458.63 + throw new RuntimeException("Test Failed!");
458.64 + } catch (SecurityException se) {
458.65 + System.out.println("Test Passed: Exception thrown");
458.66 + }
458.67 + } else {
458.68 + System.out.println("Test Passed: Loader is null");
458.69 + }
458.70 + }
458.71 +}
459.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
459.2 +++ b/test/java/math/BigInteger/ExtremeShiftingTests.java Wed Nov 25 11:08:25 2009 -0800
459.3 @@ -0,0 +1,48 @@
459.4 +/*
459.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
459.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
459.7 + *
459.8 + * This code is free software; you can redistribute it and/or modify it
459.9 + * under the terms of the GNU General Public License version 2 only, as
459.10 + * published by the Free Software Foundation.
459.11 + *
459.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
459.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
459.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
459.15 + * version 2 for more details (a copy is included in the LICENSE file that
459.16 + * accompanied this code).
459.17 + *
459.18 + * You should have received a copy of the GNU General Public License version
459.19 + * 2 along with this work; if not, write to the Free Software Foundation,
459.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
459.21 + *
459.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
459.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
459.24 + * have any questions.
459.25 + */
459.26 +
459.27 +/*
459.28 + * @test
459.29 + * @bug 6371401
459.30 + * @summary Tests of shiftLeft and shiftRight on Integer.MIN_VALUE
459.31 + * @author Joseph D. Darcy
459.32 + */
459.33 +import static java.math.BigInteger.*;
459.34 +
459.35 +public class ExtremeShiftingTests {
459.36 + public static void main(String... args) {
459.37 + try {
459.38 + ONE.shiftLeft(Integer.MIN_VALUE);
459.39 + throw new RuntimeException("Should not reach here.");
459.40 + } catch (ArithmeticException ae) {
459.41 + ; // Expected
459.42 + }
459.43 +
459.44 + try {
459.45 + ONE.shiftRight(Integer.MIN_VALUE);
459.46 + throw new RuntimeException("Should not reach here.");
459.47 + } catch (ArithmeticException ae) {
459.48 + ; // Expected
459.49 + }
459.50 + }
459.51 +}
460.1 --- a/test/java/net/CookieHandler/B6644726.java Mon Nov 23 10:04:47 2009 +0000
460.2 +++ b/test/java/net/CookieHandler/B6644726.java Wed Nov 25 11:08:25 2009 -0800
460.3 @@ -23,7 +23,7 @@
460.4
460.5 /*
460.6 * @test
460.7 - * @bug 6644726
460.8 + * @bug 6644726 6873543
460.9 * @summary Cookie management issues
460.10 */
460.11
460.12 @@ -170,6 +170,28 @@
460.13 if (isIn(clst, "myCookie8=")) {
460.14 fail("A cookie with an invalid port list was returned");
460.15 }
460.16 +
460.17 + // Test httpOnly flag (CR# 6873543)
460.18 + lst.clear();
460.19 + map.clear();
460.20 + cm.getCookieStore().removeAll();
460.21 + lst.add("myCookie11=httpOnlyTest; httpOnly");
460.22 + map.put("Set-Cookie", lst);
460.23 + uri = new URI("http://www.sun.com/");
460.24 + cm.put(uri, map);
460.25 + m = cm.get(uri, emptyMap);
460.26 + clst = m.get("Cookie");
460.27 + // URI scheme was http: so we should get the cookie
460.28 + if (!isIn(clst, "myCookie11=")) {
460.29 + fail("Missing cookie with httpOnly flag");
460.30 + }
460.31 + uri = new URI("javascript://www.sun.com/");
460.32 + m = cm.get(uri, emptyMap);
460.33 + clst = m.get("Cookie");
460.34 + // URI scheme was neither http or https so we shouldn't get the cookie
460.35 + if (isIn(clst, "myCookie11=")) {
460.36 + fail("Should get the cookie with httpOnly when scheme is javascript:");
460.37 + }
460.38 }
460.39
460.40 private static boolean isIn(List<String> lst, String cookie) {
461.1 --- a/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java Mon Nov 23 10:04:47 2009 +0000
461.2 +++ b/test/java/nio/channels/AsynchronousChannelGroup/Unbounded.java Wed Nov 25 11:08:25 2009 -0800
461.3 @@ -34,7 +34,7 @@
461.4
461.5 public class Unbounded {
461.6 // number of concurrent completion handlers
461.7 - static final int CONCURRENCY_COUNT = 512;
461.8 + static final int CONCURRENCY_COUNT = 256;
461.9
461.10 public static void main(String[] args) throws Exception {
461.11 // all accepted connections are added to a queue
462.1 --- a/test/java/nio/channels/DatagramChannel/NetworkConfiguration.java Mon Nov 23 10:04:47 2009 +0000
462.2 +++ b/test/java/nio/channels/DatagramChannel/NetworkConfiguration.java Wed Nov 25 11:08:25 2009 -0800
462.3 @@ -73,22 +73,22 @@
462.4
462.5 List<InetAddress> addrs = Collections.list(nif.getInetAddresses());
462.6 for (InetAddress addr: addrs) {
462.7 - if (addr instanceof Inet4Address) {
462.8 - List<InetAddress> list = ip4Interfaces.get(nif);
462.9 - if (list == null) {
462.10 - list = new LinkedList<InetAddress>();
462.11 + if (!addr.isAnyLocalAddress()) {
462.12 + if (addr instanceof Inet4Address) {
462.13 + List<InetAddress> list = ip4Interfaces.get(nif);
462.14 + if (list == null) {
462.15 + list = new LinkedList<InetAddress>();
462.16 + }
462.17 + list.add(addr);
462.18 + ip4Interfaces.put(nif, list);
462.19 + } else if (addr instanceof Inet6Address) {
462.20 + List<InetAddress> list = ip6Interfaces.get(nif);
462.21 + if (list == null) {
462.22 + list = new LinkedList<InetAddress>();
462.23 + }
462.24 + list.add(addr);
462.25 + ip6Interfaces.put(nif, list);
462.26 }
462.27 - list.add(addr);
462.28 - ip4Interfaces.put(nif, list);
462.29 - }
462.30 - if (addr instanceof Inet6Address) {
462.31 - List<InetAddress> list = ip6Interfaces.get(nif);
462.32 - if (list == null) {
462.33 - list = new LinkedList<InetAddress>();
462.34 - }
462.35 - list.add(addr);
462.36 - ip6Interfaces.put(nif, list);
462.37 -
462.38 }
462.39 }
462.40 }
463.1 --- a/test/java/nio/channels/FileChannel/Transfer.java Mon Nov 23 10:04:47 2009 +0000
463.2 +++ b/test/java/nio/channels/FileChannel/Transfer.java Wed Nov 25 11:08:25 2009 -0800
463.3 @@ -25,6 +25,7 @@
463.4 * @bug 4434723 4482726 4559072 4638365 4795550 5081340 5103988 6253145
463.5 * @summary Test FileChannel.transferFrom and transferTo
463.6 * @library ..
463.7 + * @run main/timeout=180 Transfer
463.8 */
463.9
463.10 import java.io.*;
464.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
464.2 +++ b/test/java/nio/channels/Selector/LotsOfCancels.java Wed Nov 25 11:08:25 2009 -0800
464.3 @@ -0,0 +1,292 @@
464.4 +/*
464.5 + * Copyright 2009 Google Inc. All Rights Reserved.
464.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
464.7 + *
464.8 + * This code is free software; you can redistribute it and/or modify it
464.9 + * under the terms of the GNU General Public License version 2 only, as
464.10 + * published by the Free Software Foundation.
464.11 + *
464.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
464.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
464.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
464.15 + * version 2 for more details (a copy is included in the LICENSE file that
464.16 + * accompanied this code).
464.17 + *
464.18 + * You should have received a copy of the GNU General Public License version
464.19 + * 2 along with this work; if not, write to the Free Software Foundation,
464.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
464.21 + *
464.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
464.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
464.24 + * have any questions.
464.25 + */
464.26 +
464.27 +import java.net.InetSocketAddress;
464.28 +import java.net.SocketAddress;
464.29 +import java.nio.channels.SelectionKey;
464.30 +import java.nio.channels.Selector;
464.31 +import java.nio.channels.ServerSocketChannel;
464.32 +import java.nio.channels.SocketChannel;
464.33 +import java.util.ArrayList;
464.34 +import java.util.Iterator;
464.35 +import java.util.List;
464.36 +
464.37 +/**
464.38 + * Reproduces O(N^2) behavior of JDK6/7 select() call. This happens when
464.39 + * a selector has many unprocessed updates to its interest set (e.g. adding
464.40 + * OP_READ on a bunch of newly accepted sockets). The O(N^2) is triggered
464.41 + * by cancelling a number of selection keys (or just closing a few sockets).
464.42 + * In this case, select() will first go through the list of cancelled keys
464.43 + * and try to deregister them. That deregistration is O(N^2) over the list
464.44 + * of unprocessed updates to the interest set.
464.45 + *
464.46 + * <p> This O(N^2) behavior is a BUG in JVM and should be fixed.
464.47 + *
464.48 + * <p> The test first creates initCount connections, and adds them
464.49 + * to the server epoll set. It then creates massCount connections,
464.50 + * registers interest (causing updateList to be populated with massCount*2
464.51 + * elements), but does not add them to epoll set (that would've cleared
464.52 + * updateList). The test then closes initCount connections, thus populating
464.53 + * deregistration queue. The subsequent call to selectNow() will first process
464.54 + * deregistration queue, performing O(N^2) over updateList size,
464.55 + * equal to massCount * 2.
464.56 + *
464.57 + * <p> Note that connect rate is artificially slowed down to compensate
464.58 + * for what I believe is a Linux bug, where too high of a connection rate
464.59 + * ends up in SYN's being dropped and then slow retransmits.
464.60 + *
464.61 + * @author Igor Chernyshev
464.62 + */
464.63 +public class LotsOfCancels {
464.64 +
464.65 + static long testStartTime;
464.66 +
464.67 + public static void main(String[] args) throws Exception {
464.68 + // the final select should run in less than 1000ms.
464.69 + runTest(500, 2700, 1000);
464.70 + }
464.71 +
464.72 + static void log(String msg) {
464.73 + System.out.println(getLogPrefix() + msg);
464.74 + }
464.75 +
464.76 + static String getLogPrefix() {
464.77 + return durationMillis(testStartTime) + ": ";
464.78 + }
464.79 +
464.80 + /**
464.81 + * Returns the elapsed time since startNanos, in milliseconds.
464.82 + * @param startNanos the start time; this must be a value returned
464.83 + * by {@link System.nanoTime}
464.84 + */
464.85 + static long durationMillis(long startNanos) {
464.86 + return (System.nanoTime() - startNanos) / (1000L * 1000L);
464.87 + }
464.88 +
464.89 + static void runTest(int initCount, int massCount, int maxSelectTime)
464.90 + throws Exception {
464.91 + testStartTime = System.nanoTime();
464.92 +
464.93 + InetSocketAddress address = new InetSocketAddress("127.0.0.1", 7359);
464.94 +
464.95 + // Create server channel, add it to selector and run epoll_ctl.
464.96 + log("Setting up server");
464.97 + Selector serverSelector = Selector.open();
464.98 + ServerSocketChannel server = ServerSocketChannel.open();
464.99 + server.configureBlocking(false);
464.100 + server.socket().bind(address, 5000);
464.101 + server.register(serverSelector, SelectionKey.OP_ACCEPT);
464.102 + serverSelector.selectNow();
464.103 +
464.104 + log("Setting up client");
464.105 + ClientThread client = new ClientThread(address);
464.106 + client.start();
464.107 + Thread.sleep(100);
464.108 +
464.109 + // Set up initial set of client sockets.
464.110 + log("Starting initial client connections");
464.111 + client.connectClients(initCount);
464.112 + Thread.sleep(500); // Wait for client connections to arrive
464.113 +
464.114 + // Accept all initial client sockets, add to selector and run
464.115 + // epoll_ctl.
464.116 + log("Accepting initial connections");
464.117 + List<SocketChannel> serverChannels1 =
464.118 + acceptAndAddAll(serverSelector, server, initCount);
464.119 + if (serverChannels1.size() != initCount) {
464.120 + throw new Exception("Accepted " + serverChannels1.size() +
464.121 + " instead of " + initCount);
464.122 + }
464.123 + serverSelector.selectNow();
464.124 +
464.125 + // Set up mass set of client sockets.
464.126 + log("Requesting mass client connections");
464.127 + client.connectClients(massCount);
464.128 + Thread.sleep(500); // Wait for client connections to arrive
464.129 +
464.130 + // Accept all mass client sockets, add to selector and do NOT
464.131 + // run epoll_ctl.
464.132 + log("Accepting mass connections");
464.133 + List<SocketChannel> serverChannels2 =
464.134 + acceptAndAddAll(serverSelector, server, massCount);
464.135 + if (serverChannels2.size() != massCount) {
464.136 + throw new Exception("Accepted " + serverChannels2.size() +
464.137 + " instead of " + massCount);
464.138 + }
464.139 +
464.140 + // Close initial set of sockets.
464.141 + log("Closing initial connections");
464.142 + closeAll(serverChannels1);
464.143 +
464.144 + // Now get the timing of select() call.
464.145 + log("Running the final select call");
464.146 + long startTime = System.nanoTime();
464.147 + serverSelector.selectNow();
464.148 + long duration = durationMillis(startTime);
464.149 + log("Init count = " + initCount +
464.150 + ", mass count = " + massCount +
464.151 + ", duration = " + duration + "ms");
464.152 +
464.153 + if (duration > maxSelectTime) {
464.154 + System.out.println
464.155 + ("\n\n\n\n\nFAILURE: The final selectNow() took " +
464.156 + duration + "ms " +
464.157 + "- seems like O(N^2) bug is still here\n\n");
464.158 + System.exit(1);
464.159 + }
464.160 + }
464.161 +
464.162 + static List<SocketChannel> acceptAndAddAll(Selector selector,
464.163 + ServerSocketChannel server,
464.164 + int expected)
464.165 + throws Exception {
464.166 + int retryCount = 0;
464.167 + int acceptCount = 0;
464.168 + List<SocketChannel> channels = new ArrayList<SocketChannel>();
464.169 + while (channels.size() < expected) {
464.170 + SocketChannel channel = server.accept();
464.171 + if (channel == null) {
464.172 + log("accept() returned null " +
464.173 + "after accepting " + acceptCount + " more connections");
464.174 + acceptCount = 0;
464.175 + if (retryCount < 10) {
464.176 + // See if more new sockets got stacked behind.
464.177 + retryCount++;
464.178 + Thread.sleep(500);
464.179 + continue;
464.180 + }
464.181 + break;
464.182 + }
464.183 + retryCount = 0;
464.184 + acceptCount++;
464.185 + channel.configureBlocking(false);
464.186 + channel.register(selector, SelectionKey.OP_READ);
464.187 + channels.add(channel);
464.188 + }
464.189 + // Cause an additional updateList entry per channel.
464.190 + for (SocketChannel channel : channels) {
464.191 + channel.register(selector, SelectionKey.OP_WRITE);
464.192 + }
464.193 + return channels;
464.194 + }
464.195 +
464.196 + static void closeAll(List<SocketChannel> channels)
464.197 + throws Exception {
464.198 + for (SocketChannel channel : channels) {
464.199 + channel.close();
464.200 + }
464.201 + }
464.202 +
464.203 + static class ClientThread extends Thread {
464.204 + private final SocketAddress address;
464.205 + private final Selector selector;
464.206 + private int connectionsNeeded;
464.207 + private int totalCreated;
464.208 +
464.209 + ClientThread(SocketAddress address) throws Exception {
464.210 + this.address = address;
464.211 + selector = Selector.open();
464.212 + setDaemon(true);
464.213 + }
464.214 +
464.215 + void connectClients(int count) throws Exception {
464.216 + synchronized (this) {
464.217 + connectionsNeeded += count;
464.218 + }
464.219 + selector.wakeup();
464.220 + }
464.221 +
464.222 + @Override
464.223 + public void run() {
464.224 + try {
464.225 + handleClients();
464.226 + } catch (Throwable e) {
464.227 + e.printStackTrace();
464.228 + System.exit(1);
464.229 + }
464.230 + }
464.231 +
464.232 + private void handleClients() throws Exception {
464.233 + int selectCount = 0;
464.234 + while (true) {
464.235 + int createdCount = 0;
464.236 + synchronized (this) {
464.237 + if (connectionsNeeded > 0) {
464.238 +
464.239 + while (connectionsNeeded > 0 && createdCount < 20) {
464.240 + connectionsNeeded--;
464.241 + createdCount++;
464.242 + totalCreated++;
464.243 +
464.244 + SocketChannel channel = SocketChannel.open();
464.245 + channel.configureBlocking(false);
464.246 + channel.connect(address);
464.247 + if (!channel.finishConnect()) {
464.248 + channel.register(selector,
464.249 + SelectionKey.OP_CONNECT);
464.250 + }
464.251 + }
464.252 +
464.253 + log("Started total of " +
464.254 + totalCreated + " client connections");
464.255 + Thread.sleep(200);
464.256 + }
464.257 + }
464.258 +
464.259 + if (createdCount > 0) {
464.260 + selector.selectNow();
464.261 + } else {
464.262 + selectCount++;
464.263 + long startTime = System.nanoTime();
464.264 + selector.select();
464.265 + long duration = durationMillis(startTime);
464.266 + log("Exited clientSelector.select(), loop #"
464.267 + + selectCount + ", duration = " + duration + "ms");
464.268 + }
464.269 +
464.270 + int keyCount = -1;
464.271 + Iterator<SelectionKey> keys =
464.272 + selector.selectedKeys().iterator();
464.273 + while (keys.hasNext()) {
464.274 + SelectionKey key = keys.next();
464.275 + synchronized (key) {
464.276 + keyCount++;
464.277 + keys.remove();
464.278 + if (!key.isValid()) {
464.279 + log("Ignoring client key #" + keyCount);
464.280 + continue;
464.281 + }
464.282 + int readyOps = key.readyOps();
464.283 + if (readyOps == SelectionKey.OP_CONNECT) {
464.284 + key.interestOps(0);
464.285 + ((SocketChannel) key.channel()).finishConnect();
464.286 + } else {
464.287 + log("readyOps() on client key #" + keyCount +
464.288 + " returned " + readyOps);
464.289 + }
464.290 + }
464.291 + }
464.292 + }
464.293 + }
464.294 + }
464.295 +}
465.1 --- a/test/java/nio/file/Path/CopyAndMove.java Mon Nov 23 10:04:47 2009 +0000
465.2 +++ b/test/java/nio/file/Path/CopyAndMove.java Wed Nov 25 11:08:25 2009 -0800
465.3 @@ -25,6 +25,8 @@
465.4 * @bug 4313887 6838333
465.5 * @summary Unit test for java.nio.file.Path copyTo/moveTo methods
465.6 * @library ..
465.7 + * @build CopyAndMove
465.8 + * @run main/othervm CopyAndMove
465.9 */
465.10
465.11 import java.nio.ByteBuffer;
466.1 --- a/test/java/nio/file/Path/Links.java Mon Nov 23 10:04:47 2009 +0000
466.2 +++ b/test/java/nio/file/Path/Links.java Wed Nov 25 11:08:25 2009 -0800
466.3 @@ -26,6 +26,8 @@
466.4 * @summary Unit test for java.nio.file.Path createSymbolicLink,
466.5 * readSymbolicLink, and createLink methods
466.6 * @library ..
466.7 + * @build Links
466.8 + * @run main/othervm Links
466.9 */
466.10
466.11 import java.nio.file.*;
467.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
467.2 +++ b/test/java/util/Arrays/Sorting.java Wed Nov 25 11:08:25 2009 -0800
467.3 @@ -0,0 +1,1440 @@
467.4 +/*
467.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
467.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
467.7 + *
467.8 + * This code is free software; you can redistribute it and/or modify it
467.9 + * under the terms of the GNU General Public License version 2 only, as
467.10 + * published by the Free Software Foundation.
467.11 + *
467.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
467.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
467.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
467.15 + * version 2 for more details (a copy is included in the LICENSE file that
467.16 + * accompanied this code).
467.17 + *
467.18 + * You should have received a copy of the GNU General Public License version
467.19 + * 2 along with this work; if not, write to the Free Software Foundation,
467.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
467.21 + *
467.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
467.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
467.24 + * have any questions.
467.25 + */
467.26 +
467.27 +/*
467.28 + * @test
467.29 + * @bug 6880672 6896573 6899694
467.30 + * @summary Exercise Arrays.sort
467.31 + * @build Sorting
467.32 + * @run main Sorting -shortrun
467.33 + *
467.34 + * @author Vladimir Yaroslavskiy
467.35 + * @author Jon Bentley
467.36 + * @author Josh Bloch
467.37 + */
467.38 +
467.39 +import java.util.Arrays;
467.40 +import java.util.Random;
467.41 +import java.io.PrintStream;
467.42 +
467.43 +public class Sorting {
467.44 + private static final PrintStream out = System.out;
467.45 + private static final PrintStream err = System.err;
467.46 +
467.47 + // Array lengths used in a long run (default)
467.48 + private static final int[] LONG_RUN_LENGTHS = {
467.49 + 1, 2, 3, 5, 8, 13, 21, 34, 55, 100, 1000, 10000, 100000, 1000000};
467.50 +
467.51 + // Array lengths used in a short run
467.52 + private static final int[] SHORT_RUN_LENGTHS = { 1, 2, 3, 21, 55, 1000, 10000 };
467.53 +
467.54 + // Random initial values used in a long run (default)
467.55 + private static final long[] LONG_RUN_RANDOMS = {666, 0xC0FFEE, 999};
467.56 +
467.57 + // Random initial values used in a short run
467.58 + private static final long[] SHORT_RUN_RANDOMS = {666};
467.59 +
467.60 + public static void main(String[] args) {
467.61 + boolean shortRun = args.length > 0 && args[0].equals("-shortrun");
467.62 + long start = System.currentTimeMillis();
467.63 +
467.64 + if (shortRun) {
467.65 + testAndCheck(SHORT_RUN_LENGTHS, SHORT_RUN_RANDOMS);
467.66 + } else {
467.67 + testAndCheck(LONG_RUN_LENGTHS, LONG_RUN_RANDOMS);
467.68 + }
467.69 + long end = System.currentTimeMillis();
467.70 +
467.71 + out.format("PASS in %d sec.\n", Math.round((end - start) / 1E3));
467.72 + }
467.73 +
467.74 + private static void testAndCheck(int[] lengths, long[] randoms) {
467.75 + for (long random : randoms) {
467.76 + reset(random);
467.77 +
467.78 + for (int len : lengths) {
467.79 + testAndCheckWithCheckSum(len, random);
467.80 + }
467.81 + reset(random);
467.82 +
467.83 + for (int len : lengths) {
467.84 + testAndCheckWithScrambling(len, random);
467.85 + }
467.86 + reset(random);
467.87 +
467.88 + for (int len : lengths) {
467.89 + testAndCheckFloat(len, random);
467.90 + }
467.91 + reset(random);
467.92 +
467.93 + for (int len : lengths) {
467.94 + testAndCheckDouble(len, random);
467.95 + }
467.96 + reset(random);
467.97 +
467.98 + for (int len : lengths) {
467.99 + testAndCheckRange(len, random);
467.100 + }
467.101 + reset(random);
467.102 +
467.103 + for (int len : lengths) {
467.104 + testAndCheckSubArray(len, random);
467.105 + }
467.106 + }
467.107 + }
467.108 +
467.109 + private static void testAndCheckSubArray(int len, long random) {
467.110 + int[] golden = new int[len];
467.111 +
467.112 + for (int m = 1; m < len / 2; m *= 2) {
467.113 + int fromIndex = m;
467.114 + int toIndex = len - m;
467.115 +
467.116 + prepareSubArray(golden, fromIndex, toIndex, m);
467.117 + int[] test = golden.clone();
467.118 +
467.119 + for (TypeConverter converter : TypeConverter.values()) {
467.120 + out.println("Test #6: " + converter +
467.121 + " len = " + len + ", m = " + m);
467.122 + Object convertedGolden = converter.convert(golden);
467.123 + Object convertedTest = converter.convert(test);
467.124 +
467.125 + // outArr(test);
467.126 + sortSubArray(convertedTest, fromIndex, toIndex);
467.127 + // outArr(test);
467.128 + checkSubArray(convertedTest, fromIndex, toIndex, m);
467.129 + }
467.130 + }
467.131 + out.println();
467.132 + }
467.133 +
467.134 + private static void testAndCheckRange(int len, long random) {
467.135 + int[] golden = new int[len];
467.136 +
467.137 + for (int m = 1; m < 2 * len; m *= 2) {
467.138 + for (int i = 1; i <= len; i++) {
467.139 + golden[i - 1] = i % m + m % i;
467.140 + }
467.141 + for (TypeConverter converter : TypeConverter.values()) {
467.142 + out.println("Test #5: " + converter +
467.143 + ", len = " + len + ", m = " + m);
467.144 + Object convertedGolden = converter.convert(golden);
467.145 + sortRange(convertedGolden, m);
467.146 + sortEmpty(convertedGolden);
467.147 + }
467.148 + }
467.149 + out.println();
467.150 + }
467.151 +
467.152 + private static void testAndCheckWithCheckSum(int len, long random) {
467.153 + int[] golden = new int[len];
467.154 +
467.155 + for (int m = 1; m < 2 * len; m *= 2) {
467.156 + for (UnsortedBuilder builder : UnsortedBuilder.values()) {
467.157 + builder.build(golden, m);
467.158 + int[] test = golden.clone();
467.159 +
467.160 + for (TypeConverter converter : TypeConverter.values()) {
467.161 + out.println("Test #1: " + converter + " " + builder +
467.162 + "random = " + random + ", len = " + len +
467.163 + ", m = " + m);
467.164 + Object convertedGolden = converter.convert(golden);
467.165 + Object convertedTest = converter.convert(test);
467.166 + sort(convertedTest);
467.167 + checkWithCheckSum(convertedTest, convertedGolden);
467.168 + }
467.169 + }
467.170 + }
467.171 + out.println();
467.172 + }
467.173 +
467.174 + private static void testAndCheckWithScrambling(int len, long random) {
467.175 + int[] golden = new int[len];
467.176 +
467.177 + for (int m = 1; m <= 7; m++) {
467.178 + if (m > len) {
467.179 + break;
467.180 + }
467.181 + for (SortedBuilder builder : SortedBuilder.values()) {
467.182 + builder.build(golden, m);
467.183 + int[] test = golden.clone();
467.184 + scramble(test);
467.185 +
467.186 + for (TypeConverter converter : TypeConverter.values()) {
467.187 + out.println("Test #2: " + converter + " " + builder +
467.188 + "random = " + random + ", len = " + len +
467.189 + ", m = " + m);
467.190 + Object convertedGolden = converter.convert(golden);
467.191 + Object convertedTest = converter.convert(test);
467.192 + sort(convertedTest);
467.193 + compare(convertedTest, convertedGolden);
467.194 + }
467.195 + }
467.196 + }
467.197 + out.println();
467.198 + }
467.199 +
467.200 + private static void testAndCheckFloat(int len, long random) {
467.201 + float[] golden = new float[len];
467.202 + final int MAX = 10;
467.203 + boolean newLine = false;
467.204 +
467.205 + for (int a = 0; a <= MAX; a++) {
467.206 + for (int g = 0; g <= MAX; g++) {
467.207 + for (int z = 0; z <= MAX; z++) {
467.208 + for (int n = 0; n <= MAX; n++) {
467.209 + for (int p = 0; p <= MAX; p++) {
467.210 + if (a + g + z + n + p > len) {
467.211 + continue;
467.212 + }
467.213 + if (a + g + z + n + p < len) {
467.214 + continue;
467.215 + }
467.216 + for (FloatBuilder builder : FloatBuilder.values()) {
467.217 + out.println("Test #3: random = " + random +
467.218 + ", len = " + len + ", a = " + a + ", g = " + g +
467.219 + ", z = " + z + ", n = " + n + ", p = " + p);
467.220 + builder.build(golden, a, g, z, n, p);
467.221 + float[] test = golden.clone();
467.222 + scramble(test);
467.223 + // outArr(test);
467.224 + sort(test);
467.225 + // outArr(test);
467.226 + compare(test, golden, a, n, g);
467.227 + }
467.228 + newLine = true;
467.229 + }
467.230 + }
467.231 + }
467.232 + }
467.233 + }
467.234 + if (newLine) {
467.235 + out.println();
467.236 + }
467.237 + }
467.238 +
467.239 + private static void testAndCheckDouble(int len, long random) {
467.240 + double[] golden = new double[len];
467.241 + final int MAX = 10;
467.242 + boolean newLine = false;
467.243 +
467.244 + for (int a = 0; a <= MAX; a++) {
467.245 + for (int g = 0; g <= MAX; g++) {
467.246 + for (int z = 0; z <= MAX; z++) {
467.247 + for (int n = 0; n <= MAX; n++) {
467.248 + for (int p = 0; p <= MAX; p++) {
467.249 + if (a + g + z + n + p > len) {
467.250 + continue;
467.251 + }
467.252 + if (a + g + z + n + p < len) {
467.253 + continue;
467.254 + }
467.255 + for (DoubleBuilder builder : DoubleBuilder.values()) {
467.256 + out.println("Test #4: random = " + random +
467.257 + ", len = " + len + ", a = " + a + ", g = " + g +
467.258 + ", z = " + z + ", n = " + n + ", p = " + p);
467.259 + builder.build(golden, a, g, z, n, p);
467.260 + double[] test = golden.clone();
467.261 + scramble(test);
467.262 + // outArr(test);
467.263 + sort(test);
467.264 + // outArr(test);
467.265 + compare(test, golden, a, n, g);
467.266 + }
467.267 + newLine = true;
467.268 + }
467.269 + }
467.270 + }
467.271 + }
467.272 + }
467.273 + if (newLine) {
467.274 + out.println();
467.275 + }
467.276 + }
467.277 +
467.278 + private static void prepareSubArray(int[] a, int fromIndex, int toIndex, int m) {
467.279 + for (int i = 0; i < fromIndex; i++) {
467.280 + a[i] = 0xBABA;
467.281 + }
467.282 +
467.283 + for (int i = fromIndex; i < toIndex; i++) {
467.284 + a[i] = -i + m;
467.285 + }
467.286 +
467.287 + for (int i = toIndex; i < a.length; i++) {
467.288 + a[i] = 0xDEDA;
467.289 + }
467.290 + }
467.291 +
467.292 + private static void scramble(int[] a) {
467.293 + int length = a.length;
467.294 +
467.295 + for (int i = 0; i < length * 7; i++) {
467.296 + swap(a, ourRandom.nextInt(length), ourRandom.nextInt(length));
467.297 + }
467.298 + }
467.299 +
467.300 + private static void scramble(float[] a) {
467.301 + int length = a.length;
467.302 +
467.303 + for (int i = 0; i < length * 7; i++) {
467.304 + swap(a, ourRandom.nextInt(length), ourRandom.nextInt(length));
467.305 + }
467.306 + }
467.307 +
467.308 + private static void scramble(double[] a) {
467.309 + int length = a.length;
467.310 +
467.311 + for (int i = 0; i < length * 7; i++) {
467.312 + swap(a, ourRandom.nextInt(length), ourRandom.nextInt(length));
467.313 + }
467.314 + }
467.315 +
467.316 + private static void swap(int[] a, int i, int j) {
467.317 + int t = a[i];
467.318 + a[i] = a[j];
467.319 + a[j] = t;
467.320 + }
467.321 +
467.322 + private static void swap(float[] a, int i, int j) {
467.323 + float t = a[i];
467.324 + a[i] = a[j];
467.325 + a[j] = t;
467.326 + }
467.327 +
467.328 + private static void swap(double[] a, int i, int j) {
467.329 + double t = a[i];
467.330 + a[i] = a[j];
467.331 + a[j] = t;
467.332 + }
467.333 +
467.334 + private static enum TypeConverter {
467.335 + INT {
467.336 + Object convert(int[] a) {
467.337 + return a.clone();
467.338 + }
467.339 + },
467.340 + LONG {
467.341 + Object convert(int[] a) {
467.342 + long[] b = new long[a.length];
467.343 +
467.344 + for (int i = 0; i < a.length; i++) {
467.345 + b[i] = (long) a[i];
467.346 + }
467.347 + return b;
467.348 + }
467.349 + },
467.350 + BYTE {
467.351 + Object convert(int[] a) {
467.352 + byte[] b = new byte[a.length];
467.353 +
467.354 + for (int i = 0; i < a.length; i++) {
467.355 + b[i] = (byte) a[i];
467.356 + }
467.357 + return b;
467.358 + }
467.359 + },
467.360 + SHORT {
467.361 + Object convert(int[] a) {
467.362 + short[] b = new short[a.length];
467.363 +
467.364 + for (int i = 0; i < a.length; i++) {
467.365 + b[i] = (short) a[i];
467.366 + }
467.367 + return b;
467.368 + }
467.369 + },
467.370 + CHAR {
467.371 + Object convert(int[] a) {
467.372 + char[] b = new char[a.length];
467.373 +
467.374 + for (int i = 0; i < a.length; i++) {
467.375 + b[i] = (char) a[i];
467.376 + }
467.377 + return b;
467.378 + }
467.379 + },
467.380 + FLOAT {
467.381 + Object convert(int[] a) {
467.382 + float[] b = new float[a.length];
467.383 +
467.384 + for (int i = 0; i < a.length; i++) {
467.385 + b[i] = (float) a[i];
467.386 + }
467.387 + return b;
467.388 + }
467.389 + },
467.390 + DOUBLE {
467.391 + Object convert(int[] a) {
467.392 + double[] b = new double[a.length];
467.393 +
467.394 + for (int i = 0; i < a.length; i++) {
467.395 + b[i] = (double) a[i];
467.396 + }
467.397 + return b;
467.398 + }
467.399 + };
467.400 +
467.401 + abstract Object convert(int[] a);
467.402 +
467.403 + @Override public String toString() {
467.404 + String name = name();
467.405 +
467.406 + for (int i = name.length(); i < 9; i++) {
467.407 + name += " ";
467.408 + }
467.409 + return name;
467.410 + }
467.411 + }
467.412 +
467.413 + private static enum FloatBuilder {
467.414 + SIMPLE {
467.415 + void build(float[] x, int a, int g, int z, int n, int p) {
467.416 + int fromIndex = 0;
467.417 + float negativeValue = -ourRandom.nextFloat();
467.418 + float positiveValue = ourRandom.nextFloat();
467.419 +
467.420 + writeValue(x, negativeValue, fromIndex, n);
467.421 + fromIndex += n;
467.422 +
467.423 + writeValue(x, -0.0f, fromIndex, g);
467.424 + fromIndex += g;
467.425 +
467.426 + writeValue(x, 0.0f, fromIndex, z);
467.427 + fromIndex += z;
467.428 +
467.429 + writeValue(x, positiveValue, fromIndex, p);
467.430 + fromIndex += p;
467.431 +
467.432 + writeValue(x, Float.NaN, fromIndex, a);
467.433 + }
467.434 + };
467.435 +
467.436 + abstract void build(float[] x, int a, int g, int z, int n, int p);
467.437 + }
467.438 +
467.439 + private static enum DoubleBuilder {
467.440 + SIMPLE {
467.441 + void build(double[] x, int a, int g, int z, int n, int p) {
467.442 + int fromIndex = 0;
467.443 + double negativeValue = -ourRandom.nextFloat();
467.444 + double positiveValue = ourRandom.nextFloat();
467.445 +
467.446 + writeValue(x, negativeValue, fromIndex, n);
467.447 + fromIndex += n;
467.448 +
467.449 + writeValue(x, -0.0d, fromIndex, g);
467.450 + fromIndex += g;
467.451 +
467.452 + writeValue(x, 0.0d, fromIndex, z);
467.453 + fromIndex += z;
467.454 +
467.455 + writeValue(x, positiveValue, fromIndex, p);
467.456 + fromIndex += p;
467.457 +
467.458 + writeValue(x, Double.NaN, fromIndex, a);
467.459 + }
467.460 + };
467.461 +
467.462 + abstract void build(double[] x, int a, int g, int z, int n, int p);
467.463 + }
467.464 +
467.465 + private static void writeValue(float[] a, float value, int fromIndex, int count) {
467.466 + for (int i = fromIndex; i < fromIndex + count; i++) {
467.467 + a[i] = value;
467.468 + }
467.469 + }
467.470 +
467.471 + private static void compare(float[] a, float[] b, int numNaN, int numNeg, int numNegZero) {
467.472 + for (int i = a.length - numNaN; i < a.length; i++) {
467.473 + if (a[i] == a[i]) {
467.474 + failed("On position " + i + " must be NaN instead of " + a[i]);
467.475 + }
467.476 + }
467.477 + final int NEGATIVE_ZERO = Float.floatToIntBits(-0.0f);
467.478 +
467.479 + for (int i = numNeg; i < numNeg + numNegZero; i++) {
467.480 + if (NEGATIVE_ZERO != Float.floatToIntBits(a[i])) {
467.481 + failed("On position " + i + " must be -0.0f instead of " + a[i]);
467.482 + }
467.483 + }
467.484 + for (int i = 0; i < a.length - numNaN; i++) {
467.485 + if (a[i] != b[i]) {
467.486 + failed(i, "" + a[i], "" + b[i]);
467.487 + }
467.488 + }
467.489 + }
467.490 +
467.491 + private static void writeValue(double[] a, double value, int fromIndex, int count) {
467.492 + for (int i = fromIndex; i < fromIndex + count; i++) {
467.493 + a[i] = value;
467.494 + }
467.495 + }
467.496 +
467.497 + private static void compare(double[] a, double[] b, int numNaN, int numNeg, int numNegZero) {
467.498 + for (int i = a.length - numNaN; i < a.length; i++) {
467.499 + if (a[i] == a[i]) {
467.500 + failed("On position " + i + " must be NaN instead of " + a[i]);
467.501 + }
467.502 + }
467.503 + final long NEGATIVE_ZERO = Double.doubleToLongBits(-0.0d);
467.504 +
467.505 + for (int i = numNeg; i < numNeg + numNegZero; i++) {
467.506 + if (NEGATIVE_ZERO != Double.doubleToLongBits(a[i])) {
467.507 + failed("On position " + i + " must be -0.0d instead of " + a[i]);
467.508 + }
467.509 + }
467.510 + for (int i = 0; i < a.length - numNaN; i++) {
467.511 + if (a[i] != b[i]) {
467.512 + failed(i, "" + a[i], "" + b[i]);
467.513 + }
467.514 + }
467.515 + }
467.516 +
467.517 + private static enum SortedBuilder {
467.518 + REPEATED {
467.519 + void build(int[] a, int m) {
467.520 + int period = a.length / m;
467.521 + int i = 0;
467.522 + int k = 0;
467.523 +
467.524 + while (true) {
467.525 + for (int t = 1; t <= period; t++) {
467.526 + if (i >= a.length) {
467.527 + return;
467.528 + }
467.529 + a[i++] = k;
467.530 + }
467.531 + if (i >= a.length) {
467.532 + return;
467.533 + }
467.534 + k++;
467.535 + }
467.536 + }
467.537 + },
467.538 +
467.539 + ORGAN_PIPES {
467.540 + void build(int[] a, int m) {
467.541 + int i = 0;
467.542 + int k = m;
467.543 +
467.544 + while (true) {
467.545 + for (int t = 1; t <= m; t++) {
467.546 + if (i >= a.length) {
467.547 + return;
467.548 + }
467.549 + a[i++] = k;
467.550 + }
467.551 + }
467.552 + }
467.553 + };
467.554 +
467.555 + abstract void build(int[] a, int m);
467.556 +
467.557 + @Override public String toString() {
467.558 + String name = name();
467.559 +
467.560 + for (int i = name.length(); i < 12; i++) {
467.561 + name += " ";
467.562 + }
467.563 + return name;
467.564 + }
467.565 + }
467.566 +
467.567 + private static enum UnsortedBuilder {
467.568 + RANDOM {
467.569 + void build(int[] a, int m) {
467.570 + for (int i = 0; i < a.length; i++) {
467.571 + a[i] = ourRandom.nextInt();
467.572 + }
467.573 + }
467.574 + },
467.575 + ASCENDING {
467.576 + void build(int[] a, int m) {
467.577 + for (int i = 0; i < a.length; i++) {
467.578 + a[i] = m + i;
467.579 + }
467.580 + }
467.581 + },
467.582 + DESCENDING {
467.583 + void build(int[] a, int m) {
467.584 + for (int i = 0; i < a.length; i++) {
467.585 + a[i] = a.length - m - i;
467.586 + }
467.587 + }
467.588 + },
467.589 + ALL_EQUAL {
467.590 + void build(int[] a, int m) {
467.591 + for (int i = 0; i < a.length; i++) {
467.592 + a[i] = m;
467.593 + }
467.594 + }
467.595 + },
467.596 + SAW {
467.597 + void build(int[] a, int m) {
467.598 + int incCount = 1;
467.599 + int decCount = a.length;
467.600 + int i = 0;
467.601 + int period = m;
467.602 + m--;
467.603 + while (true) {
467.604 + for (int k = 1; k <= period; k++) {
467.605 + if (i >= a.length) {
467.606 + return;
467.607 + }
467.608 + a[i++] = incCount++;
467.609 + }
467.610 + period += m;
467.611 +
467.612 + for (int k = 1; k <= period; k++) {
467.613 + if (i >= a.length) {
467.614 + return;
467.615 + }
467.616 + a[i++] = decCount--;
467.617 + }
467.618 + period += m;
467.619 + }
467.620 + }
467.621 + },
467.622 + REPEATED {
467.623 + void build(int[] a, int m) {
467.624 + for (int i = 0; i < a.length; i++) {
467.625 + a[i] = i % m;
467.626 + }
467.627 + }
467.628 + },
467.629 + DUPLICATED {
467.630 + void build(int[] a, int m) {
467.631 + for (int i = 0; i < a.length; i++) {
467.632 + a[i] = ourRandom.nextInt(m);
467.633 + }
467.634 + }
467.635 + },
467.636 + ORGAN_PIPES {
467.637 + void build(int[] a, int m) {
467.638 + int middle = a.length / (m + 1);
467.639 +
467.640 + for (int i = 0; i < middle; i++) {
467.641 + a[i] = i;
467.642 + }
467.643 + for (int i = middle; i < a.length; i++) {
467.644 + a[i] = a.length - i - 1;
467.645 + }
467.646 + }
467.647 + },
467.648 + STAGGER {
467.649 + void build(int[] a, int m) {
467.650 + for (int i = 0; i < a.length; i++) {
467.651 + a[i] = (i * m + i) % a.length;
467.652 + }
467.653 + }
467.654 + },
467.655 + PLATEAU {
467.656 + void build(int[] a, int m) {
467.657 + for (int i = 0; i < a.length; i++) {
467.658 + a[i] = Math.min(i, m);
467.659 + }
467.660 + }
467.661 + },
467.662 + SHUFFLE {
467.663 + void build(int[] a, int m) {
467.664 + for (int i = 0; i < a.length; i++) {
467.665 + a[i] = ourRandom.nextBoolean() ? (ourFirst += 2) : (ourSecond += 2);
467.666 + }
467.667 + }
467.668 + };
467.669 +
467.670 + abstract void build(int[] a, int m);
467.671 +
467.672 + @Override public String toString() {
467.673 + String name = name();
467.674 +
467.675 + for (int i = name.length(); i < 12; i++) {
467.676 + name += " ";
467.677 + }
467.678 + return name;
467.679 + }
467.680 + }
467.681 +
467.682 + private static void compare(Object test, Object golden) {
467.683 + if (test instanceof int[]) {
467.684 + compare((int[]) test, (int[]) golden);
467.685 + } else if (test instanceof long[]) {
467.686 + compare((long[]) test, (long[]) golden);
467.687 + } else if (test instanceof short[]) {
467.688 + compare((short[]) test, (short[]) golden);
467.689 + } else if (test instanceof byte[]) {
467.690 + compare((byte[]) test, (byte[]) golden);
467.691 + } else if (test instanceof char[]) {
467.692 + compare((char[]) test, (char[]) golden);
467.693 + } else if (test instanceof float[]) {
467.694 + compare((float[]) test, (float[]) golden);
467.695 + } else if (test instanceof double[]) {
467.696 + compare((double[]) test, (double[]) golden);
467.697 + } else {
467.698 + failed("Unknow type of array: " + test + " of class " +
467.699 + test.getClass().getName());
467.700 + }
467.701 + }
467.702 +
467.703 + private static void checkWithCheckSum(Object test, Object golden) {
467.704 + checkSorted(test);
467.705 + checkCheckSum(test, golden);
467.706 + }
467.707 +
467.708 + private static void failed(String message) {
467.709 + err.format("\n*** FAILED: %s\n\n", message);
467.710 + throw new RuntimeException("Test failed - see log file for details");
467.711 + }
467.712 +
467.713 + private static void failed(int index, String value1, String value2) {
467.714 + failed("Array is not sorted at " + index + "-th position: " + value1 +
467.715 + " and " + value2);
467.716 + }
467.717 +
467.718 + private static void checkSorted(Object object) {
467.719 + if (object instanceof int[]) {
467.720 + checkSorted((int[]) object);
467.721 + } else if (object instanceof long[]) {
467.722 + checkSorted((long[]) object);
467.723 + } else if (object instanceof short[]) {
467.724 + checkSorted((short[]) object);
467.725 + } else if (object instanceof byte[]) {
467.726 + checkSorted((byte[]) object);
467.727 + } else if (object instanceof char[]) {
467.728 + checkSorted((char[]) object);
467.729 + } else if (object instanceof float[]) {
467.730 + checkSorted((float[]) object);
467.731 + } else if (object instanceof double[]) {
467.732 + checkSorted((double[]) object);
467.733 + } else {
467.734 + failed("Unknow type of array: " + object + " of class " +
467.735 + object.getClass().getName());
467.736 + }
467.737 + }
467.738 +
467.739 + private static void compare(int[] a, int[] b) {
467.740 + for (int i = 0; i < a.length; i++) {
467.741 + if (a[i] != b[i]) {
467.742 + failed(i, "" + a[i], "" + b[i]);
467.743 + }
467.744 + }
467.745 + }
467.746 +
467.747 + private static void compare(long[] a, long[] b) {
467.748 + for (int i = 0; i < a.length; i++) {
467.749 + if (a[i] != b[i]) {
467.750 + failed(i, "" + a[i], "" + b[i]);
467.751 + }
467.752 + }
467.753 + }
467.754 +
467.755 + private static void compare(short[] a, short[] b) {
467.756 + for (int i = 0; i < a.length; i++) {
467.757 + if (a[i] != b[i]) {
467.758 + failed(i, "" + a[i], "" + b[i]);
467.759 + }
467.760 + }
467.761 + }
467.762 +
467.763 + private static void compare(byte[] a, byte[] b) {
467.764 + for (int i = 0; i < a.length; i++) {
467.765 + if (a[i] != b[i]) {
467.766 + failed(i, "" + a[i], "" + b[i]);
467.767 + }
467.768 + }
467.769 + }
467.770 +
467.771 + private static void compare(char[] a, char[] b) {
467.772 + for (int i = 0; i < a.length; i++) {
467.773 + if (a[i] != b[i]) {
467.774 + failed(i, "" + a[i], "" + b[i]);
467.775 + }
467.776 + }
467.777 + }
467.778 +
467.779 + private static void compare(float[] a, float[] b) {
467.780 + for (int i = 0; i < a.length; i++) {
467.781 + if (a[i] != b[i]) {
467.782 + failed(i, "" + a[i], "" + b[i]);
467.783 + }
467.784 + }
467.785 + }
467.786 +
467.787 + private static void compare(double[] a, double[] b) {
467.788 + for (int i = 0; i < a.length; i++) {
467.789 + if (a[i] != b[i]) {
467.790 + failed(i, "" + a[i], "" + b[i]);
467.791 + }
467.792 + }
467.793 + }
467.794 +
467.795 + private static void checkSorted(int[] a) {
467.796 + for (int i = 0; i < a.length - 1; i++) {
467.797 + if (a[i] > a[i + 1]) {
467.798 + failed(i, "" + a[i], "" + a[i + 1]);
467.799 + }
467.800 + }
467.801 + }
467.802 +
467.803 + private static void checkSorted(long[] a) {
467.804 + for (int i = 0; i < a.length - 1; i++) {
467.805 + if (a[i] > a[i + 1]) {
467.806 + failed(i, "" + a[i], "" + a[i + 1]);
467.807 + }
467.808 + }
467.809 + }
467.810 +
467.811 + private static void checkSorted(short[] a) {
467.812 + for (int i = 0; i < a.length - 1; i++) {
467.813 + if (a[i] > a[i + 1]) {
467.814 + failed(i, "" + a[i], "" + a[i + 1]);
467.815 + }
467.816 + }
467.817 + }
467.818 +
467.819 + private static void checkSorted(byte[] a) {
467.820 + for (int i = 0; i < a.length - 1; i++) {
467.821 + if (a[i] > a[i + 1]) {
467.822 + failed(i, "" + a[i], "" + a[i + 1]);
467.823 + }
467.824 + }
467.825 + }
467.826 +
467.827 + private static void checkSorted(char[] a) {
467.828 + for (int i = 0; i < a.length - 1; i++) {
467.829 + if (a[i] > a[i + 1]) {
467.830 + failed(i, "" + a[i], "" + a[i + 1]);
467.831 + }
467.832 + }
467.833 + }
467.834 +
467.835 + private static void checkSorted(float[] a) {
467.836 + for (int i = 0; i < a.length - 1; i++) {
467.837 + if (a[i] > a[i + 1]) {
467.838 + failed(i, "" + a[i], "" + a[i + 1]);
467.839 + }
467.840 + }
467.841 + }
467.842 +
467.843 + private static void checkSorted(double[] a) {
467.844 + for (int i = 0; i < a.length - 1; i++) {
467.845 + if (a[i] > a[i + 1]) {
467.846 + failed(i, "" + a[i], "" + a[i + 1]);
467.847 + }
467.848 + }
467.849 + }
467.850 +
467.851 + private static void checkCheckSum(Object test, Object golden) {
467.852 + if (checkSum(test) != checkSum(golden)) {
467.853 + failed("Original and sorted arrays seems not identical");
467.854 + }
467.855 + }
467.856 +
467.857 + private static int checkSum(Object object) {
467.858 + if (object instanceof int[]) {
467.859 + return checkSum((int[]) object);
467.860 + } else if (object instanceof long[]) {
467.861 + return checkSum((long[]) object);
467.862 + } else if (object instanceof short[]) {
467.863 + return checkSum((short[]) object);
467.864 + } else if (object instanceof byte[]) {
467.865 + return checkSum((byte[]) object);
467.866 + } else if (object instanceof char[]) {
467.867 + return checkSum((char[]) object);
467.868 + } else if (object instanceof float[]) {
467.869 + return checkSum((float[]) object);
467.870 + } else if (object instanceof double[]) {
467.871 + return checkSum((double[]) object);
467.872 + } else {
467.873 + failed("Unknow type of array: " + object + " of class " +
467.874 + object.getClass().getName());
467.875 + return -1;
467.876 + }
467.877 + }
467.878 +
467.879 + private static int checkSum(int[] a) {
467.880 + int checkXorSum = 0;
467.881 +
467.882 + for (int e : a) {
467.883 + checkXorSum ^= e;
467.884 + }
467.885 + return checkXorSum;
467.886 + }
467.887 +
467.888 + private static int checkSum(long[] a) {
467.889 + long checkXorSum = 0;
467.890 +
467.891 + for (long e : a) {
467.892 + checkXorSum ^= e;
467.893 + }
467.894 + return (int) checkXorSum;
467.895 + }
467.896 +
467.897 + private static int checkSum(short[] a) {
467.898 + short checkXorSum = 0;
467.899 +
467.900 + for (short e : a) {
467.901 + checkXorSum ^= e;
467.902 + }
467.903 + return (int) checkXorSum;
467.904 + }
467.905 +
467.906 + private static int checkSum(byte[] a) {
467.907 + byte checkXorSum = 0;
467.908 +
467.909 + for (byte e : a) {
467.910 + checkXorSum ^= e;
467.911 + }
467.912 + return (int) checkXorSum;
467.913 + }
467.914 +
467.915 + private static int checkSum(char[] a) {
467.916 + char checkXorSum = 0;
467.917 +
467.918 + for (char e : a) {
467.919 + checkXorSum ^= e;
467.920 + }
467.921 + return (int) checkXorSum;
467.922 + }
467.923 +
467.924 + private static int checkSum(float[] a) {
467.925 + int checkXorSum = 0;
467.926 +
467.927 + for (float e : a) {
467.928 + checkXorSum ^= (int) e;
467.929 + }
467.930 + return checkXorSum;
467.931 + }
467.932 +
467.933 + private static int checkSum(double[] a) {
467.934 + int checkXorSum = 0;
467.935 +
467.936 + for (double e : a) {
467.937 + checkXorSum ^= (int) e;
467.938 + }
467.939 + return checkXorSum;
467.940 + }
467.941 +
467.942 + private static void sort(Object object) {
467.943 + if (object instanceof int[]) {
467.944 + Arrays.sort((int[]) object);
467.945 + } else if (object instanceof long[]) {
467.946 + Arrays.sort((long[]) object);
467.947 + } else if (object instanceof short[]) {
467.948 + Arrays.sort((short[]) object);
467.949 + } else if (object instanceof byte[]) {
467.950 + Arrays.sort((byte[]) object);
467.951 + } else if (object instanceof char[]) {
467.952 + Arrays.sort((char[]) object);
467.953 + } else if (object instanceof float[]) {
467.954 + Arrays.sort((float[]) object);
467.955 + } else if (object instanceof double[]) {
467.956 + Arrays.sort((double[]) object);
467.957 + } else {
467.958 + failed("Unknow type of array: " + object + " of class " +
467.959 + object.getClass().getName());
467.960 + }
467.961 + }
467.962 +
467.963 + private static void sortSubArray(Object object, int fromIndex, int toIndex) {
467.964 + if (object instanceof int[]) {
467.965 + Arrays.sort((int[]) object, fromIndex, toIndex);
467.966 + } else if (object instanceof long[]) {
467.967 + Arrays.sort((long[]) object, fromIndex, toIndex);
467.968 + } else if (object instanceof short[]) {
467.969 + Arrays.sort((short[]) object, fromIndex, toIndex);
467.970 + } else if (object instanceof byte[]) {
467.971 + Arrays.sort((byte[]) object, fromIndex, toIndex);
467.972 + } else if (object instanceof char[]) {
467.973 + Arrays.sort((char[]) object, fromIndex, toIndex);
467.974 + } else if (object instanceof float[]) {
467.975 + Arrays.sort((float[]) object, fromIndex, toIndex);
467.976 + } else if (object instanceof double[]) {
467.977 + Arrays.sort((double[]) object, fromIndex, toIndex);
467.978 + } else {
467.979 + failed("Unknow type of array: " + object + " of class " +
467.980 + object.getClass().getName());
467.981 + }
467.982 + }
467.983 +
467.984 + private static void checkSubArray(Object object, int fromIndex, int toIndex, int m) {
467.985 + if (object instanceof int[]) {
467.986 + checkSubArray((int[]) object, fromIndex, toIndex, m);
467.987 + } else if (object instanceof long[]) {
467.988 + checkSubArray((long[]) object, fromIndex, toIndex, m);
467.989 + } else if (object instanceof short[]) {
467.990 + checkSubArray((short[]) object, fromIndex, toIndex, m);
467.991 + } else if (object instanceof byte[]) {
467.992 + checkSubArray((byte[]) object, fromIndex, toIndex, m);
467.993 + } else if (object instanceof char[]) {
467.994 + checkSubArray((char[]) object, fromIndex, toIndex, m);
467.995 + } else if (object instanceof float[]) {
467.996 + checkSubArray((float[]) object, fromIndex, toIndex, m);
467.997 + } else if (object instanceof double[]) {
467.998 + checkSubArray((double[]) object, fromIndex, toIndex, m);
467.999 + } else {
467.1000 + failed("Unknow type of array: " + object + " of class " +
467.1001 + object.getClass().getName());
467.1002 + }
467.1003 + }
467.1004 +
467.1005 + private static void checkSubArray(int[] a, int fromIndex, int toIndex, int m) {
467.1006 + for (int i = 0; i < fromIndex; i++) {
467.1007 + if (a[i] != 0xBABA) {
467.1008 + failed("Range sort changes left element on position " + i +
467.1009 + ": " + a[i] + ", must be " + 0xBABA);
467.1010 + }
467.1011 + }
467.1012 +
467.1013 + for (int i = fromIndex; i < toIndex - 1; i++) {
467.1014 + if (a[i] > a[i + 1]) {
467.1015 + failed(i, "" + a[i], "" + a[i + 1]);
467.1016 + }
467.1017 + }
467.1018 +
467.1019 + for (int i = toIndex; i < a.length; i++) {
467.1020 + if (a[i] != 0xDEDA) {
467.1021 + failed("Range sort changes right element on position " + i +
467.1022 + ": " + a[i] + ", must be " + 0xDEDA);
467.1023 + }
467.1024 + }
467.1025 + }
467.1026 +
467.1027 + private static void checkSubArray(byte[] a, int fromIndex, int toIndex, int m) {
467.1028 + for (int i = 0; i < fromIndex; i++) {
467.1029 + if (a[i] != (byte) 0xBABA) {
467.1030 + failed("Range sort changes left element on position " + i +
467.1031 + ": " + a[i] + ", must be " + 0xBABA);
467.1032 + }
467.1033 + }
467.1034 +
467.1035 + for (int i = fromIndex; i < toIndex - 1; i++) {
467.1036 + if (a[i] > a[i + 1]) {
467.1037 + failed(i, "" + a[i], "" + a[i + 1]);
467.1038 + }
467.1039 + }
467.1040 +
467.1041 + for (int i = toIndex; i < a.length; i++) {
467.1042 + if (a[i] != (byte) 0xDEDA) {
467.1043 + failed("Range sort changes right element on position " + i +
467.1044 + ": " + a[i] + ", must be " + 0xDEDA);
467.1045 + }
467.1046 + }
467.1047 + }
467.1048 +
467.1049 + private static void checkSubArray(long[] a, int fromIndex, int toIndex, int m) {
467.1050 + for (int i = 0; i < fromIndex; i++) {
467.1051 + if (a[i] != (long) 0xBABA) {
467.1052 + failed("Range sort changes left element on position " + i +
467.1053 + ": " + a[i] + ", must be " + 0xBABA);
467.1054 + }
467.1055 + }
467.1056 +
467.1057 + for (int i = fromIndex; i < toIndex - 1; i++) {
467.1058 + if (a[i] > a[i + 1]) {
467.1059 + failed(i, "" + a[i], "" + a[i + 1]);
467.1060 + }
467.1061 + }
467.1062 +
467.1063 + for (int i = toIndex; i < a.length; i++) {
467.1064 + if (a[i] != (long) 0xDEDA) {
467.1065 + failed("Range sort changes right element on position " + i +
467.1066 + ": " + a[i] + ", must be " + 0xDEDA);
467.1067 + }
467.1068 + }
467.1069 + }
467.1070 +
467.1071 + private static void checkSubArray(char[] a, int fromIndex, int toIndex, int m) {
467.1072 + for (int i = 0; i < fromIndex; i++) {
467.1073 + if (a[i] != (char) 0xBABA) {
467.1074 + failed("Range sort changes left element on position " + i +
467.1075 + ": " + a[i] + ", must be " + 0xBABA);
467.1076 + }
467.1077 + }
467.1078 +
467.1079 + for (int i = fromIndex; i < toIndex - 1; i++) {
467.1080 + if (a[i] > a[i + 1]) {
467.1081 + failed(i, "" + a[i], "" + a[i + 1]);
467.1082 + }
467.1083 + }
467.1084 +
467.1085 + for (int i = toIndex; i < a.length; i++) {
467.1086 + if (a[i] != (char) 0xDEDA) {
467.1087 + failed("Range sort changes right element on position " + i +
467.1088 + ": " + a[i] + ", must be " + 0xDEDA);
467.1089 + }
467.1090 + }
467.1091 + }
467.1092 +
467.1093 + private static void checkSubArray(short[] a, int fromIndex, int toIndex, int m) {
467.1094 + for (int i = 0; i < fromIndex; i++) {
467.1095 + if (a[i] != (short) 0xBABA) {
467.1096 + failed("Range sort changes left element on position " + i +
467.1097 + ": " + a[i] + ", must be " + 0xBABA);
467.1098 + }
467.1099 + }
467.1100 +
467.1101 + for (int i = fromIndex; i < toIndex - 1; i++) {
467.1102 + if (a[i] > a[i + 1]) {
467.1103 + failed(i, "" + a[i], "" + a[i + 1]);
467.1104 + }
467.1105 + }
467.1106 +
467.1107 + for (int i = toIndex; i < a.length; i++) {
467.1108 + if (a[i] != (short) 0xDEDA) {
467.1109 + failed("Range sort changes right element on position " + i +
467.1110 + ": " + a[i] + ", must be " + 0xDEDA);
467.1111 + }
467.1112 + }
467.1113 + }
467.1114 +
467.1115 + private static void checkSubArray(float[] a, int fromIndex, int toIndex, int m) {
467.1116 + for (int i = 0; i < fromIndex; i++) {
467.1117 + if (a[i] != (float) 0xBABA) {
467.1118 + failed("Range sort changes left element on position " + i +
467.1119 + ": " + a[i] + ", must be " + 0xBABA);
467.1120 + }
467.1121 + }
467.1122 +
467.1123 + for (int i = fromIndex; i < toIndex - 1; i++) {
467.1124 + if (a[i] > a[i + 1]) {
467.1125 + failed(i, "" + a[i], "" + a[i + 1]);
467.1126 + }
467.1127 + }
467.1128 +
467.1129 + for (int i = toIndex; i < a.length; i++) {
467.1130 + if (a[i] != (float) 0xDEDA) {
467.1131 + failed("Range sort changes right element on position " + i +
467.1132 + ": " + a[i] + ", must be " + 0xDEDA);
467.1133 + }
467.1134 + }
467.1135 + }
467.1136 +
467.1137 + private static void checkSubArray(double[] a, int fromIndex, int toIndex, int m) {
467.1138 + for (int i = 0; i < fromIndex; i++) {
467.1139 + if (a[i] != (double) 0xBABA) {
467.1140 + failed("Range sort changes left element on position " + i +
467.1141 + ": " + a[i] + ", must be " + 0xBABA);
467.1142 + }
467.1143 + }
467.1144 +
467.1145 + for (int i = fromIndex; i < toIndex - 1; i++) {
467.1146 + if (a[i] > a[i + 1]) {
467.1147 + failed(i, "" + a[i], "" + a[i + 1]);
467.1148 + }
467.1149 + }
467.1150 +
467.1151 + for (int i = toIndex; i < a.length; i++) {
467.1152 + if (a[i] != (double) 0xDEDA) {
467.1153 + failed("Range sort changes right element on position " + i +
467.1154 + ": " + a[i] + ", must be " + 0xDEDA);
467.1155 + }
467.1156 + }
467.1157 + }
467.1158 +
467.1159 + private static void sortRange(Object object, int m) {
467.1160 + if (object instanceof int[]) {
467.1161 + sortRange((int[]) object, m);
467.1162 + } else if (object instanceof long[]) {
467.1163 + sortRange((long[]) object, m);
467.1164 + } else if (object instanceof short[]) {
467.1165 + sortRange((short[]) object, m);
467.1166 + } else if (object instanceof byte[]) {
467.1167 + sortRange((byte[]) object, m);
467.1168 + } else if (object instanceof char[]) {
467.1169 + sortRange((char[]) object, m);
467.1170 + } else if (object instanceof float[]) {
467.1171 + sortRange((float[]) object, m);
467.1172 + } else if (object instanceof double[]) {
467.1173 + sortRange((double[]) object, m);
467.1174 + } else {
467.1175 + failed("Unknow type of array: " + object + " of class " +
467.1176 + object.getClass().getName());
467.1177 + }
467.1178 + }
467.1179 +
467.1180 + private static void sortEmpty(Object object) {
467.1181 + if (object instanceof int[]) {
467.1182 + Arrays.sort(new int [] {});
467.1183 + } else if (object instanceof long[]) {
467.1184 + Arrays.sort(new long [] {});
467.1185 + } else if (object instanceof short[]) {
467.1186 + Arrays.sort(new short [] {});
467.1187 + } else if (object instanceof byte[]) {
467.1188 + Arrays.sort(new byte [] {});
467.1189 + } else if (object instanceof char[]) {
467.1190 + Arrays.sort(new char [] {});
467.1191 + } else if (object instanceof float[]) {
467.1192 + Arrays.sort(new float [] {});
467.1193 + } else if (object instanceof double[]) {
467.1194 + Arrays.sort(new double [] {});
467.1195 + } else {
467.1196 + failed("Unknow type of array: " + object + " of class " +
467.1197 + object.getClass().getName());
467.1198 + }
467.1199 + }
467.1200 +
467.1201 + private static void sortRange(int[] a, int m) {
467.1202 + try {
467.1203 + Arrays.sort(a, m + 1, m);
467.1204 +
467.1205 + failed("Sort does not throw IllegalArgumentException " +
467.1206 + " as expected: fromIndex = " + (m + 1) +
467.1207 + " toIndex = " + m);
467.1208 + }
467.1209 + catch (IllegalArgumentException iae) {
467.1210 + try {
467.1211 + Arrays.sort(a, -m, a.length);
467.1212 +
467.1213 + failed("Sort does not throw ArrayIndexOutOfBoundsException " +
467.1214 + " as expected: fromIndex = " + (-m));
467.1215 + }
467.1216 + catch (ArrayIndexOutOfBoundsException aoe) {
467.1217 + try {
467.1218 + Arrays.sort(a, 0, a.length + m);
467.1219 +
467.1220 + failed("Sort does not throw ArrayIndexOutOfBoundsException " +
467.1221 + " as expected: toIndex = " + (a.length + m));
467.1222 + }
467.1223 + catch (ArrayIndexOutOfBoundsException aie) {
467.1224 + return;
467.1225 + }
467.1226 + }
467.1227 + }
467.1228 + }
467.1229 +
467.1230 + private static void sortRange(long[] a, int m) {
467.1231 + try {
467.1232 + Arrays.sort(a, m + 1, m);
467.1233 +
467.1234 + failed("Sort does not throw IllegalArgumentException " +
467.1235 + " as expected: fromIndex = " + (m + 1) +
467.1236 + " toIndex = " + m);
467.1237 + }
467.1238 + catch (IllegalArgumentException iae) {
467.1239 + try {
467.1240 + Arrays.sort(a, -m, a.length);
467.1241 +
467.1242 + failed("Sort does not throw ArrayIndexOutOfBoundsException " +
467.1243 + " as expected: fromIndex = " + (-m));
467.1244 + }
467.1245 + catch (ArrayIndexOutOfBoundsException aoe) {
467.1246 + try {
467.1247 + Arrays.sort(a, 0, a.length + m);
467.1248 +
467.1249 + failed("Sort does not throw ArrayIndexOutOfBoundsException " +
467.1250 + " as expected: toIndex = " + (a.length + m));
467.1251 + }
467.1252 + catch (ArrayIndexOutOfBoundsException aie) {
467.1253 + return;
467.1254 + }
467.1255 + }
467.1256 + }
467.1257 + }
467.1258 +
467.1259 + private static void sortRange(byte[] a, int m) {
467.1260 + try {
467.1261 + Arrays.sort(a, m + 1, m);
467.1262 +
467.1263 + failed("Sort does not throw IllegalArgumentException " +
467.1264 + " as expected: fromIndex = " + (m + 1) +
467.1265 + " toIndex = " + m);
467.1266 + }
467.1267 + catch (IllegalArgumentException iae) {
467.1268 + try {
467.1269 + Arrays.sort(a, -m, a.length);
467.1270 +
467.1271 + failed("Sort does not throw ArrayIndexOutOfBoundsException " +
467.1272 + " as expected: fromIndex = " + (-m));
467.1273 + }
467.1274 + catch (ArrayIndexOutOfBoundsException aoe) {
467.1275 + try {
467.1276 + Arrays.sort(a, 0, a.length + m);
467.1277 +
467.1278 + failed("Sort does not throw ArrayIndexOutOfBoundsException " +
467.1279 + " as expected: toIndex = " + (a.length + m));
467.1280 + }
467.1281 + catch (ArrayIndexOutOfBoundsException aie) {
467.1282 + return;
467.1283 + }
467.1284 + }
467.1285 + }
467.1286 + }
467.1287 +
467.1288 + private static void sortRange(short[] a, int m) {
467.1289 + try {
467.1290 + Arrays.sort(a, m + 1, m);
467.1291 +
467.1292 + failed("Sort does not throw IllegalArgumentException " +
467.1293 + " as expected: fromIndex = " + (m + 1) +
467.1294 + " toIndex = " + m);
467.1295 + }
467.1296 + catch (IllegalArgumentException iae) {
467.1297 + try {
467.1298 + Arrays.sort(a, -m, a.length);
467.1299 +
467.1300 + failed("Sort does not throw ArrayIndexOutOfBoundsException " +
467.1301 + " as expected: fromIndex = " + (-m));
467.1302 + }
467.1303 + catch (ArrayIndexOutOfBoundsException aoe) {
467.1304 + try {
467.1305 + Arrays.sort(a, 0, a.length + m);
467.1306 +
467.1307 + failed("Sort does not throw ArrayIndexOutOfBoundsException " +
467.1308 + " as expected: toIndex = " + (a.length + m));
467.1309 + }
467.1310 + catch (ArrayIndexOutOfBoundsException aie) {
467.1311 + return;
467.1312 + }
467.1313 + }
467.1314 + }
467.1315 + }
467.1316 +
467.1317 + private static void sortRange(char[] a, int m) {
467.1318 + try {
467.1319 + Arrays.sort(a, m + 1, m);
467.1320 +
467.1321 + failed("Sort does not throw IllegalArgumentException " +
467.1322 + " as expected: fromIndex = " + (m + 1) +
467.1323 + " toIndex = " + m);
467.1324 + }
467.1325 + catch (IllegalArgumentException iae) {
467.1326 + try {
467.1327 + Arrays.sort(a, -m, a.length);
467.1328 +
467.1329 + failed("Sort does not throw ArrayIndexOutOfBoundsException " +
467.1330 + " as expected: fromIndex = " + (-m));
467.1331 + }
467.1332 + catch (ArrayIndexOutOfBoundsException aoe) {
467.1333 + try {
467.1334 + Arrays.sort(a, 0, a.length + m);
467.1335 +
467.1336 + failed("Sort does not throw ArrayIndexOutOfBoundsException " +
467.1337 + " as expected: toIndex = " + (a.length + m));
467.1338 + }
467.1339 + catch (ArrayIndexOutOfBoundsException aie) {
467.1340 + return;
467.1341 + }
467.1342 + }
467.1343 + }
467.1344 + }
467.1345 +
467.1346 + private static void sortRange(float[] a, int m) {
467.1347 + try {
467.1348 + Arrays.sort(a, m + 1, m);
467.1349 +
467.1350 + failed("Sort does not throw IllegalArgumentException " +
467.1351 + " as expected: fromIndex = " + (m + 1) +
467.1352 + " toIndex = " + m);
467.1353 + }
467.1354 + catch (IllegalArgumentException iae) {
467.1355 + try {
467.1356 + Arrays.sort(a, -m, a.length);
467.1357 +
467.1358 + failed("Sort does not throw ArrayIndexOutOfBoundsException " +
467.1359 + " as expected: fromIndex = " + (-m));
467.1360 + }
467.1361 + catch (ArrayIndexOutOfBoundsException aoe) {
467.1362 + try {
467.1363 + Arrays.sort(a, 0, a.length + m);
467.1364 +
467.1365 + failed("Sort does not throw ArrayIndexOutOfBoundsException " +
467.1366 + " as expected: toIndex = " + (a.length + m));
467.1367 + }
467.1368 + catch (ArrayIndexOutOfBoundsException aie) {
467.1369 + return;
467.1370 + }
467.1371 + }
467.1372 + }
467.1373 + }
467.1374 +
467.1375 + private static void sortRange(double[] a, int m) {
467.1376 + try {
467.1377 + Arrays.sort(a, m + 1, m);
467.1378 +
467.1379 + failed("Sort does not throw IllegalArgumentException " +
467.1380 + " as expected: fromIndex = " + (m + 1) +
467.1381 + " toIndex = " + m);
467.1382 + }
467.1383 + catch (IllegalArgumentException iae) {
467.1384 + try {
467.1385 + Arrays.sort(a, -m, a.length);
467.1386 +
467.1387 + failed("Sort does not throw ArrayIndexOutOfBoundsException " +
467.1388 + " as expected: fromIndex = " + (-m));
467.1389 + }
467.1390 + catch (ArrayIndexOutOfBoundsException aoe) {
467.1391 + try {
467.1392 + Arrays.sort(a, 0, a.length + m);
467.1393 +
467.1394 + failed("Sort does not throw ArrayIndexOutOfBoundsException " +
467.1395 + " as expected: toIndex = " + (a.length + m));
467.1396 + }
467.1397 + catch (ArrayIndexOutOfBoundsException aie) {
467.1398 + return;
467.1399 + }
467.1400 + }
467.1401 + }
467.1402 + }
467.1403 +
467.1404 + private static void prepareRandom(int[] a) {
467.1405 + for (int i = 0; i < a.length; i++) {
467.1406 + a[i] = ourRandom.nextInt();
467.1407 + }
467.1408 + }
467.1409 +
467.1410 + private static void reset(long seed) {
467.1411 + ourRandom = new Random(seed);
467.1412 + ourFirst = 0;
467.1413 + ourSecond = 0;
467.1414 + }
467.1415 +
467.1416 + private static void outArr(int[] a) {
467.1417 + for (int i = 0; i < a.length; i++) {
467.1418 + out.print(a[i] + " ");
467.1419 + }
467.1420 + out.println();
467.1421 + out.println();
467.1422 + }
467.1423 +
467.1424 + private static void outArr(float[] a) {
467.1425 + for (int i = 0; i < a.length; i++) {
467.1426 + out.print(a[i] + " ");
467.1427 + }
467.1428 + out.println();
467.1429 + out.println();
467.1430 + }
467.1431 +
467.1432 + private static void outArr(double[] a) {
467.1433 + for (int i = 0; i < a.length; i++) {
467.1434 + out.print(a[i] + " ");
467.1435 + }
467.1436 + out.println();
467.1437 + out.println();
467.1438 + }
467.1439 +
467.1440 + private static int ourFirst;
467.1441 + private static int ourSecond;
467.1442 + private static Random ourRandom;
467.1443 +}
468.1 --- a/test/java/util/Collection/MOAT.java Mon Nov 23 10:04:47 2009 +0000
468.2 +++ b/test/java/util/Collection/MOAT.java Wed Nov 25 11:08:25 2009 -0800
468.3 @@ -421,8 +421,11 @@
468.4
468.5 private static void testQueue(Queue<Integer> q) {
468.6 q.clear();
468.7 - for (int i = 0; i < 5; i++)
468.8 + for (int i = 0; i < 5; i++) {
468.9 + testQueueAddRemove(q, null);
468.10 + testQueueAddRemove(q, 537);
468.11 q.add(i);
468.12 + }
468.13 equal(q.size(), 5);
468.14 checkFunctionalInvariants(q);
468.15 q.poll();
468.16 @@ -435,6 +438,216 @@
468.17 }
468.18 }
468.19
468.20 + private static void testQueueAddRemove(final Queue<Integer> q,
468.21 + final Integer e) {
468.22 + final List<Integer> originalContents = new ArrayList<Integer>(q);
468.23 + final boolean isEmpty = q.isEmpty();
468.24 + final boolean isList = (q instanceof List);
468.25 + final List asList = isList ? (List) q : null;
468.26 + check(!q.contains(e));
468.27 + try {
468.28 + q.add(e);
468.29 + } catch (NullPointerException npe) {
468.30 + check(e == null);
468.31 + return; // Null elements not supported
468.32 + }
468.33 + check(q.contains(e));
468.34 + check(q.remove(e));
468.35 + check(!q.contains(e));
468.36 + equal(new ArrayList<Integer>(q), originalContents);
468.37 +
468.38 + if (q instanceof Deque<?>) {
468.39 + final Deque<Integer> deq = (Deque<Integer>) q;
468.40 + final List<Integer> singleton = Collections.singletonList(e);
468.41 +
468.42 + // insert, query, remove element at head
468.43 + if (isEmpty) {
468.44 + THROWS(NoSuchElementException.class,
468.45 + new Fun(){void f(){ deq.getFirst(); }},
468.46 + new Fun(){void f(){ deq.element(); }},
468.47 + new Fun(){void f(){ deq.iterator().next(); }});
468.48 + check(deq.peekFirst() == null);
468.49 + check(deq.peek() == null);
468.50 + } else {
468.51 + check(deq.getFirst() != e);
468.52 + check(deq.element() != e);
468.53 + check(deq.iterator().next() != e);
468.54 + check(deq.peekFirst() != e);
468.55 + check(deq.peek() != e);
468.56 + }
468.57 + check(!deq.contains(e));
468.58 + check(!deq.removeFirstOccurrence(e));
468.59 + check(!deq.removeLastOccurrence(e));
468.60 + if (isList) {
468.61 + check(asList.indexOf(e) == -1);
468.62 + check(asList.lastIndexOf(e) == -1);
468.63 + }
468.64 + switch (rnd.nextInt(isList ? 4 : 3)) {
468.65 + case 0: deq.addFirst(e); break;
468.66 + case 1: check(deq.offerFirst(e)); break;
468.67 + case 2: deq.push(e); break;
468.68 + case 3: asList.add(0, e); break;
468.69 + default: throw new AssertionError();
468.70 + }
468.71 + check(deq.peekFirst() == e);
468.72 + check(deq.getFirst() == e);
468.73 + check(deq.element() == e);
468.74 + check(deq.peek() == e);
468.75 + check(deq.iterator().next() == e);
468.76 + check(deq.contains(e));
468.77 + if (isList) {
468.78 + check(asList.get(0) == e);
468.79 + check(asList.indexOf(e) == 0);
468.80 + check(asList.lastIndexOf(e) == 0);
468.81 + check(asList.subList(0, 1).equals(singleton));
468.82 + }
468.83 + switch (rnd.nextInt(isList ? 11 : 9)) {
468.84 + case 0: check(deq.pollFirst() == e); break;
468.85 + case 1: check(deq.removeFirst() == e); break;
468.86 + case 2: check(deq.remove() == e); break;
468.87 + case 3: check(deq.pop() == e); break;
468.88 + case 4: check(deq.removeFirstOccurrence(e)); break;
468.89 + case 5: check(deq.removeLastOccurrence(e)); break;
468.90 + case 6: check(deq.remove(e)); break;
468.91 + case 7: check(deq.removeAll(singleton)); break;
468.92 + case 8: Iterator it = deq.iterator(); it.next(); it.remove(); break;
468.93 + case 9: asList.remove(0); break;
468.94 + case 10: asList.subList(0, 1).clear(); break;
468.95 + default: throw new AssertionError();
468.96 + }
468.97 + if (isEmpty) {
468.98 + THROWS(NoSuchElementException.class,
468.99 + new Fun(){void f(){ deq.getFirst(); }},
468.100 + new Fun(){void f(){ deq.element(); }},
468.101 + new Fun(){void f(){ deq.iterator().next(); }});
468.102 + check(deq.peekFirst() == null);
468.103 + check(deq.peek() == null);
468.104 + } else {
468.105 + check(deq.getFirst() != e);
468.106 + check(deq.element() != e);
468.107 + check(deq.iterator().next() != e);
468.108 + check(deq.peekFirst() != e);
468.109 + check(deq.peek() != e);
468.110 + }
468.111 + check(!deq.contains(e));
468.112 + check(!deq.removeFirstOccurrence(e));
468.113 + check(!deq.removeLastOccurrence(e));
468.114 + if (isList) {
468.115 + check(isEmpty || asList.get(0) != e);
468.116 + check(asList.indexOf(e) == -1);
468.117 + check(asList.lastIndexOf(e) == -1);
468.118 + }
468.119 + equal(new ArrayList<Integer>(deq), originalContents);
468.120 +
468.121 + // insert, query, remove element at tail
468.122 + if (isEmpty) {
468.123 + check(deq.peekLast() == null);
468.124 + THROWS(NoSuchElementException.class,
468.125 + new Fun(){void f(){ deq.getLast(); }});
468.126 + } else {
468.127 + check(deq.peekLast() != e);
468.128 + check(deq.getLast() != e);
468.129 + }
468.130 + switch (rnd.nextInt(isList ? 6 : 4)) {
468.131 + case 0: deq.addLast(e); break;
468.132 + case 1: check(deq.offerLast(e)); break;
468.133 + case 2: check(deq.add(e)); break;
468.134 + case 3: deq.addAll(singleton); break;
468.135 + case 4: asList.addAll(deq.size(), singleton); break;
468.136 + case 5: asList.add(deq.size(), e); break;
468.137 + default: throw new AssertionError();
468.138 + }
468.139 + check(deq.peekLast() == e);
468.140 + check(deq.getLast() == e);
468.141 + check(deq.contains(e));
468.142 + if (isList) {
468.143 + ListIterator it = asList.listIterator(asList.size());
468.144 + check(it.previous() == e);
468.145 + check(asList.get(asList.size() - 1) == e);
468.146 + check(asList.indexOf(e) == asList.size() - 1);
468.147 + check(asList.lastIndexOf(e) == asList.size() - 1);
468.148 + int size = asList.size();
468.149 + check(asList.subList(size - 1, size).equals(singleton));
468.150 + }
468.151 + switch (rnd.nextInt(isList ? 8 : 6)) {
468.152 + case 0: check(deq.pollLast() == e); break;
468.153 + case 1: check(deq.removeLast() == e); break;
468.154 + case 2: check(deq.removeFirstOccurrence(e)); break;
468.155 + case 3: check(deq.removeLastOccurrence(e)); break;
468.156 + case 4: check(deq.remove(e)); break;
468.157 + case 5: check(deq.removeAll(singleton)); break;
468.158 + case 6: asList.remove(asList.size() - 1); break;
468.159 + case 7:
468.160 + ListIterator it = asList.listIterator(asList.size());
468.161 + it.previous();
468.162 + it.remove();
468.163 + break;
468.164 + default: throw new AssertionError();
468.165 + }
468.166 + if (isEmpty) {
468.167 + check(deq.peekLast() == null);
468.168 + THROWS(NoSuchElementException.class,
468.169 + new Fun(){void f(){ deq.getLast(); }});
468.170 + } else {
468.171 + check(deq.peekLast() != e);
468.172 + check(deq.getLast() != e);
468.173 + }
468.174 + check(!deq.contains(e));
468.175 + equal(new ArrayList<Integer>(deq), originalContents);
468.176 +
468.177 + // Test operations on empty deque
468.178 + switch (rnd.nextInt(isList ? 4 : 2)) {
468.179 + case 0: deq.clear(); break;
468.180 + case 1:
468.181 + Iterator it = deq.iterator();
468.182 + while (it.hasNext()) {
468.183 + it.next();
468.184 + it.remove();
468.185 + }
468.186 + break;
468.187 + case 2: asList.subList(0, asList.size()).clear(); break;
468.188 + case 3:
468.189 + ListIterator lit = asList.listIterator(asList.size());
468.190 + while (lit.hasPrevious()) {
468.191 + lit.previous();
468.192 + lit.remove();
468.193 + }
468.194 + break;
468.195 + default: throw new AssertionError();
468.196 + }
468.197 + testEmptyCollection(deq);
468.198 + check(!deq.iterator().hasNext());
468.199 + if (isList) {
468.200 + check(!asList.listIterator().hasPrevious());
468.201 + THROWS(NoSuchElementException.class,
468.202 + new Fun(){void f(){ asList.listIterator().previous(); }});
468.203 + }
468.204 + THROWS(NoSuchElementException.class,
468.205 + new Fun(){void f(){ deq.iterator().next(); }},
468.206 + new Fun(){void f(){ deq.element(); }},
468.207 + new Fun(){void f(){ deq.getFirst(); }},
468.208 + new Fun(){void f(){ deq.getLast(); }},
468.209 + new Fun(){void f(){ deq.pop(); }},
468.210 + new Fun(){void f(){ deq.remove(); }},
468.211 + new Fun(){void f(){ deq.removeFirst(); }},
468.212 + new Fun(){void f(){ deq.removeLast(); }});
468.213 +
468.214 + check(deq.poll() == null);
468.215 + check(deq.pollFirst() == null);
468.216 + check(deq.pollLast() == null);
468.217 + check(deq.peek() == null);
468.218 + check(deq.peekFirst() == null);
468.219 + check(deq.peekLast() == null);
468.220 + check(!deq.removeFirstOccurrence(e));
468.221 + check(!deq.removeLastOccurrence(e));
468.222 +
468.223 + check(deq.addAll(originalContents) == !isEmpty);
468.224 + equal(new ArrayList<Integer>(deq), originalContents);
468.225 + check(!deq.addAll(Collections.<Integer>emptyList()));
468.226 + equal(new ArrayList<Integer>(deq), originalContents);
468.227 + }
468.228 + }
468.229 +
468.230 private static void testQueueIteratorRemove(Queue<Integer> q) {
468.231 System.err.printf("testQueueIteratorRemove %s%n",
468.232 q.getClass().getSimpleName());
469.1 --- a/test/java/util/Objects/BasicObjectsTest.java Mon Nov 23 10:04:47 2009 +0000
469.2 +++ b/test/java/util/Objects/BasicObjectsTest.java Wed Nov 25 11:08:25 2009 -0800
469.3 @@ -23,7 +23,7 @@
469.4
469.5 /*
469.6 * @test
469.7 - * @bug 6797535
469.8 + * @bug 6797535 6889858 6891113
469.9 * @summary Basic tests for methods in java.util.Objects
469.10 * @author Joseph D. Darcy
469.11 */
469.12 @@ -34,8 +34,11 @@
469.13 public static void main(String... args) {
469.14 int errors = 0;
469.15 errors += testEquals();
469.16 + errors += testDeepEquals();
469.17 errors += testHashCode();
469.18 + errors += testHash();
469.19 errors += testToString();
469.20 + errors += testToString2();
469.21 errors += testCompare();
469.22 errors += testNonNull();
469.23 if (errors > 0 )
469.24 @@ -60,6 +63,36 @@
469.25 return errors;
469.26 }
469.27
469.28 + private static int testDeepEquals() {
469.29 + int errors = 0;
469.30 + Object[] values = {null,
469.31 + null, // Change to values later
469.32 + new byte[] {(byte)1},
469.33 + new short[] {(short)1},
469.34 + new int[] {1},
469.35 + new long[] {1L},
469.36 + new char[] {(char)1},
469.37 + new float[] {1.0f},
469.38 + new double[]{1.0d},
469.39 + new String[]{"one"}};
469.40 + values[1] = values;
469.41 +
469.42 + for(int i = 0; i < values.length; i++)
469.43 + for(int j = 0; j < values.length; j++) {
469.44 + boolean expected = (i == j);
469.45 + Object a = values[i];
469.46 + Object b = values[j];
469.47 + boolean result = Objects.deepEquals(a, b);
469.48 + if (result != expected) {
469.49 + errors++;
469.50 + System.err.printf("When equating %s to %s, got %b instead of %b%n.",
469.51 + a, b, result, expected);
469.52 + }
469.53 + }
469.54 +
469.55 + return errors;
469.56 + }
469.57 +
469.58 private static int testHashCode() {
469.59 int errors = 0;
469.60 errors += (Objects.hashCode(null) == 0 ) ? 0 : 1;
469.61 @@ -68,6 +101,19 @@
469.62 return errors;
469.63 }
469.64
469.65 + private static int testHash() {
469.66 + int errors = 0;
469.67 +
469.68 + Object[] data = new String[]{"perfect", "ham", "THC"};
469.69 +
469.70 + errors += ((Objects.hash((Object[])null) == 0) ? 0 : 1);
469.71 +
469.72 + errors += (Objects.hash("perfect", "ham", "THC") ==
469.73 + Arrays.hashCode(data)) ? 0 : 1;
469.74 +
469.75 + return errors;
469.76 + }
469.77 +
469.78 private static int testToString() {
469.79 int errors = 0;
469.80 errors += ("null".equals(Objects.toString(null)) ) ? 0 : 1;
469.81 @@ -76,6 +122,14 @@
469.82 return errors;
469.83 }
469.84
469.85 + private static int testToString2() {
469.86 + int errors = 0;
469.87 + String s = "not the default";
469.88 + errors += (s.equals(Objects.toString(null, s)) ) ? 0 : 1;
469.89 + errors += (s.equals(Objects.toString(s, "another string")) ) ? 0 : 1;
469.90 + return errors;
469.91 + }
469.92 +
469.93 private static int testCompare() {
469.94 int errors = 0;
469.95 String[] values = {"e. e. cummings", "zzz"};
470.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
470.2 +++ b/test/java/util/logging/PlatformLoggingMXBean/PlatformLoggingMXBeanTest.java Wed Nov 25 11:08:25 2009 -0800
470.3 @@ -0,0 +1,279 @@
470.4 +/*
470.5 + * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
470.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
470.7 + *
470.8 + * This code is free software; you can redistribute it and/or modify it
470.9 + * under the terms of the GNU General Public License version 2 only, as
470.10 + * published by the Free Software Foundation.
470.11 + *
470.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
470.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
470.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
470.15 + * version 2 for more details (a copy is included in the LICENSE file that
470.16 + * accompanied this code).
470.17 + *
470.18 + * You should have received a copy of the GNU General Public License version
470.19 + * 2 along with this work; if not, write to the Free Software Foundation,
470.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
470.21 + *
470.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
470.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
470.24 + * have any questions.
470.25 + */
470.26 +
470.27 +/*
470.28 + * @test
470.29 + * @bug 6876135
470.30 + *
470.31 + * @summary Test PlatformLoggingMXBean
470.32 + * This test performs similar testing as LoggingMXBeanTest.
470.33 + *
470.34 + * @build PlatformLoggingMXBeanTest
470.35 + * @run main PlatformLoggingMXBeanTest
470.36 + */
470.37 +
470.38 +import javax.management.*;
470.39 +import java.lang.management.ManagementFactory;
470.40 +import java.util.logging.*;
470.41 +import java.util.List;
470.42 +
470.43 +public class PlatformLoggingMXBeanTest
470.44 +{
470.45 +
470.46 + ObjectName objectName = null;
470.47 + static String LOGGER_NAME_1 = "com.sun.management.Logger1";
470.48 + static String LOGGER_NAME_2 = "com.sun.management.Logger2";
470.49 +
470.50 + public PlatformLoggingMXBeanTest() throws Exception {
470.51 + }
470.52 +
470.53 + private void runTest(PlatformLoggingMXBean mBean) throws Exception {
470.54 +
470.55 + /*
470.56 + * Create the MBeanServeri, register the PlatformLoggingMXBean
470.57 + */
470.58 + System.out.println( "***************************************************" );
470.59 + System.out.println( "********** PlatformLoggingMXBean Unit Test **********" );
470.60 + System.out.println( "***************************************************" );
470.61 + System.out.println( "" );
470.62 + System.out.println( "*******************************" );
470.63 + System.out.println( "*********** Phase 1 ***********" );
470.64 + System.out.println( "*******************************" );
470.65 + System.out.println( " Creating MBeanServer " );
470.66 + System.out.print( " Register PlatformLoggingMXBean: " );
470.67 + MBeanServer mbs = MBeanServerFactory.createMBeanServer();
470.68 + String[] list = new String[0];
470.69 +
470.70 + try {
470.71 + objectName = new ObjectName(LogManager.LOGGING_MXBEAN_NAME);
470.72 + mbs.registerMBean( mBean, objectName );
470.73 + }
470.74 + catch ( Exception e ) {
470.75 + System.out.println( "FAILED" );
470.76 + throw e;
470.77 + }
470.78 + System.out.println( "PASSED" );
470.79 + System.out.println("");
470.80 +
470.81 + /*
470.82 + * Access our MBean to get the current list of Loggers
470.83 + */
470.84 + System.out.println( "*******************************" );
470.85 + System.out.println( "*********** Phase 2 ***********" );
470.86 + System.out.println( "*******************************" );
470.87 + System.out.println( " Test Logger Name retrieval (getLoggerNames) " );
470.88 + // check that Level object are returned properly
470.89 + try {
470.90 + list = (String[]) mbs.getAttribute( objectName, "LoggerNames" );
470.91 + }
470.92 + catch ( Exception e ) {
470.93 + System.out.println(" : FAILED" );
470.94 + throw e;
470.95 + }
470.96 +
470.97 + /*
470.98 + * Dump the list of Loggers already present, if any
470.99 + */
470.100 + Object[] params = new Object[1];
470.101 + String[] signature = new String[1];
470.102 + Level l;
470.103 +
470.104 + if ( list == null ) {
470.105 + System.out.println(" : PASSED. No Standard Loggers Present" );
470.106 + System.out.println("");
470.107 + }
470.108 + else {
470.109 + System.out.println(" : PASSED. There are " + list.length + " Loggers Present" );
470.110 + System.out.println("");
470.111 + System.out.println( "*******************************" );
470.112 + System.out.println( "*********** Phase 2B **********" );
470.113 + System.out.println( "*******************************" );
470.114 + System.out.println( " Examine Existing Loggers" );
470.115 + for ( int i = 0; i < list.length; i++ ) {
470.116 + try {
470.117 + params[0] = list[i];
470.118 + signature[0] = "java.lang.String";
470.119 + String levelName = (String) mbs.invoke( objectName, "getLoggerLevel", params, signature );
470.120 + System.out.println(" : Logger #" + i + " = " + list[i] );
470.121 + System.out.println(" : Level = " + levelName );
470.122 + }
470.123 + catch ( Exception e ) {
470.124 + System.out.println(" : FAILED" );
470.125 + throw e;
470.126 + }
470.127 + }
470.128 + System.out.println(" : PASSED" );
470.129 + }
470.130 +
470.131 + /*
470.132 + * Create two new loggers to the list of Loggers already present
470.133 + */
470.134 + System.out.println("");
470.135 + System.out.println( "*******************************" );
470.136 + System.out.println( "*********** Phase 3 ***********" );
470.137 + System.out.println( "*******************************" );
470.138 + System.out.println( " Create and test new Loggers" );
470.139 + Logger logger1 = Logger.getLogger( LOGGER_NAME_1 );
470.140 + Logger logger2 = Logger.getLogger( LOGGER_NAME_2 );
470.141 +
470.142 + // check that Level object are returned properly
470.143 + try {
470.144 + list = (String[]) mbs.getAttribute( objectName, "LoggerNames" );
470.145 + }
470.146 + catch ( Exception e ) {
470.147 + System.out.println(" : FAILED" );
470.148 + throw e;
470.149 + }
470.150 +
470.151 + /*
470.152 + * Check for the existence of our new Loggers
470.153 + */
470.154 + boolean log1 = false, log2 = false;
470.155 +
470.156 + if ( list == null || list.length < 2 ) {
470.157 + System.out.println(" : FAILED. Could not Detect the presense of the new Loggers" );
470.158 + throw new RuntimeException(
470.159 + "Could not Detect the presense of the new Loggers");
470.160 + }
470.161 + else {
470.162 + for ( int i = 0; i < list.length; i++ ) {
470.163 + if ( list[i].equals( LOGGER_NAME_1 ) ) {
470.164 + log1 = true;
470.165 + System.out.println( " : Found new Logger : " + list[i] );
470.166 + }
470.167 + if ( list[i].equals( LOGGER_NAME_2 ) ) {
470.168 + log2 = true;
470.169 + System.out.println( " : Found new Logger : " + list[i] );
470.170 + }
470.171 + }
470.172 + if ( log1 && log2 )
470.173 + System.out.println( " : PASSED." );
470.174 + else {
470.175 + System.out.println( " : FAILED. Could not Detect the new Loggers." );
470.176 + throw new RuntimeException(
470.177 + "Could not Detect the presense of the new Loggers");
470.178 + }
470.179 + }
470.180 +
470.181 + /*
470.182 + * Set a new Logging levels and check that it succeeded
470.183 + */
470.184 + System.out.println("");
470.185 + System.out.println( "*******************************" );
470.186 + System.out.println( "*********** Phase 4 ***********" );
470.187 + System.out.println( "*******************************" );
470.188 + System.out.println( " Set and Check the Logger Level" );
470.189 + log1 = false;
470.190 + log2 = false;
470.191 + try {
470.192 + // Set the level of logger1 to ALL
470.193 + params = new Object[2];
470.194 + signature = new String[2];
470.195 + params[0] = LOGGER_NAME_1;
470.196 + params[1] = Level.ALL.getName();
470.197 + signature[0] = "java.lang.String";
470.198 + signature[1] = "java.lang.String";
470.199 + mbs.invoke( objectName, "setLoggerLevel", params, signature );
470.200 +
470.201 + // Set the level of logger2 to FINER
470.202 + params[0] = LOGGER_NAME_2;
470.203 + params[1] = Level.FINER.getName();
470.204 + mbs.invoke( objectName, "setLoggerLevel", params, signature );
470.205 +
470.206 + // Okay read back the Level from Logger1. Should be ALL
470.207 + params = new Object[1];
470.208 + signature = new String[1];
470.209 + params[0] = LOGGER_NAME_1;
470.210 + signature[0] = "java.lang.String";
470.211 + String levelName = (String) mbs.invoke( objectName, "getLoggerLevel", params, signature );
470.212 + l = Level.parse(levelName);
470.213 + System.out.print(" Logger1: " );
470.214 + if ( l.equals( l.ALL ) ) {
470.215 + System.out.println("Level Set to ALL: PASSED" );
470.216 + log1 = true;
470.217 + }
470.218 + else {
470.219 + System.out.println("Level Set to ALL: FAILED" );
470.220 + throw new RuntimeException(
470.221 + "Level Set to ALL but returned " + l.toString());
470.222 + }
470.223 +
470.224 + // Okay read back the Level from Logger2. Should be FINER
470.225 + params = new Object[1];
470.226 + signature = new String[1];
470.227 + params[0] = LOGGER_NAME_2;
470.228 + signature[0] = "java.lang.String";
470.229 + levelName = (String) mbs.invoke( objectName, "getLoggerLevel", params, signature );
470.230 + l = Level.parse(levelName);
470.231 + System.out.print(" Logger2: " );
470.232 + if ( l.equals( l.FINER ) ) {
470.233 + System.out.println("Level Set to FINER: PASSED" );
470.234 + log2 = true;
470.235 + }
470.236 + else {
470.237 + System.out.println("Level Set to FINER: FAILED" );
470.238 + throw new RuntimeException(
470.239 + "Level Set to FINER but returned " + l.toString());
470.240 + }
470.241 + }
470.242 + catch ( Exception e ) {
470.243 + throw e;
470.244 + }
470.245 +
470.246 + System.out.println( "" );
470.247 + System.out.println( "***************************************************" );
470.248 + System.out.println( "***************** All Tests Passed ****************" );
470.249 + System.out.println( "***************************************************" );
470.250 + }
470.251 +
470.252 + public static void main(String[] argv) throws Exception {
470.253 + List<PlatformLoggingMXBean> result =
470.254 + ManagementFactory.getPlatformMXBeans(PlatformLoggingMXBean.class);
470.255 + if (result.size() != 1) {
470.256 + throw new RuntimeException("Unexpected number of PlatformLoggingMXBean instances: " +
470.257 + result.size());
470.258 + }
470.259 +
470.260 + PlatformLoggingMXBean mbean = result.get(0);
470.261 + ObjectName objname = mbean.getObjectName();
470.262 + if (!objname.equals(new ObjectName(LogManager.LOGGING_MXBEAN_NAME))) {
470.263 + throw new RuntimeException("Invalid ObjectName " + objname);
470.264 + }
470.265 +
470.266 + // check if the PlatformLoggingMXBean is registered in the platform MBeanServer
470.267 + MBeanServer platformMBS = ManagementFactory.getPlatformMBeanServer();
470.268 + ObjectName objName = new ObjectName(LogManager.LOGGING_MXBEAN_NAME);
470.269 + // We could call mbs.isRegistered(objName) here.
470.270 + // Calling getMBeanInfo will throw exception if not found.
470.271 + platformMBS.getMBeanInfo(objName);
470.272 +
470.273 + if (!platformMBS.isInstanceOf(objName, "java.util.logging.PlatformLoggingMXBean") ||
470.274 + !platformMBS.isInstanceOf(objName, "java.util.logging.LoggingMXBean")) {
470.275 + throw new RuntimeException(objName + " is of unexpected type");
470.276 + }
470.277 +
470.278 + // test if PlatformLoggingMXBean works properly in a MBeanServer
470.279 + PlatformLoggingMXBeanTest test = new PlatformLoggingMXBeanTest();
470.280 + test.runTest(mbean);
470.281 + }
470.282 +}
471.1 --- a/test/java/util/regex/RegExTest.java Mon Nov 23 10:04:47 2009 +0000
471.2 +++ b/test/java/util/regex/RegExTest.java Wed Nov 25 11:08:25 2009 -0800
471.3 @@ -32,7 +32,7 @@
471.4 * 4872664 4803179 4892980 4900747 4945394 4938995 4979006 4994840 4997476
471.5 * 5013885 5003322 4988891 5098443 5110268 6173522 4829857 5027748 6376940
471.6 * 6358731 6178785 6284152 6231989 6497148 6486934 6233084 6504326 6635133
471.7 - * 6350801 6676425
471.8 + * 6350801 6676425 6878475
471.9 */
471.10
471.11 import java.util.regex.*;
471.12 @@ -3389,9 +3389,9 @@
471.13 "gname",
471.14 "yyy");
471.15
471.16 - check(Pattern.compile("x+(?<8gname>y+)z+"),
471.17 + check(Pattern.compile("x+(?<gname8>y+)z+"),
471.18 "xxxyyyzzz",
471.19 - "8gname",
471.20 + "gname8",
471.21 "yyy");
471.22
471.23 //backref
471.24 @@ -3430,81 +3430,82 @@
471.25 //replaceFirst/All
471.26 checkReplaceFirst("(?<gn>ab)(c*)",
471.27 "abccczzzabcczzzabccc",
471.28 - "$<gn>",
471.29 + "${gn}",
471.30 "abzzzabcczzzabccc");
471.31
471.32 checkReplaceAll("(?<gn>ab)(c*)",
471.33 "abccczzzabcczzzabccc",
471.34 - "$<gn>",
471.35 + "${gn}",
471.36 "abzzzabzzzab");
471.37
471.38
471.39 checkReplaceFirst("(?<gn>ab)(c*)",
471.40 "zzzabccczzzabcczzzabccczzz",
471.41 - "$<gn>",
471.42 + "${gn}",
471.43 "zzzabzzzabcczzzabccczzz");
471.44
471.45 checkReplaceAll("(?<gn>ab)(c*)",
471.46 "zzzabccczzzabcczzzabccczzz",
471.47 - "$<gn>",
471.48 + "${gn}",
471.49 "zzzabzzzabzzzabzzz");
471.50
471.51 checkReplaceFirst("(?<gn1>ab)(?<gn2>c*)",
471.52 "zzzabccczzzabcczzzabccczzz",
471.53 - "$<gn2>",
471.54 + "${gn2}",
471.55 "zzzccczzzabcczzzabccczzz");
471.56
471.57 checkReplaceAll("(?<gn1>ab)(?<gn2>c*)",
471.58 "zzzabccczzzabcczzzabccczzz",
471.59 - "$<gn2>",
471.60 + "${gn2}",
471.61 "zzzccczzzcczzzccczzz");
471.62
471.63 //toSupplementaries("(ab)(c*)"));
471.64 checkReplaceFirst("(?<gn1>" + toSupplementaries("ab") +
471.65 ")(?<gn2>" + toSupplementaries("c") + "*)",
471.66 toSupplementaries("abccczzzabcczzzabccc"),
471.67 - "$<gn1>",
471.68 + "${gn1}",
471.69 toSupplementaries("abzzzabcczzzabccc"));
471.70
471.71
471.72 checkReplaceAll("(?<gn1>" + toSupplementaries("ab") +
471.73 ")(?<gn2>" + toSupplementaries("c") + "*)",
471.74 toSupplementaries("abccczzzabcczzzabccc"),
471.75 - "$<gn1>",
471.76 + "${gn1}",
471.77 toSupplementaries("abzzzabzzzab"));
471.78
471.79 checkReplaceFirst("(?<gn1>" + toSupplementaries("ab") +
471.80 ")(?<gn2>" + toSupplementaries("c") + "*)",
471.81 toSupplementaries("abccczzzabcczzzabccc"),
471.82 - "$<gn2>",
471.83 + "${gn2}",
471.84 toSupplementaries("ccczzzabcczzzabccc"));
471.85
471.86
471.87 checkReplaceAll("(?<gn1>" + toSupplementaries("ab") +
471.88 ")(?<gn2>" + toSupplementaries("c") + "*)",
471.89 toSupplementaries("abccczzzabcczzzabccc"),
471.90 - "$<gn2>",
471.91 + "${gn2}",
471.92 toSupplementaries("ccczzzcczzzccc"));
471.93
471.94 checkReplaceFirst("(?<dog>Dog)AndCat",
471.95 "zzzDogAndCatzzzDogAndCatzzz",
471.96 - "$<dog>",
471.97 + "${dog}",
471.98 "zzzDogzzzDogAndCatzzz");
471.99
471.100
471.101 checkReplaceAll("(?<dog>Dog)AndCat",
471.102 "zzzDogAndCatzzzDogAndCatzzz",
471.103 - "$<dog>",
471.104 + "${dog}",
471.105 "zzzDogzzzDogzzz");
471.106
471.107 // backref in Matcher & String
471.108 - if (!"abcdefghij".replaceFirst("cd(?<gn>ef)gh", "$<gn>").equals("abefij") ||
471.109 - !"abbbcbdbefgh".replaceAll("(?<gn>[a-e])b", "$<gn>").equals("abcdefgh"))
471.110 + if (!"abcdefghij".replaceFirst("cd(?<gn>ef)gh", "${gn}").equals("abefij") ||
471.111 + !"abbbcbdbefgh".replaceAll("(?<gn>[a-e])b", "${gn}").equals("abcdefgh"))
471.112 failCount++;
471.113
471.114 // negative
471.115 checkExpectedFail("(?<groupnamehasnoascii.in>abc)(def)");
471.116 checkExpectedFail("(?<groupnamehasnoascii_in>abc)(def)");
471.117 + checkExpectedFail("(?<6groupnamestartswithdigit>abc)(def)");
471.118 checkExpectedFail("(?<gname>abc)(def)\\k<gnameX>");
471.119 checkExpectedFail("(?<gname>abc)(?<gname>def)\\k<gnameX>");
471.120 checkExpectedFail(Pattern.compile("(?<gname>abc)(def)").matcher("abcdef"),
472.1 --- a/test/java/util/zip/Bounds.java Mon Nov 23 10:04:47 2009 +0000
472.2 +++ b/test/java/util/zip/Bounds.java Wed Nov 25 11:08:25 2009 -0800
472.3 @@ -22,7 +22,7 @@
472.4 */
472.5
472.6 /* @test
472.7 - * @bug 4811913
472.8 + * @bug 4811913 6894950
472.9 * @summary Test bounds checking in zip package
472.10 */
472.11
473.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
473.2 +++ b/test/java/util/zip/InflateIn_DeflateOut.java Wed Nov 25 11:08:25 2009 -0800
473.3 @@ -0,0 +1,251 @@
473.4 +/*
473.5 + * Copyright 2009 Google, Inc. All Rights Reserved.
473.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
473.7 + *
473.8 + * This code is free software; you can redistribute it and/or modify it
473.9 + * under the terms of the GNU General Public License version 2 only, as
473.10 + * published by the Free Software Foundation.
473.11 + *
473.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
473.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
473.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
473.15 + * version 2 for more details (a copy is included in the LICENSE file that
473.16 + * accompanied this code).
473.17 + *
473.18 + * You should have received a copy of the GNU General Public License version
473.19 + * 2 along with this work; if not, write to the Free Software Foundation,
473.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
473.21 + *
473.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
473.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
473.24 + * have any questions.
473.25 + */
473.26 +
473.27 +/**
473.28 + * @test
473.29 + * @bug 4206909
473.30 + * @summary Test basic functionality of DeflaterOutputStream and InflaterInputStream including flush
473.31 + */
473.32 +
473.33 +import java.io.*;
473.34 +import java.util.*;
473.35 +import java.util.zip.*;
473.36 +
473.37 +public class InflateIn_DeflateOut {
473.38 +
473.39 + private static class PairedInputStream extends ByteArrayInputStream {
473.40 + private PairedOutputStream out = null;
473.41 + private Random random;
473.42 +
473.43 + public PairedInputStream() {
473.44 + // The ByteArrayInputStream needs to start with a buffer, but we
473.45 + // need to set it to have no data
473.46 + super(new byte[1]);
473.47 + count = 0;
473.48 + pos = 0;
473.49 + random = new Random(new Date().getTime());
473.50 + }
473.51 +
473.52 + public void setPairedOutputStream(PairedOutputStream out) {
473.53 + this.out = out;
473.54 + }
473.55 +
473.56 + private void maybeFlushPair() {
473.57 + if (random.nextInt(100) < 10) {
473.58 + out.flush();
473.59 + }
473.60 + }
473.61 +
473.62 + public int read() {
473.63 + maybeFlushPair();
473.64 + return super.read();
473.65 + }
473.66 +
473.67 + public int read(byte b[], int off, int len) {
473.68 + maybeFlushPair();
473.69 + return super.read(b, off, len);
473.70 + }
473.71 +
473.72 + public void addBytes(byte[] bytes, int len) {
473.73 + int oldavail = count - pos;
473.74 + int newcount = oldavail + len;
473.75 + byte[] newbuf = new byte[newcount];
473.76 + System.arraycopy(buf, pos, newbuf, 0, oldavail);
473.77 + System.arraycopy(bytes, 0, newbuf, oldavail, len);
473.78 + pos = 0;
473.79 + count = newcount;
473.80 + buf = newbuf;
473.81 + }
473.82 + }
473.83 +
473.84 + private static class PairedOutputStream extends ByteArrayOutputStream {
473.85 + private PairedInputStream pairedStream = null;
473.86 +
473.87 + public PairedOutputStream(PairedInputStream inputPair) {
473.88 + super();
473.89 + this.pairedStream = inputPair;
473.90 + }
473.91 +
473.92 + public void flush() {
473.93 + if (count > 0) {
473.94 + pairedStream.addBytes(buf, count);
473.95 + reset();
473.96 + }
473.97 + }
473.98 +
473.99 + public void close() {
473.100 + flush();
473.101 + }
473.102 + }
473.103 +
473.104 + private static boolean readFully(InputStream in, byte[] buf, int length)
473.105 + throws IOException {
473.106 + int pos = 0;
473.107 + int n;
473.108 + while ((n = in.read(buf, pos, length - pos)) > 0) {
473.109 + pos += n;
473.110 + if (pos == length) return true;
473.111 + }
473.112 + return false;
473.113 + }
473.114 +
473.115 + private static boolean readLineIfAvailable(InputStream in, StringBuilder sb)
473.116 + throws IOException {
473.117 + try {
473.118 + while (in.available() > 0) {
473.119 + int i = in.read();
473.120 + if (i < 0) break;
473.121 + char c = (char) (((byte) i) & 0xff);
473.122 + sb.append(c);
473.123 + if (c == '\n') return true;
473.124 + }
473.125 + } catch (EOFException e) {
473.126 + // empty
473.127 + }
473.128 + return false;
473.129 + }
473.130 +
473.131 + /** Check that written, closed and read */
473.132 + private static void WriteCloseRead() throws Throwable {
473.133 + Random random = new Random(new Date().getTime());
473.134 +
473.135 + PairedInputStream pis = new PairedInputStream();
473.136 + InflaterInputStream iis = new InflaterInputStream(pis);
473.137 +
473.138 + PairedOutputStream pos = new PairedOutputStream(pis);
473.139 + pis.setPairedOutputStream(pos);
473.140 + DeflaterOutputStream dos = new DeflaterOutputStream(pos, true);
473.141 +
473.142 + byte[] data = new byte[random.nextInt(1024 * 1024)];
473.143 + byte[] buf = new byte[data.length];
473.144 + random.nextBytes(data);
473.145 +
473.146 + dos.write(data);
473.147 + dos.close();
473.148 + check(readFully(iis, buf, buf.length));
473.149 + check(Arrays.equals(data, buf));
473.150 + }
473.151 +
473.152 + /** Check that written, flushed and read */
473.153 + private static void WriteFlushRead() throws Throwable {
473.154 + Random random = new Random(new Date().getTime());
473.155 +
473.156 + PairedInputStream pis = new PairedInputStream();
473.157 + InflaterInputStream iis = new InflaterInputStream(pis);
473.158 +
473.159 + PairedOutputStream pos = new PairedOutputStream(pis);
473.160 + pis.setPairedOutputStream(pos);
473.161 + DeflaterOutputStream dos = new DeflaterOutputStream(pos, true);
473.162 +
473.163 + // Large writes
473.164 + for (int x = 0; x < 200 ; x++) {
473.165 + // byte[] data = new byte[random.nextInt(1024 * 1024)];
473.166 + byte[] data = new byte[1024];
473.167 + byte[] buf = new byte[data.length];
473.168 + random.nextBytes(data);
473.169 +
473.170 + dos.write(data);
473.171 + dos.flush();
473.172 + check(readFully(iis, buf, buf.length));
473.173 + check(Arrays.equals(data, buf));
473.174 + }
473.175 +
473.176 + // Small writes
473.177 + for (int x = 0; x < 2000 ; x++) {
473.178 + byte[] data = new byte[random.nextInt(20) + 10];
473.179 + byte[] buf = new byte[data.length];
473.180 + random.nextBytes(data);
473.181 +
473.182 + dos.write(data);
473.183 + dos.flush();
473.184 + if (!readFully(iis, buf, buf.length)) {
473.185 + fail("Didn't read full buffer of " + buf.length);
473.186 + }
473.187 + check(Arrays.equals(data, buf));
473.188 + }
473.189 +
473.190 + String quit = "QUIT\r\n";
473.191 +
473.192 + // Close it out
473.193 + dos.write(quit.getBytes());
473.194 + dos.close();
473.195 +
473.196 + StringBuilder sb = new StringBuilder();
473.197 + check(readLineIfAvailable(iis, sb));
473.198 + equal(sb.toString(), quit);
473.199 + }
473.200 +
473.201 + /** Validate that we need to use flush at least once on a line
473.202 + * oriented protocol */
473.203 + private static void LineOrientedProtocol() throws Throwable {
473.204 + PairedInputStream pis = new PairedInputStream();
473.205 + InflaterInputStream iis = new InflaterInputStream(pis);
473.206 +
473.207 + PairedOutputStream pos = new PairedOutputStream(pis);
473.208 + pis.setPairedOutputStream(pos);
473.209 + DeflaterOutputStream dos = new DeflaterOutputStream(pos, true);
473.210 +
473.211 + boolean flushed = false;
473.212 + int count = 0;
473.213 +
473.214 + // Do at least a certain number of lines, but too many without a
473.215 + // flush means this test isn't testing anything
473.216 + while ((count < 10 && flushed) || (count < 1000 && !flushed)) {
473.217 + String command = "PING " + count + "\r\n";
473.218 + dos.write(command.getBytes());
473.219 +
473.220 + StringBuilder buf = new StringBuilder();
473.221 + if (!readLineIfAvailable(iis, buf)) {
473.222 + flushed = true;
473.223 + dos.flush();
473.224 + check(readLineIfAvailable(iis, buf));
473.225 + }
473.226 + equal(buf.toString(), command);
473.227 + count++;
473.228 + }
473.229 + check(flushed);
473.230 + }
473.231 +
473.232 + public static void realMain(String[] args) throws Throwable {
473.233 + WriteCloseRead();
473.234 +
473.235 + WriteFlushRead();
473.236 +
473.237 + LineOrientedProtocol();
473.238 + }
473.239 +
473.240 + //--------------------- Infrastructure ---------------------------
473.241 + static volatile int passed = 0, failed = 0;
473.242 + static void pass() {passed++;}
473.243 + static void fail() {failed++; Thread.dumpStack();}
473.244 + static void fail(String msg) {System.out.println(msg); fail();}
473.245 + static void unexpected(Throwable t) {failed++; t.printStackTrace();}
473.246 + static void check(boolean cond) {if (cond) pass(); else fail();}
473.247 + static void equal(Object x, Object y) {
473.248 + if (x == null ? y == null : x.equals(y)) pass();
473.249 + else fail(x + " not equal to " + y);}
473.250 + public static void main(String[] args) throws Throwable {
473.251 + try {realMain(args);} catch (Throwable t) {unexpected(t);}
473.252 + System.out.println("\nPassed = " + passed + " failed = " + failed);
473.253 + if (failed > 0) throw new AssertionError("Some tests failed");}
473.254 +}
474.1 --- a/test/javax/management/Introspector/AnnotatedMBeanTest.java Mon Nov 23 10:04:47 2009 +0000
474.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
474.3 @@ -1,337 +0,0 @@
474.4 -/*
474.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
474.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
474.7 - *
474.8 - * This code is free software; you can redistribute it and/or modify it
474.9 - * under the terms of the GNU General Public License version 2 only, as
474.10 - * published by the Free Software Foundation.
474.11 - *
474.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
474.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
474.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
474.15 - * version 2 for more details (a copy is included in the LICENSE file that
474.16 - * accompanied this code).
474.17 - *
474.18 - * You should have received a copy of the GNU General Public License version
474.19 - * 2 along with this work; if not, write to the Free Software Foundation,
474.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
474.21 - *
474.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
474.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
474.24 - * have any questions.
474.25 - */
474.26 -
474.27 -/*
474.28 - * @test %M% %I%
474.29 - * @bug 6323980
474.30 - * @summary Test MBeans defined with @MBean
474.31 - * @author Eamonn McManus
474.32 - * @run main/othervm -ea AnnotatedMBeanTest
474.33 - */
474.34 -
474.35 -import java.io.File;
474.36 -import java.io.PrintWriter;
474.37 -import java.lang.annotation.Retention;
474.38 -import java.lang.annotation.RetentionPolicy;
474.39 -import java.lang.reflect.InvocationTargetException;
474.40 -import java.lang.reflect.Method;
474.41 -import java.lang.reflect.Modifier;
474.42 -import java.util.Arrays;
474.43 -import java.util.HashSet;
474.44 -import java.util.Set;
474.45 -import javax.management.Attribute;
474.46 -import javax.management.Descriptor;
474.47 -import javax.management.DescriptorKey;
474.48 -import javax.management.MBeanAttributeInfo;
474.49 -import javax.management.MBeanInfo;
474.50 -import javax.management.MBeanOperationInfo;
474.51 -import javax.management.MBeanParameterInfo;
474.52 -import javax.management.MBeanServer;
474.53 -import javax.management.MBeanServerFactory;
474.54 -import javax.management.MXBean;
474.55 -import javax.management.MalformedObjectNameException;
474.56 -import javax.management.ManagedAttribute;
474.57 -import javax.management.ManagedOperation;
474.58 -import javax.management.MBean;
474.59 -import javax.management.ObjectName;
474.60 -import javax.management.openmbean.CompositeData;
474.61 -import javax.management.openmbean.CompositeType;
474.62 -
474.63 -public class AnnotatedMBeanTest {
474.64 - private static MBeanServer mbs;
474.65 - private static final ObjectName objectName;
474.66 - static {
474.67 - try {
474.68 - objectName = new ObjectName("test:type=Test");
474.69 - } catch (MalformedObjectNameException e) {
474.70 - throw new RuntimeException(e);
474.71 - }
474.72 - }
474.73 -
474.74 - public static void main(String[] args) throws Exception {
474.75 - if (!AnnotatedMBeanTest.class.desiredAssertionStatus())
474.76 - throw new Exception("Test must be run with -ea");
474.77 -
474.78 - File policyFile = File.createTempFile("jmxperms", ".policy");
474.79 - policyFile.deleteOnExit();
474.80 - PrintWriter pw = new PrintWriter(policyFile);
474.81 - pw.println("grant {");
474.82 - pw.println(" permission javax.management.MBeanPermission \"*\", \"*\";");
474.83 - pw.println(" permission javax.management.MBeanServerPermission \"*\";");
474.84 - pw.println(" permission javax.management.MBeanTrustPermission \"*\";");
474.85 - pw.println("};");
474.86 - pw.close();
474.87 -
474.88 - System.setProperty("java.security.policy", policyFile.getAbsolutePath());
474.89 - System.setSecurityManager(new SecurityManager());
474.90 -
474.91 - String failure = null;
474.92 -
474.93 - for (Method m : AnnotatedMBeanTest.class.getDeclaredMethods()) {
474.94 - if (Modifier.isStatic(m.getModifiers()) &&
474.95 - m.getName().startsWith("test") &&
474.96 - m.getParameterTypes().length == 0) {
474.97 - mbs = MBeanServerFactory.newMBeanServer();
474.98 - try {
474.99 - m.invoke(null);
474.100 - System.out.println(m.getName() + " OK");
474.101 - } catch (InvocationTargetException ite) {
474.102 - System.out.println(m.getName() + " got exception:");
474.103 - Throwable t = ite.getCause();
474.104 - t.printStackTrace(System.out);
474.105 - failure = m.getName() + ": " + t.toString();
474.106 - }
474.107 - }
474.108 - }
474.109 - if (failure == null)
474.110 - System.out.println("TEST PASSED");
474.111 - else
474.112 - throw new Exception("TEST FAILED: " + failure);
474.113 - }
474.114 -
474.115 - public static class Stats {
474.116 - private final int used;
474.117 - private final int size;
474.118 - private final boolean interesting;
474.119 -
474.120 - public Stats(int used, int size, boolean interesting) {
474.121 - this.used = used;
474.122 - this.size = size;
474.123 - this.interesting = interesting;
474.124 - }
474.125 -
474.126 - public int getUsed() {
474.127 - return used;
474.128 - }
474.129 -
474.130 - public int getSize() {
474.131 - return size;
474.132 - }
474.133 -
474.134 - public boolean isInteresting() {
474.135 - return interesting;
474.136 - }
474.137 - }
474.138 -
474.139 - @Retention(RetentionPolicy.RUNTIME)
474.140 - public static @interface Units {
474.141 - @DescriptorKey("units")
474.142 - String value();
474.143 - }
474.144 -
474.145 - @MBean
474.146 - public static class Cache {
474.147 - private int used = 23;
474.148 - private int size = 99;
474.149 -
474.150 - @ManagedAttribute
474.151 - @Units("bytes")
474.152 - public int getUsed() {
474.153 - return used;
474.154 - }
474.155 -
474.156 - @ManagedAttribute
474.157 - public int getSize() {
474.158 - return size;
474.159 - }
474.160 -
474.161 - @ManagedAttribute
474.162 - public void setSize(int x) {
474.163 - this.size = x;
474.164 - }
474.165 -
474.166 - @ManagedAttribute
474.167 - public boolean isInteresting() {
474.168 - return false;
474.169 - }
474.170 -
474.171 - @ManagedAttribute
474.172 - public Stats getStats() {
474.173 - return new Stats(used, size, false);
474.174 - }
474.175 -
474.176 - @ManagedOperation
474.177 - public int dropOldest(int n) {
474.178 - return 55;
474.179 - }
474.180 -
474.181 - private void irrelevantMethod() {}
474.182 - private int getIrrelevant() {return 0;}
474.183 - public int getIrrelevant2() {return 0;}
474.184 -
474.185 - public int otherIrrelevantMethod() {return 5;}
474.186 - }
474.187 -
474.188 - public static class SubCache extends Cache {
474.189 - // SubCache does not have the @MBean annotation
474.190 - // but its parent does. It doesn't add any @ManagedAttribute or
474.191 - // @ManagedOperation methods, so its management interface
474.192 - // should be the same.
474.193 - private void irrelevantMethod2() {}
474.194 - public int otherIrrelevantMethod3() {return 0;}
474.195 -
474.196 - public int getX() {return 0;}
474.197 - public void setX(int x) {}
474.198 - }
474.199 -
474.200 - @MXBean
474.201 - public static class CacheMX {
474.202 - private int used = 23;
474.203 - private int size = 99;
474.204 -
474.205 - @ManagedAttribute
474.206 - @Units("bytes")
474.207 - public int getUsed() {
474.208 - return used;
474.209 - }
474.210 -
474.211 - @ManagedAttribute
474.212 - public int getSize() {
474.213 - return size;
474.214 - }
474.215 -
474.216 - @ManagedAttribute
474.217 - public void setSize(int x) {
474.218 - this.size = x;
474.219 - }
474.220 -
474.221 - @ManagedAttribute
474.222 - public boolean isInteresting() {
474.223 - return false;
474.224 - }
474.225 -
474.226 - @ManagedAttribute
474.227 - public Stats getStats() {
474.228 - return new Stats(used, size, false);
474.229 - }
474.230 -
474.231 - @ManagedOperation
474.232 - public int dropOldest(int n) {
474.233 - return 55;
474.234 - }
474.235 -
474.236 - private void irrelevantMethod() {}
474.237 - private int getIrrelevant() {return 0;}
474.238 - public int getIrrelevant2() {return 0;}
474.239 -
474.240 - public int otherIrrelevantMethod() {return 5;}
474.241 - }
474.242 -
474.243 - public static class SubCacheMX extends CacheMX {
474.244 - private void irrelevantMethod2() {}
474.245 - public int otherIrrelevantMethod3() {return 0;}
474.246 -
474.247 - public int getX() {return 0;}
474.248 - public void setX(int x) {}
474.249 - }
474.250 -
474.251 - private static void testSimpleManagedResource() throws Exception {
474.252 - testResource(new Cache(), false);
474.253 - }
474.254 -
474.255 - private static void testSubclassManagedResource() throws Exception {
474.256 - testResource(new SubCache(), false);
474.257 - }
474.258 -
474.259 - private static void testMXBeanResource() throws Exception {
474.260 - testResource(new CacheMX(), true);
474.261 - }
474.262 -
474.263 - private static void testSubclassMXBeanResource() throws Exception {
474.264 - testResource(new SubCacheMX(), true);
474.265 - }
474.266 -
474.267 - private static void testResource(Object resource, boolean mx) throws Exception {
474.268 - mbs.registerMBean(resource, objectName);
474.269 -
474.270 - MBeanInfo mbi = mbs.getMBeanInfo(objectName);
474.271 - assert mbi.getDescriptor().getFieldValue("mxbean").equals(Boolean.toString(mx));
474.272 -
474.273 - MBeanAttributeInfo[] mbais = mbi.getAttributes();
474.274 -
474.275 - assert mbais.length == 4: mbais.length;
474.276 -
474.277 - for (MBeanAttributeInfo mbai : mbais) {
474.278 - String name = mbai.getName();
474.279 - if (name.equals("Used")) {
474.280 - assert mbai.isReadable();
474.281 - assert !mbai.isWritable();
474.282 - assert !mbai.isIs();
474.283 - assert mbai.getType().equals("int");
474.284 - assert "bytes".equals(mbai.getDescriptor().getFieldValue("units"));
474.285 - } else if (name.equals("Size")) {
474.286 - assert mbai.isReadable();
474.287 - assert mbai.isWritable();
474.288 - assert !mbai.isIs();
474.289 - assert mbai.getType().equals("int");
474.290 - } else if (name.equals("Interesting")) {
474.291 - assert mbai.isReadable();
474.292 - assert !mbai.isWritable();
474.293 - assert mbai.isIs();
474.294 - assert mbai.getType().equals("boolean");
474.295 - } else if (name.equals("Stats")) {
474.296 - assert mbai.isReadable();
474.297 - assert !mbai.isWritable();
474.298 - assert !mbai.isIs();
474.299 - Descriptor d = mbai.getDescriptor();
474.300 - if (mx) {
474.301 - assert mbai.getType().equals(CompositeData.class.getName());
474.302 - assert d.getFieldValue("originalType").equals(Stats.class.getName());
474.303 - CompositeType ct = (CompositeType) d.getFieldValue("openType");
474.304 - Set<String> names = new HashSet<String>(
474.305 - Arrays.asList("used", "size", "interesting"));
474.306 - assert ct.keySet().equals(names) : ct.keySet();
474.307 - } else {
474.308 - assert mbai.getType().equals(Stats.class.getName());
474.309 - }
474.310 - } else
474.311 - assert false : name;
474.312 - }
474.313 -
474.314 - MBeanOperationInfo[] mbois = mbi.getOperations();
474.315 -
474.316 - assert mbois.length == 1: mbois.length;
474.317 -
474.318 - MBeanOperationInfo mboi = mbois[0];
474.319 - assert mboi.getName().equals("dropOldest");
474.320 - assert mboi.getReturnType().equals("int");
474.321 - MBeanParameterInfo[] mbpis = mboi.getSignature();
474.322 - assert mbpis.length == 1: mbpis.length;
474.323 - assert mbpis[0].getType().equals("int");
474.324 -
474.325 - assert mbs.getAttribute(objectName, "Used").equals(23);
474.326 -
474.327 - assert mbs.getAttribute(objectName, "Size").equals(99);
474.328 - mbs.setAttribute(objectName, new Attribute("Size", 55));
474.329 - assert mbs.getAttribute(objectName, "Size").equals(55);
474.330 -
474.331 - assert mbs.getAttribute(objectName, "Interesting").equals(false);
474.332 -
474.333 - Object stats = mbs.getAttribute(objectName, "Stats");
474.334 - assert (mx ? CompositeData.class : Stats.class).isInstance(stats) : stats.getClass();
474.335 -
474.336 - int ret = (Integer) mbs.invoke(
474.337 - objectName, "dropOldest", new Object[] {66}, new String[] {"int"});
474.338 - assert ret == 55;
474.339 - }
474.340 -}
475.1 --- a/test/javax/management/Introspector/AnnotatedNotificationInfoTest.java Mon Nov 23 10:04:47 2009 +0000
475.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
475.3 @@ -1,442 +0,0 @@
475.4 -/*
475.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
475.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
475.7 - *
475.8 - * This code is free software; you can redistribute it and/or modify it
475.9 - * under the terms of the GNU General Public License version 2 only, as
475.10 - * published by the Free Software Foundation.
475.11 - *
475.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
475.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
475.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
475.15 - * version 2 for more details (a copy is included in the LICENSE file that
475.16 - * accompanied this code).
475.17 - *
475.18 - * You should have received a copy of the GNU General Public License version
475.19 - * 2 along with this work; if not, write to the Free Software Foundation,
475.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
475.21 - *
475.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
475.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
475.24 - * have any questions.
475.25 - */
475.26 -
475.27 -/*
475.28 - * @test
475.29 - * @bug 6323980 6772779
475.30 - * @summary Test @NotificationInfo annotation
475.31 - * @author Eamonn McManus
475.32 - * @run main/othervm -ea AnnotatedNotificationInfoTest
475.33 - */
475.34 -
475.35 -import java.io.Serializable;
475.36 -import java.lang.management.ManagementFactory;
475.37 -import java.lang.reflect.Field;
475.38 -import java.util.Arrays;
475.39 -import javax.annotation.Resource;
475.40 -import javax.management.AttributeChangeNotification;
475.41 -import javax.management.Description;
475.42 -import javax.management.Descriptor;
475.43 -import javax.management.ImmutableDescriptor;
475.44 -import javax.management.ListenerNotFoundException;
475.45 -import javax.management.MBean;
475.46 -import javax.management.MBeanInfo;
475.47 -import javax.management.MBeanNotificationInfo;
475.48 -import javax.management.MBeanServer;
475.49 -import javax.management.MXBean;
475.50 -import javax.management.Notification;
475.51 -import javax.management.NotificationBroadcaster;
475.52 -import javax.management.NotificationBroadcasterSupport;
475.53 -import javax.management.NotificationFilter;
475.54 -import javax.management.NotificationInfo;
475.55 -import javax.management.NotificationInfos;
475.56 -import javax.management.NotificationListener;
475.57 -import javax.management.ObjectName;
475.58 -import javax.management.SendNotification;
475.59 -
475.60 -public class AnnotatedNotificationInfoTest {
475.61 -
475.62 - static final Descriptor expectedDescriptor = new ImmutableDescriptor(
475.63 - "foo=bar", "descriptionResourceBundleBaseName=bundle",
475.64 - "descriptionResourceKey=key");
475.65 - static final MBeanNotificationInfo expected = new MBeanNotificationInfo(
475.66 - new String[] {"foo", "bar"},
475.67 - AttributeChangeNotification.class.getName(),
475.68 - "description",
475.69 - expectedDescriptor);
475.70 -
475.71 - // Data for the first kind of test. This tests that MBeanNotificationInfo
475.72 - // is correctly derived from @NotificationInfo.
475.73 - // Every static field called mbean* is expected to be an MBean
475.74 - // with a single MBeanNotificationInfo that has the same value
475.75 - // in each case.
475.76 -
475.77 - @NotificationInfo(
475.78 - types = {"foo", "bar"},
475.79 - notificationClass = AttributeChangeNotification.class,
475.80 - description = @Description(
475.81 - value = "description",
475.82 - bundleBaseName = "bundle",
475.83 - key = "key"),
475.84 - descriptorFields = {"foo=bar"})
475.85 - public static interface Intf1MBean {}
475.86 -
475.87 - public static class Intf1
475.88 - extends NotificationBroadcasterSupport implements Intf1MBean {}
475.89 -
475.90 - private static Object mbeanIntf1 = new Intf1();
475.91 -
475.92 - @NotificationInfos(
475.93 - @NotificationInfo(
475.94 - types = {"foo", "bar"},
475.95 - notificationClass = AttributeChangeNotification.class,
475.96 - description = @Description(
475.97 - value = "description",
475.98 - bundleBaseName = "bundle",
475.99 - key = "key"),
475.100 - descriptorFields = {"foo=bar"}))
475.101 - public static interface Intf2MBean {}
475.102 -
475.103 - public static class Intf2
475.104 - extends NotificationBroadcasterSupport implements Intf2MBean {}
475.105 -
475.106 - private static Object mbeanIntf2 = new Intf2();
475.107 -
475.108 - @NotificationInfos({})
475.109 - @NotificationInfo(
475.110 - types = {"foo", "bar"},
475.111 - notificationClass = AttributeChangeNotification.class,
475.112 - description = @Description(
475.113 - value = "description",
475.114 - bundleBaseName = "bundle",
475.115 - key = "key"),
475.116 - descriptorFields = {"foo=bar"})
475.117 - public static interface Intf3MBean {}
475.118 -
475.119 - public static class Intf3
475.120 - extends NotificationBroadcasterSupport implements Intf3MBean {}
475.121 -
475.122 - private static Object mbeanIntf3 = new Intf3();
475.123 -
475.124 - @NotificationInfo(
475.125 - types = {"foo", "bar"},
475.126 - notificationClass = AttributeChangeNotification.class,
475.127 - description = @Description(
475.128 - value = "description",
475.129 - bundleBaseName = "bundle",
475.130 - key = "key"),
475.131 - descriptorFields = {"foo=bar"})
475.132 - public static interface ParentIntf {}
475.133 -
475.134 - public static interface Intf4MBean extends Serializable, ParentIntf, Cloneable {}
475.135 -
475.136 - public static class Intf4
475.137 - extends NotificationBroadcasterSupport implements Intf4MBean {}
475.138 -
475.139 - private static Object mbeanIntf4 = new Intf4();
475.140 -
475.141 - @NotificationInfo(
475.142 - types = {"foo", "bar"},
475.143 - notificationClass = AttributeChangeNotification.class,
475.144 - description = @Description(
475.145 - value = "description",
475.146 - bundleBaseName = "bundle",
475.147 - key = "key"),
475.148 - descriptorFields = {"foo=bar"})
475.149 - public static interface Intf5MXBean {}
475.150 -
475.151 - public static class Intf5Impl
475.152 - extends NotificationBroadcasterSupport implements Intf5MXBean {}
475.153 -
475.154 - private static Object mbeanIntf5 = new Intf5Impl();
475.155 -
475.156 - @NotificationInfo(
475.157 - types = {"foo", "bar"},
475.158 - notificationClass = AttributeChangeNotification.class,
475.159 - description = @Description(
475.160 - value = "description",
475.161 - bundleBaseName = "bundle",
475.162 - key = "key"),
475.163 - descriptorFields = {"foo=bar"})
475.164 - public static interface Intf6MBean {}
475.165 -
475.166 - public static class Intf6 implements Intf6MBean {
475.167 - @Resource
475.168 - private volatile SendNotification send;
475.169 - }
475.170 -
475.171 - private static Object mbeanIntf6 = new Intf6();
475.172 -
475.173 - public static interface Impl1MBean {}
475.174 -
475.175 - @NotificationInfo(
475.176 - types = {"foo", "bar"},
475.177 - notificationClass = AttributeChangeNotification.class,
475.178 - description = @Description(
475.179 - value = "description",
475.180 - bundleBaseName = "bundle",
475.181 - key = "key"),
475.182 - descriptorFields = {"foo=bar"})
475.183 - public static class Impl1
475.184 - extends NotificationBroadcasterSupport implements Impl1MBean {}
475.185 -
475.186 - private static Object mbeanImpl1 = new Impl1();
475.187 -
475.188 - @NotificationInfo(
475.189 - types = {"foo", "bar"},
475.190 - notificationClass = AttributeChangeNotification.class,
475.191 - description = @Description(
475.192 - value = "description",
475.193 - bundleBaseName = "bundle",
475.194 - key = "key"),
475.195 - descriptorFields = {"foo=bar"})
475.196 - public static class ParentImpl extends NotificationBroadcasterSupport {}
475.197 -
475.198 - public static interface Impl2MBean {}
475.199 -
475.200 - public static class Impl2 extends ParentImpl implements Impl2MBean {}
475.201 -
475.202 - private static Object mbeanImpl2 = new Impl2();
475.203 -
475.204 - public static interface Impl3MXBean {}
475.205 -
475.206 - @NotificationInfo(
475.207 - types = {"foo", "bar"},
475.208 - notificationClass = AttributeChangeNotification.class,
475.209 - description = @Description(
475.210 - value = "description",
475.211 - bundleBaseName = "bundle",
475.212 - key = "key"),
475.213 - descriptorFields = {"foo=bar"})
475.214 - public static class Impl3
475.215 - extends NotificationBroadcasterSupport implements Impl3MXBean {}
475.216 -
475.217 - private static Object mbeanImpl3 = new Impl3();
475.218 -
475.219 - public static class Impl4 extends ParentImpl implements Impl3MXBean {}
475.220 -
475.221 - private static Object mbeanImpl4 = new Impl4();
475.222 -
475.223 - @MBean
475.224 - @NotificationInfo(
475.225 - types = {"foo", "bar"},
475.226 - notificationClass = AttributeChangeNotification.class,
475.227 - description = @Description(
475.228 - value = "description",
475.229 - bundleBaseName = "bundle",
475.230 - key = "key"),
475.231 - descriptorFields = {"foo=bar"})
475.232 - public static class MBean1 extends NotificationBroadcasterSupport {}
475.233 -
475.234 - private static Object mbeanMBean1 = new MBean1();
475.235 -
475.236 - @MBean
475.237 - public static class MBean2 extends ParentImpl {}
475.238 -
475.239 - private static Object mbeanMBean2 = new MBean2();
475.240 -
475.241 - @MBean
475.242 - @NotificationInfo(
475.243 - types = {"foo", "bar"},
475.244 - notificationClass = AttributeChangeNotification.class,
475.245 - description = @Description(
475.246 - value = "description",
475.247 - bundleBaseName = "bundle",
475.248 - key = "key"),
475.249 - descriptorFields = {"foo=bar"})
475.250 - public static class MBean3 {
475.251 - @Resource
475.252 - private volatile SendNotification send;
475.253 - }
475.254 -
475.255 - private static Object mbeanMBean3 = new MBean3();
475.256 -
475.257 - @MXBean
475.258 - @NotificationInfo(
475.259 - types = {"foo", "bar"},
475.260 - notificationClass = AttributeChangeNotification.class,
475.261 - description = @Description(
475.262 - value = "description",
475.263 - bundleBaseName = "bundle",
475.264 - key = "key"),
475.265 - descriptorFields = {"foo=bar"})
475.266 - public static class MXBean1 extends NotificationBroadcasterSupport {}
475.267 -
475.268 - private static Object mbeanMXBean1 = new MXBean1();
475.269 -
475.270 - @MXBean
475.271 - public static class MXBean2 extends ParentImpl {}
475.272 -
475.273 - private static Object mbeanMXBean2 = new MXBean2();
475.274 -
475.275 - // Test that @NotificationInfo and @NotificationInfos are ignored if
475.276 - // the MBean returns a non-empty MBeanNotificationInfo[] from its
475.277 - // NotificationBroadcaster.getNotifications() implementation.
475.278 -
475.279 - @NotificationInfo(types={"blim", "blam"})
475.280 - public static interface Explicit1MBean {}
475.281 -
475.282 - public static class Explicit1
475.283 - extends NotificationBroadcasterSupport implements Explicit1MBean {
475.284 - public Explicit1() {
475.285 - super(expected);
475.286 - }
475.287 - }
475.288 -
475.289 - private static Object mbeanExplicit1 = new Explicit1();
475.290 -
475.291 - @NotificationInfos(
475.292 - {
475.293 - @NotificationInfo(types="blim"), @NotificationInfo(types="blam")
475.294 - }
475.295 - )
475.296 - public static interface Explicit2MXBean {}
475.297 -
475.298 - public static class Explicit2
475.299 - implements NotificationBroadcaster, Explicit2MXBean {
475.300 - public void addNotificationListener(NotificationListener listener,
475.301 - NotificationFilter filter, Object handback) {}
475.302 -
475.303 - public void removeNotificationListener(NotificationListener listener)
475.304 - throws ListenerNotFoundException {}
475.305 -
475.306 - public MBeanNotificationInfo[] getNotificationInfo() {
475.307 - return new MBeanNotificationInfo[] {expected};
475.308 - }
475.309 - }
475.310 -
475.311 - // Data for the second kind of test. This tests that @NotificationInfo is
475.312 - // ignored if the MBean is not a notification source. Every static
475.313 - // field called ignoredMBean* is expected to be an MBean on which
475.314 - // isInstanceOf(NotificationBroadcaster.class.getName() is false,
475.315 - // addNotificationListener produces an exception, and the
475.316 - // MBeanNotificationInfo array is empty.
475.317 - @NotificationInfo(types={"com.example.notifs.create",
475.318 - "com.example.notifs.destroy"})
475.319 - public static interface CacheMBean {
475.320 - public int getCachedNum();
475.321 - }
475.322 -
475.323 - public static class Cache implements CacheMBean {
475.324 - public int getCachedNum() {
475.325 - return 0;
475.326 - }
475.327 - }
475.328 -
475.329 - private static Object ignoredMBean1 = new Cache();
475.330 -
475.331 - @NotificationInfos(
475.332 - @NotificationInfo(types={"foo", "bar"})
475.333 - )
475.334 - public static interface Cache2MBean {
475.335 - public int getCachedNum();
475.336 - }
475.337 -
475.338 - public static class Cache2 implements Cache2MBean {
475.339 - public int getCachedNum() {
475.340 - return 0;
475.341 - }
475.342 - }
475.343 -
475.344 - private static Object ignoredMBean2 = new Cache2();
475.345 -
475.346 - private static final NotificationListener nullListener =
475.347 - new NotificationListener() {
475.348 - public void handleNotification(
475.349 - Notification notification, Object handback) {}
475.350 - };
475.351 -
475.352 - // Test that inheriting inconsistent @NotificationInfo annotations is
475.353 - // an error, but not if they are overridden by a non-empty getNotifications()
475.354 -
475.355 - @NotificationInfo(types={"blim"})
475.356 - public static interface Inconsistent1 {}
475.357 -
475.358 - @NotificationInfo(types={"blam"})
475.359 - public static interface Inconsistent2 {}
475.360 -
475.361 - public static interface InconsistentMBean extends Inconsistent1, Inconsistent2 {}
475.362 -
475.363 - public static class Inconsistent
475.364 - extends NotificationBroadcasterSupport implements InconsistentMBean {}
475.365 -
475.366 - public static class Consistent
475.367 - extends Inconsistent implements NotificationBroadcaster {
475.368 - public void addNotificationListener(NotificationListener listener,
475.369 - NotificationFilter filter, Object handback) {}
475.370 -
475.371 - public void removeNotificationListener(NotificationListener listener)
475.372 - throws ListenerNotFoundException {}
475.373 -
475.374 - public MBeanNotificationInfo[] getNotificationInfo() {
475.375 - return new MBeanNotificationInfo[] {expected};
475.376 - }
475.377 - }
475.378 -
475.379 - private static Object mbeanConsistent = new Consistent();
475.380 -
475.381 - @NotificationInfo(
475.382 - types = {"foo", "bar"},
475.383 - notificationClass = AttributeChangeNotification.class,
475.384 - description = @Description(
475.385 - value = "description",
475.386 - bundleBaseName = "bundle",
475.387 - key = "key"),
475.388 - descriptorFields = {"foo=bar"})
475.389 - public static interface Consistent2MBean extends Inconsistent1, Inconsistent2 {}
475.390 -
475.391 - public static class Consistent2
475.392 - extends NotificationBroadcasterSupport implements Consistent2MBean {}
475.393 -
475.394 - private static Object mbeanConsistent2 = new Consistent2();
475.395 -
475.396 - public static void main(String[] args) throws Exception {
475.397 - if (!AnnotatedNotificationInfoTest.class.desiredAssertionStatus())
475.398 - throw new Exception("Test must be run with -ea");
475.399 -
475.400 - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
475.401 - ObjectName on = new ObjectName("a:b=c");
475.402 -
475.403 - System.out.println("Testing MBeans...");
475.404 - for (Field mbeanField :
475.405 - AnnotatedNotificationInfoTest.class.getDeclaredFields()) {
475.406 - boolean notifier;
475.407 - if (mbeanField.getName().startsWith("mbean"))
475.408 - notifier = true;
475.409 - else if (mbeanField.getName().startsWith("ignoredMBean"))
475.410 - notifier = false;
475.411 - else
475.412 - continue;
475.413 - System.out.println("..." + mbeanField.getName());
475.414 - Object mbean = mbeanField.get(null);
475.415 - mbs.registerMBean(mbean, on);
475.416 - MBeanInfo mbi = mbs.getMBeanInfo(on);
475.417 - MBeanNotificationInfo[] mbnis = mbi.getNotifications();
475.418 - if (notifier) {
475.419 - assert mbnis.length == 1 : mbnis.length;
475.420 - assert mbnis[0].equals(expected) : mbnis[0];
475.421 - } else {
475.422 - assert mbnis.length == 0 : mbnis.length;
475.423 - assert !mbs.isInstanceOf(on, NotificationBroadcaster.class.getName());
475.424 - try {
475.425 - mbs.addNotificationListener(on, nullListener, null, null);
475.426 - assert false : "addNotificationListener works";
475.427 - } catch (Exception e) {
475.428 - // OK: addNL correctly refused
475.429 - }
475.430 - }
475.431 - mbs.unregisterMBean(on);
475.432 - }
475.433 -
475.434 - // Test that inconsistent @NotificationInfo annotations produce an
475.435 - // error.
475.436 - try {
475.437 - mbs.registerMBean(new Inconsistent(), on);
475.438 - System.out.println(mbs.getMBeanInfo(on));
475.439 - assert false : "Inconsistent @NotificationInfo not detected";
475.440 - } catch (Exception e) {
475.441 - System.out.println(
475.442 - "Inconsistent @NotificationInfo correctly produced " + e);
475.443 - }
475.444 - }
475.445 -}
476.1 --- a/test/javax/management/Introspector/AnnotationTest.java Mon Nov 23 10:04:47 2009 +0000
476.2 +++ b/test/javax/management/Introspector/AnnotationTest.java Wed Nov 25 11:08:25 2009 -0800
476.3 @@ -32,15 +32,22 @@
476.4 * @run main AnnotationTest
476.5 */
476.6
476.7 -import java.lang.annotation.*;
476.8 -import java.lang.reflect.*;
476.9 -import java.util.*;
476.10 -import javax.management.*;
476.11 +import java.lang.annotation.Retention;
476.12 +import java.lang.annotation.RetentionPolicy;
476.13 +import javax.management.Descriptor;
476.14 +import javax.management.DescriptorRead;
476.15 +import javax.management.DescriptorKey;
476.16 +import javax.management.ImmutableDescriptor;
476.17 +import javax.management.MBeanAttributeInfo;
476.18 +import javax.management.MBeanConstructorInfo;
476.19 +import javax.management.MBeanInfo;
476.20 +import javax.management.MBeanOperationInfo;
476.21 +import javax.management.MBeanServer;
476.22 +import javax.management.ObjectName;
476.23
476.24 /*
476.25 This test checks that annotations produce Descriptor entries as
476.26 - specified in javax.management.DescriptorKey and javax.management.DescriptorField.
476.27 - It does the following:
476.28 + specified in javax.management.DescriptorKey. It does two things:
476.29
476.30 - An annotation consisting of an int and a String, each with an
476.31 appropriate @DescriptorKey annotation, is placed on every program
476.32 @@ -62,10 +69,6 @@
476.33 The test checks that in each case the corresponding Descriptor
476.34 appears in the appropriate place inside the MBean's MBeanInfo.
476.35
476.36 - - A @DescriptorFields annotation defining two fields is placed in the
476.37 - same places and again the test checks that the two fields appear
476.38 - in the corresponding MBean*Info objects.
476.39 -
476.40 - An annotation consisting of enough other types to ensure coverage
476.41 is placed on a getter. The test checks that the generated
476.42 MBeanAttributeInfo contains the corresponding Descriptor. The tested
476.43 @@ -111,12 +114,11 @@
476.44 boolean[] booleanArrayValue();
476.45 }
476.46
476.47 - /* We use the annotations @Pair(x = 3, y = "foo")
476.48 - and @DescriptorFields({"foo=bar", "baz="}) everywhere, and this is
476.49 - the Descriptor that they should produce: */
476.50 + /* We use the annotation @Pair(x = 3, y = "foo") everywhere, and this is
476.51 + the Descriptor that it should produce: */
476.52 private static Descriptor expectedDescriptor =
476.53 - new ImmutableDescriptor(new String[] {"x", "y", "foo", "baz"},
476.54 - new Object[] {3, "foo", "bar", ""});
476.55 + new ImmutableDescriptor(new String[] {"x", "y"},
476.56 + new Object[] {3, "foo"});
476.57
476.58 private static Descriptor expectedFullDescriptor =
476.59 new ImmutableDescriptor(new String[] {
476.60 @@ -136,10 +138,8 @@
476.61 });
476.62
476.63 @Pair(x = 3, y = "foo")
476.64 - @DescriptorFields({"foo=bar", "baz="})
476.65 public static interface ThingMBean {
476.66 @Pair(x = 3, y = "foo")
476.67 - @DescriptorFields({"foo=bar", "baz="})
476.68 @Full(classValue=Full.class,
476.69 enumValue=RetentionPolicy.RUNTIME,
476.70 booleanValue=false,
476.71 @@ -151,47 +151,32 @@
476.72 int getReadOnly();
476.73
476.74 @Pair(x = 3, y = "foo")
476.75 - @DescriptorFields({"foo=bar", "baz="})
476.76 void setWriteOnly(int x);
476.77
476.78 @Pair(x = 3, y = "foo")
476.79 - @DescriptorFields({"foo=bar", "baz="})
476.80 int getReadWrite1();
476.81 void setReadWrite1(int x);
476.82
476.83 @Pair(x = 3, y = "foo")
476.84 - @DescriptorFields({"foo=bar", "baz="})
476.85 int getReadWrite2();
476.86 @Pair(x = 3, y = "foo")
476.87 - @DescriptorFields({"foo=bar", "baz="})
476.88 void setReadWrite2(int x);
476.89
476.90 int getReadWrite3();
476.91 @Pair(x = 3, y = "foo")
476.92 - @DescriptorFields({"foo=bar", "baz="})
476.93 void setReadWrite3(int x);
476.94
476.95 @Pair(x = 3, y = "foo")
476.96 - @DescriptorFields({"foo=bar", "baz="})
476.97 - int operation(@Pair(x = 3, y = "foo")
476.98 - @DescriptorFields({"foo=bar", "baz="})
476.99 - int p1,
476.100 - @Pair(x = 3, y = "foo")
476.101 - @DescriptorFields({"foo=bar", "baz="})
476.102 - int p2);
476.103 + int operation(@Pair(x = 3, y = "foo") int p1,
476.104 + @Pair(x = 3, y = "foo") int p2);
476.105 }
476.106
476.107 public static class Thing implements ThingMBean {
476.108 @Pair(x = 3, y = "foo")
476.109 - @DescriptorFields({"foo=bar", "baz="})
476.110 public Thing() {}
476.111
476.112 @Pair(x = 3, y = "foo")
476.113 - @DescriptorFields({"foo=bar", "baz="})
476.114 - public Thing(
476.115 - @Pair(x = 3, y = "foo")
476.116 - @DescriptorFields({"foo=bar", "baz="})
476.117 - int p1) {}
476.118 + public Thing(@Pair(x = 3, y = "foo") int p1) {}
476.119
476.120 public int getReadOnly() {return 0;}
476.121
476.122 @@ -210,20 +195,14 @@
476.123 }
476.124
476.125 @Pair(x = 3, y = "foo")
476.126 - @DescriptorFields({"foo=bar", "baz="})
476.127 public static interface ThingMXBean extends ThingMBean {}
476.128
476.129 public static class ThingImpl implements ThingMXBean {
476.130 @Pair(x = 3, y = "foo")
476.131 - @DescriptorFields({"foo=bar", "baz="})
476.132 public ThingImpl() {}
476.133
476.134 @Pair(x = 3, y = "foo")
476.135 - @DescriptorFields({"foo=bar", "baz="})
476.136 - public ThingImpl(
476.137 - @Pair(x = 3, y = "foo")
476.138 - @DescriptorFields({"foo=bar", "baz="})
476.139 - int p1) {}
476.140 + public ThingImpl(@Pair(x = 3, y = "foo") int p1) {}
476.141
476.142 public int getReadOnly() {return 0;}
476.143
476.144 @@ -241,79 +220,6 @@
476.145 public int operation(int p1, int p2) {return 0;}
476.146 }
476.147
476.148 - @Retention(RetentionPolicy.RUNTIME)
476.149 - public static @interface DefaultTest {
476.150 - @DescriptorKey(value = "string1", omitIfDefault = true)
476.151 - String string1() default "";
476.152 - @DescriptorKey(value = "string2", omitIfDefault = true)
476.153 - String string2() default "tiddly pom";
476.154 - @DescriptorKey(value = "int", omitIfDefault = true)
476.155 - int intx() default 23;
476.156 - @DescriptorKey(value = "intarray1", omitIfDefault = true)
476.157 - int[] intArray1() default {};
476.158 - @DescriptorKey(value = "intarray2", omitIfDefault = true)
476.159 - int[] intArray2() default {1, 2};
476.160 - @DescriptorKey(value = "stringarray1", omitIfDefault = true)
476.161 - String[] stringArray1() default {};
476.162 - @DescriptorKey(value = "stringarray2", omitIfDefault = true)
476.163 - String[] stringArray2() default {"foo", "bar"};
476.164 - }
476.165 -
476.166 - @Retention(RetentionPolicy.RUNTIME)
476.167 - public static @interface Expect {
476.168 - String[] value() default {};
476.169 - }
476.170 -
476.171 - public static interface DefaultMBean {
476.172 - @DefaultTest
476.173 - @Expect()
476.174 - public void a();
476.175 -
476.176 - @DefaultTest(string1="")
476.177 - @Expect()
476.178 - public void b();
476.179 -
476.180 - @DefaultTest(string1="nondefault")
476.181 - @Expect("string1=nondefault")
476.182 - public void c();
476.183 -
476.184 - @DefaultTest(string2="tiddly pom")
476.185 - @Expect()
476.186 - public void d();
476.187 -
476.188 - @DefaultTest(intx=23)
476.189 - @Expect()
476.190 - public void e();
476.191 -
476.192 - @DefaultTest(intx=34)
476.193 - @Expect("int=34")
476.194 - public void f();
476.195 -
476.196 - @DefaultTest(intArray1={})
476.197 - @Expect()
476.198 - public void g();
476.199 -
476.200 - @DefaultTest(intArray1={2,3})
476.201 - @Expect("intarray1=[2, 3]")
476.202 - public void h();
476.203 -
476.204 - @DefaultTest(intArray2={})
476.205 - @Expect("intarray2=[]")
476.206 - public void i();
476.207 -
476.208 - @DefaultTest(stringArray1={})
476.209 - @Expect()
476.210 - public void j();
476.211 -
476.212 - @DefaultTest(stringArray1={"foo"})
476.213 - @Expect("stringarray1=[foo]")
476.214 - public void k();
476.215 -
476.216 - @DefaultTest(stringArray2={})
476.217 - @Expect("stringarray2=[]")
476.218 - public void l();
476.219 - }
476.220 -
476.221 public static void main(String[] args) throws Exception {
476.222 System.out.println("Testing that annotations are correctly " +
476.223 "reflected in Descriptor entries");
476.224 @@ -336,43 +242,6 @@
476.225 }
476.226 check(mbs, on);
476.227
476.228 - System.out.println();
476.229 - System.out.println("Testing that omitIfDefault works");
476.230 - DefaultMBean defaultImpl = (DefaultMBean) Proxy.newProxyInstance(
476.231 - DefaultMBean.class.getClassLoader(),
476.232 - new Class<?>[] {DefaultMBean.class},
476.233 - new InvocationHandler(){
476.234 - public Object invoke(Object proxy, Method method, Object[] args) {
476.235 - return null;
476.236 - }
476.237 - });
476.238 - DynamicMBean mbean = new StandardMBean(defaultImpl, DefaultMBean.class);
476.239 - MBeanOperationInfo[] ops = mbean.getMBeanInfo().getOperations();
476.240 - for (MBeanOperationInfo op : ops) {
476.241 - String name = op.getName();
476.242 - Expect expect =
476.243 - DefaultMBean.class.getMethod(name).getAnnotation(Expect.class);
476.244 - Descriptor opd = op.getDescriptor();
476.245 - List<String> fields = new ArrayList<String>();
476.246 - for (String fieldName : opd.getFieldNames()) {
476.247 - Object value = opd.getFieldValue(fieldName);
476.248 - String s = Arrays.deepToString(new Object[] {value});
476.249 - s = s.substring(1, s.length() - 1);
476.250 - fields.add(fieldName + "=" + s);
476.251 - }
476.252 - Descriptor opds = new ImmutableDescriptor(fields.toArray(new String[0]));
476.253 - Descriptor expd = new ImmutableDescriptor(expect.value());
476.254 - if (opds.equals(expd))
476.255 - System.out.println("OK: op " + name + ": " + opds);
476.256 - else {
476.257 - String failure = "Bad descriptor for op " + name + ": " +
476.258 - "expected " + expd + ", got " + opds;
476.259 - System.out.println("NOT OK: " + failure);
476.260 - failed = failure;
476.261 - }
476.262 - }
476.263 - System.out.println();
476.264 -
476.265 if (failed == null)
476.266 System.out.println("Test passed");
476.267 else
477.1 --- a/test/javax/management/Introspector/ExceptionsDescriptorTest.java Mon Nov 23 10:04:47 2009 +0000
477.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
477.3 @@ -1,245 +0,0 @@
477.4 -/*
477.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
477.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
477.7 - *
477.8 - * This code is free software; you can redistribute it and/or modify it
477.9 - * under the terms of the GNU General Public License version 2 only, as
477.10 - * published by the Free Software Foundation.
477.11 - *
477.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
477.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
477.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
477.15 - * version 2 for more details (a copy is included in the LICENSE file that
477.16 - * accompanied this code).
477.17 - *
477.18 - * You should have received a copy of the GNU General Public License version
477.19 - * 2 along with this work; if not, write to the Free Software Foundation,
477.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
477.21 - *
477.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
477.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
477.24 - * have any questions.
477.25 - */
477.26 -
477.27 -/*
477.28 - * @test %M% %I%
477.29 - * @bug 6250014
477.30 - * @summary Test that Exceptions are added to the MbeanInfo
477.31 - * @author Jean-Francois Denise
477.32 - * @run main/othervm ExceptionsDescriptorTest
477.33 - */
477.34 -import java.lang.management.ManagementFactory;
477.35 -import java.util.HashSet;
477.36 -import java.util.Set;
477.37 -import javax.management.Descriptor;
477.38 -import javax.management.JMX;
477.39 -import javax.management.MBeanAttributeInfo;
477.40 -import javax.management.MBeanConstructorInfo;
477.41 -import javax.management.MBeanInfo;
477.42 -import javax.management.MBeanOperationInfo;
477.43 -import javax.management.ObjectName;
477.44 -
477.45 -public class ExceptionsDescriptorTest {
477.46 -
477.47 - private static final ObjectName OBJECT_NAME = ObjectName.valueOf(":type=Foo");
477.48 - final static String EXCEPTION_NAME = Exception.class.getName();
477.49 - final static String ILLEGAL_ARGUMENT_EXCEPTION_NAME =
477.50 - IllegalArgumentException.class.getName();
477.51 - final static Set<String> ONE_EXCEPTION = new HashSet<String>();
477.52 - final static Set<String> TWO_EXCEPTION = new HashSet<String>();
477.53 - static {
477.54 - ONE_EXCEPTION.add(EXCEPTION_NAME);
477.55 - TWO_EXCEPTION.add(EXCEPTION_NAME);
477.56 - TWO_EXCEPTION.add(ILLEGAL_ARGUMENT_EXCEPTION_NAME);
477.57 - }
477.58 - public interface TestMBean {
477.59 -
477.60 - public void doIt();
477.61 -
477.62 - public void doIt(String str) throws Exception;
477.63 -
477.64 - public void doIt(String str, boolean b) throws Exception,
477.65 - IllegalArgumentException;
477.66 -
477.67 - public String getThat();
477.68 -
477.69 - public void setThat(String that);
477.70 -
477.71 - public String getThe() throws Exception;
477.72 -
477.73 - public void setThe(String the);
477.74 -
477.75 - public String getThese();
477.76 -
477.77 - public void setThese(String the) throws Exception;
477.78 -
477.79 - public String getIt() throws Exception;
477.80 -
477.81 - public void setIt(String str) throws Exception;
477.82 -
477.83 - public String getThis() throws Exception, IllegalArgumentException;
477.84 -
477.85 - public void setThose(String str) throws Exception,
477.86 - IllegalArgumentException;
477.87 - }
477.88 -
477.89 - public static class Test implements TestMBean {
477.90 -
477.91 - public Test() {
477.92 - }
477.93 -
477.94 - public Test(int i) throws Exception {
477.95 - }
477.96 -
477.97 - public Test(int i, int j) throws Exception, IllegalArgumentException {
477.98 - }
477.99 -
477.100 - public void doIt() {
477.101 - throw new UnsupportedOperationException("Not supported yet.");
477.102 - }
477.103 -
477.104 - public void doIt(String str) throws Exception {
477.105 - throw new UnsupportedOperationException("Not supported yet.");
477.106 - }
477.107 -
477.108 - public void doIt(String str, boolean b) throws Exception, IllegalArgumentException {
477.109 - throw new UnsupportedOperationException("Not supported yet.");
477.110 - }
477.111 -
477.112 - public String getThat() {
477.113 - throw new UnsupportedOperationException("Not supported yet.");
477.114 - }
477.115 -
477.116 - public void setThat(String that) {
477.117 - throw new UnsupportedOperationException("Not supported yet.");
477.118 - }
477.119 -
477.120 - public String getThe() throws Exception {
477.121 - throw new UnsupportedOperationException("Not supported yet.");
477.122 - }
477.123 -
477.124 - public void setThe(String the) {
477.125 - throw new UnsupportedOperationException("Not supported yet.");
477.126 - }
477.127 -
477.128 - public String getThese() {
477.129 - throw new UnsupportedOperationException("Not supported yet.");
477.130 - }
477.131 -
477.132 - public void setThese(String the) throws Exception {
477.133 - throw new UnsupportedOperationException("Not supported yet.");
477.134 - }
477.135 -
477.136 - public String getIt() throws Exception {
477.137 - throw new UnsupportedOperationException("Not supported yet.");
477.138 - }
477.139 -
477.140 - public void setIt(String str) throws Exception {
477.141 - throw new UnsupportedOperationException("Not supported yet.");
477.142 - }
477.143 -
477.144 - public String getThis() throws Exception, IllegalArgumentException {
477.145 - throw new UnsupportedOperationException("Not supported yet.");
477.146 - }
477.147 -
477.148 - public void setThose(String str) throws Exception, IllegalArgumentException {
477.149 - throw new UnsupportedOperationException("Not supported yet.");
477.150 - }
477.151 - }
477.152 -
477.153 - private static void check(Descriptor d,
477.154 - Set<String> exceptionsExpectedValue,
477.155 - boolean exceptionsExpected,
477.156 - Set<String> setExceptionsExpectedValue,
477.157 - boolean setExceptionsExpected) throws Exception {
477.158 - String[] exceptionsValues = (String[]) d.getFieldValue(JMX.EXCEPTIONS_FIELD);
477.159 - String[] setExceptionsValues = (String[]) d.getFieldValue(JMX.SET_EXCEPTIONS_FIELD);
477.160 -
477.161 - if (exceptionsExpected && exceptionsValues == null) {
477.162 - throw new Exception("exceptions is expected but null value");
477.163 - }
477.164 - if (!exceptionsExpected && exceptionsValues != null) {
477.165 - throw new Exception("exceptions is not expected but non null value");
477.166 - }
477.167 - if (setExceptionsExpected && setExceptionsValues == null) {
477.168 - throw new Exception("setExceptions is expected but null value");
477.169 - }
477.170 - if (!setExceptionsExpected && setExceptionsValues != null) {
477.171 - throw new Exception("setExceptions is not expected but non null value");
477.172 - }
477.173 -
477.174 - if (exceptionsExpected) {
477.175 - checkValues(exceptionsExpectedValue, exceptionsValues);
477.176 - }
477.177 - if (setExceptionsExpected) {
477.178 - checkValues(setExceptionsExpectedValue, setExceptionsValues);
477.179 - }
477.180 - }
477.181 -
477.182 - private static void checkValues(Set<String> expectedValuesSet,
477.183 - String[] realValues) throws Exception {
477.184 -
477.185 - Set<String> realValuesSet = new HashSet<String>();
477.186 - for (String ex : realValues) {
477.187 - realValuesSet.add(ex);
477.188 - }
477.189 - if (!realValuesSet.equals(expectedValuesSet)) {
477.190 - throw new Exception("Invalid content for exceptions. Was expecting " +
477.191 - expectedValuesSet + ". Found " + realValuesSet);
477.192 - }
477.193 - }
477.194 -
477.195 - public static void main(String[] args) throws Exception {
477.196 - Test t = new Test();
477.197 - ManagementFactory.getPlatformMBeanServer().registerMBean(t, OBJECT_NAME);
477.198 - MBeanInfo info = ManagementFactory.getPlatformMBeanServer().
477.199 - getMBeanInfo(OBJECT_NAME);
477.200 - //Constructors
477.201 - for (MBeanConstructorInfo ctr : info.getConstructors()) {
477.202 - if (ctr.getSignature().length == 0) {
477.203 - check(ctr.getDescriptor(), null, false, null, false);
477.204 - }
477.205 - if (ctr.getSignature().length == 1) {
477.206 - check(ctr.getDescriptor(), ONE_EXCEPTION, true, null, false);
477.207 - }
477.208 - if (ctr.getSignature().length == 2) {
477.209 - check(ctr.getDescriptor(),TWO_EXCEPTION,true, null, false);
477.210 - }
477.211 - }
477.212 - //Attributes
477.213 - for (MBeanAttributeInfo attr : info.getAttributes()) {
477.214 - if (attr.getName().equals("That")) {
477.215 - check(attr.getDescriptor(), null, false, null, false);
477.216 - }
477.217 - if (attr.getName().equals("The")) {
477.218 - check(attr.getDescriptor(), ONE_EXCEPTION,true,null, false);
477.219 - }
477.220 - if (attr.getName().equals("These")) {
477.221 - check(attr.getDescriptor(), null, false, ONE_EXCEPTION,true);
477.222 - }
477.223 - if (attr.getName().equals("It")) {
477.224 - check(attr.getDescriptor(), ONE_EXCEPTION,true,ONE_EXCEPTION,
477.225 - true);
477.226 - }
477.227 - if (attr.getName().equals("This")) {
477.228 - check(attr.getDescriptor(), TWO_EXCEPTION,true,null,false);
477.229 - }
477.230 - if (attr.getName().equals("Those")) {
477.231 - check(attr.getDescriptor(), null,false,TWO_EXCEPTION,true);
477.232 - }
477.233 - }
477.234 - //Operations
477.235 - for (MBeanOperationInfo oper : info.getOperations()) {
477.236 - if (oper.getSignature().length == 0) {
477.237 - check(oper.getDescriptor(), null, false, null, false);
477.238 - }
477.239 - if (oper.getSignature().length == 1) {
477.240 - check(oper.getDescriptor(), ONE_EXCEPTION, true, null, false);
477.241 - }
477.242 - if (oper.getSignature().length == 2) {
477.243 - check(oper.getDescriptor(), TWO_EXCEPTION,true, null, false);
477.244 - }
477.245 - }
477.246 - System.out.println("Test passed");
477.247 - }
477.248 -}
478.1 --- a/test/javax/management/Introspector/MBeanDescriptionTest.java Mon Nov 23 10:04:47 2009 +0000
478.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
478.3 @@ -1,830 +0,0 @@
478.4 -/*
478.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
478.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
478.7 - *
478.8 - * This code is free software; you can redistribute it and/or modify it
478.9 - * under the terms of the GNU General Public License version 2 only, as
478.10 - * published by the Free Software Foundation.
478.11 - *
478.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
478.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
478.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
478.15 - * version 2 for more details (a copy is included in the LICENSE file that
478.16 - * accompanied this code).
478.17 - *
478.18 - * You should have received a copy of the GNU General Public License version
478.19 - * 2 along with this work; if not, write to the Free Software Foundation,
478.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
478.21 - *
478.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
478.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
478.24 - * have any questions.
478.25 - */
478.26 -
478.27 -/*
478.28 - * @test %M% %I%
478.29 - * @bug 6323980
478.30 - * @summary Test @Description
478.31 - * @author Eamonn McManus
478.32 - */
478.33 -
478.34 -import java.lang.management.ManagementFactory;
478.35 -import javax.management.Description;
478.36 -import javax.management.IntrospectionException;
478.37 -import javax.management.MBean;
478.38 -import javax.management.MBeanAttributeInfo;
478.39 -import javax.management.MBeanConstructorInfo;
478.40 -import javax.management.MBeanFeatureInfo;
478.41 -import javax.management.MBeanInfo;
478.42 -import javax.management.MBeanOperationInfo;
478.43 -import javax.management.MBeanParameterInfo;
478.44 -import javax.management.MBeanServer;
478.45 -import javax.management.MXBean;
478.46 -import javax.management.ManagedAttribute;
478.47 -import javax.management.ManagedOperation;
478.48 -import javax.management.NotCompliantMBeanException;
478.49 -import javax.management.ObjectName;
478.50 -import javax.management.StandardMBean;
478.51 -
478.52 -public class MBeanDescriptionTest {
478.53 - private static String failure;
478.54 - private static final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
478.55 - private static final ObjectName name;
478.56 - static {
478.57 - try {
478.58 - name = new ObjectName("a:b=c");
478.59 - } catch (Exception e) {
478.60 - throw new RuntimeException(e);
478.61 - }
478.62 - }
478.63 -
478.64 - public static interface Interface {
478.65 - @Description("A description")
478.66 - public String getA();
478.67 -
478.68 - @Description("B description")
478.69 - public int getB();
478.70 - public void setB(int x);
478.71 -
478.72 - public boolean isC();
478.73 - @Description("C description")
478.74 - public void setC(boolean x);
478.75 -
478.76 - @Description("D description")
478.77 - public void setD(float x);
478.78 -
478.79 - @Description("H description")
478.80 - public int getH();
478.81 - @Description("H description")
478.82 - public void setH(int x);
478.83 -
478.84 - public String getE();
478.85 -
478.86 - public int getF();
478.87 - public void setF(int x);
478.88 -
478.89 - public void setG(boolean x);
478.90 -
478.91 - @Description("opA description")
478.92 - public int opA(
478.93 - @Description("p1 description")
478.94 - int p1,
478.95 - @Description("p2 description")
478.96 - int p2);
478.97 -
478.98 - public void opB(float x);
478.99 - }
478.100 -
478.101 - @Description("MBean description")
478.102 - public static interface TestMBean extends Interface {}
478.103 -
478.104 - public static class Test implements TestMBean {
478.105 - @Description("0-arg constructor description")
478.106 - public Test() {}
478.107 -
478.108 - public Test(String why) {}
478.109 -
478.110 - @Description("2-arg constructor description")
478.111 - public Test(
478.112 - @Description("p1 description")
478.113 - int x,
478.114 - @Description("p2 description")
478.115 - String y) {
478.116 - }
478.117 -
478.118 - public String getA() {
478.119 - return null;
478.120 - }
478.121 -
478.122 - public int getB() {
478.123 - return 0;
478.124 - }
478.125 -
478.126 - public void setB(int x) {
478.127 - }
478.128 -
478.129 - public boolean isC() {
478.130 - return false;
478.131 - }
478.132 -
478.133 - public void setC(boolean x) {
478.134 - }
478.135 -
478.136 - public void setD(float x) {
478.137 - }
478.138 -
478.139 - public String getE() {
478.140 - return null;
478.141 - }
478.142 -
478.143 - public int getF() {
478.144 - return 0;
478.145 - }
478.146 -
478.147 - public void setF(int x) {
478.148 - }
478.149 -
478.150 - public void setG(boolean x) {
478.151 - }
478.152 -
478.153 - public int getH() {
478.154 - return 0;
478.155 - }
478.156 -
478.157 - public void setH(int x) {
478.158 - }
478.159 -
478.160 - public int opA(int p1, int p2) {
478.161 - return 0;
478.162 - }
478.163 -
478.164 - public void opB(float x) {
478.165 - }
478.166 - }
478.167 -
478.168 - public static class TestSub extends Test {
478.169 - @Description("0-arg constructor description")
478.170 - public TestSub() {}
478.171 -
478.172 - public TestSub(String why) {}
478.173 -
478.174 - @Description("2-arg constructor description")
478.175 - public TestSub(
478.176 - @Description("p1 description")
478.177 - int x,
478.178 - @Description("p2 description")
478.179 - String y) {
478.180 - }
478.181 - }
478.182 -
478.183 - public static class StandardSub extends StandardMBean implements TestMBean {
478.184 - @Description("0-arg constructor description")
478.185 - public StandardSub() {
478.186 - super(TestMBean.class, false);
478.187 - }
478.188 -
478.189 - public StandardSub(String why) {
478.190 - super(TestMBean.class, false);
478.191 - }
478.192 -
478.193 - @Description("2-arg constructor description")
478.194 - public StandardSub(
478.195 - @Description("p1 description")
478.196 - int x,
478.197 - @Description("p2 description")
478.198 - String y) {
478.199 - super(TestMBean.class, false);
478.200 - }
478.201 -
478.202 - public String getA() {
478.203 - return null;
478.204 - }
478.205 -
478.206 - public int getB() {
478.207 - return 0;
478.208 - }
478.209 -
478.210 - public void setB(int x) {
478.211 - }
478.212 -
478.213 - public boolean isC() {
478.214 - return false;
478.215 - }
478.216 -
478.217 - public void setC(boolean x) {
478.218 - }
478.219 -
478.220 - public void setD(float x) {
478.221 - }
478.222 -
478.223 - public String getE() {
478.224 - return null;
478.225 - }
478.226 -
478.227 - public int getF() {
478.228 - return 0;
478.229 - }
478.230 -
478.231 - public void setF(int x) {
478.232 - }
478.233 -
478.234 - public void setG(boolean x) {
478.235 - }
478.236 -
478.237 - public int opA(int p1, int p2) {
478.238 - return 0;
478.239 - }
478.240 -
478.241 - public void opB(float x) {
478.242 - }
478.243 -
478.244 - public int getH() {
478.245 - return 0;
478.246 - }
478.247 -
478.248 - public void setH(int x) {
478.249 - }
478.250 - }
478.251 -
478.252 - @Description("MBean description")
478.253 - public static interface TestMXBean extends Interface {}
478.254 -
478.255 - public static class TestMXBeanImpl implements TestMXBean {
478.256 - @Description("0-arg constructor description")
478.257 - public TestMXBeanImpl() {}
478.258 -
478.259 - public TestMXBeanImpl(String why) {}
478.260 -
478.261 - @Description("2-arg constructor description")
478.262 - public TestMXBeanImpl(
478.263 - @Description("p1 description")
478.264 - int x,
478.265 - @Description("p2 description")
478.266 - String y) {
478.267 - }
478.268 -
478.269 - public String getA() {
478.270 - return null;
478.271 - }
478.272 -
478.273 - public int getB() {
478.274 - return 0;
478.275 - }
478.276 -
478.277 - public void setB(int x) {
478.278 - }
478.279 -
478.280 - public boolean isC() {
478.281 - return false;
478.282 - }
478.283 -
478.284 - public void setC(boolean x) {
478.285 - }
478.286 -
478.287 - public void setD(float x) {
478.288 - }
478.289 -
478.290 - public String getE() {
478.291 - return null;
478.292 - }
478.293 -
478.294 - public int getF() {
478.295 - return 0;
478.296 - }
478.297 -
478.298 - public void setF(int x) {
478.299 - }
478.300 -
478.301 - public void setG(boolean x) {
478.302 - }
478.303 -
478.304 - public int opA(int p1, int p2) {
478.305 - return 0;
478.306 - }
478.307 -
478.308 - public void opB(float x) {
478.309 - }
478.310 -
478.311 - public int getH() {
478.312 - return 0;
478.313 - }
478.314 -
478.315 - public void setH(int x) {
478.316 - }
478.317 - }
478.318 -
478.319 - public static class StandardMXSub extends StandardMBean implements TestMXBean {
478.320 - @Description("0-arg constructor description")
478.321 - public StandardMXSub() {
478.322 - super(TestMXBean.class, true);
478.323 - }
478.324 -
478.325 - public StandardMXSub(String why) {
478.326 - super(TestMXBean.class, true);
478.327 - }
478.328 -
478.329 - @Description("2-arg constructor description")
478.330 - public StandardMXSub(
478.331 - @Description("p1 description")
478.332 - int x,
478.333 - @Description("p2 description")
478.334 - String y) {
478.335 - super(TestMXBean.class, true);
478.336 - }
478.337 -
478.338 - public String getA() {
478.339 - return null;
478.340 - }
478.341 -
478.342 - public int getB() {
478.343 - return 0;
478.344 - }
478.345 -
478.346 - public void setB(int x) {
478.347 - }
478.348 -
478.349 - public boolean isC() {
478.350 - return false;
478.351 - }
478.352 -
478.353 - public void setC(boolean x) {
478.354 - }
478.355 -
478.356 - public void setD(float x) {
478.357 - }
478.358 -
478.359 - public String getE() {
478.360 - return null;
478.361 - }
478.362 -
478.363 - public int getF() {
478.364 - return 0;
478.365 - }
478.366 -
478.367 - public void setF(int x) {
478.368 - }
478.369 -
478.370 - public void setG(boolean x) {
478.371 - }
478.372 -
478.373 - public int opA(int p1, int p2) {
478.374 - return 0;
478.375 - }
478.376 -
478.377 - public void opB(float x) {
478.378 - }
478.379 -
478.380 - public int getH() {
478.381 - return 0;
478.382 - }
478.383 -
478.384 - public void setH(int x) {
478.385 - }
478.386 - }
478.387 -
478.388 - @MBean
478.389 - @Description("MBean description")
478.390 - public static class AnnotatedMBean {
478.391 - @Description("0-arg constructor description")
478.392 - public AnnotatedMBean() {}
478.393 -
478.394 - public AnnotatedMBean(String why) {}
478.395 -
478.396 - @Description("2-arg constructor description")
478.397 - public AnnotatedMBean(
478.398 - @Description("p1 description")
478.399 - int x,
478.400 - @Description("p2 description")
478.401 - String y) {}
478.402 -
478.403 - @ManagedAttribute
478.404 - @Description("A description")
478.405 - public String getA() {
478.406 - return null;
478.407 - }
478.408 -
478.409 - @ManagedAttribute
478.410 - @Description("B description")
478.411 - public int getB() {
478.412 - return 0;
478.413 - }
478.414 -
478.415 - @ManagedAttribute
478.416 - public void setB(int x) {
478.417 - }
478.418 -
478.419 - @ManagedAttribute
478.420 - public boolean isC() {
478.421 - return false;
478.422 - }
478.423 -
478.424 - @ManagedAttribute
478.425 - @Description("C description")
478.426 - public void setC(boolean x) {
478.427 - }
478.428 -
478.429 - @ManagedAttribute
478.430 - @Description("D description")
478.431 - public void setD(float x) {
478.432 - }
478.433 -
478.434 - @ManagedAttribute
478.435 - public String getE() {
478.436 - return null;
478.437 - }
478.438 -
478.439 - @ManagedAttribute
478.440 - public int getF() {
478.441 - return 0;
478.442 - }
478.443 -
478.444 - @ManagedAttribute
478.445 - public void setF(int x) {
478.446 - }
478.447 -
478.448 - @ManagedAttribute
478.449 - public void setG(boolean x) {
478.450 - }
478.451 -
478.452 - @ManagedAttribute
478.453 - @Description("H description")
478.454 - public int getH() {
478.455 - return 0;
478.456 - }
478.457 -
478.458 - @ManagedAttribute
478.459 - @Description("H description")
478.460 - public void setH(int x) {
478.461 - }
478.462 -
478.463 - @ManagedOperation
478.464 - @Description("opA description")
478.465 - public int opA(
478.466 - @Description("p1 description") int p1,
478.467 - @Description("p2 description") int p2) {
478.468 - return 0;
478.469 - }
478.470 -
478.471 - @ManagedOperation
478.472 - public void opB(float x) {
478.473 - }
478.474 - }
478.475 -
478.476 - @MXBean
478.477 - @Description("MBean description")
478.478 - public static class AnnotatedMXBean {
478.479 - @Description("0-arg constructor description")
478.480 - public AnnotatedMXBean() {}
478.481 -
478.482 - public AnnotatedMXBean(String why) {}
478.483 -
478.484 - @Description("2-arg constructor description")
478.485 - public AnnotatedMXBean(
478.486 - @Description("p1 description")
478.487 - int x,
478.488 - @Description("p2 description")
478.489 - String y) {}
478.490 -
478.491 - @ManagedAttribute
478.492 - @Description("A description")
478.493 - public String getA() {
478.494 - return null;
478.495 - }
478.496 -
478.497 - @ManagedAttribute
478.498 - @Description("B description")
478.499 - public int getB() {
478.500 - return 0;
478.501 - }
478.502 -
478.503 - @ManagedAttribute
478.504 - public void setB(int x) {
478.505 - }
478.506 -
478.507 - @ManagedAttribute
478.508 - public boolean isC() {
478.509 - return false;
478.510 - }
478.511 -
478.512 - @ManagedAttribute
478.513 - @Description("C description")
478.514 - public void setC(boolean x) {
478.515 - }
478.516 -
478.517 - @ManagedAttribute
478.518 - @Description("D description")
478.519 - public void setD(float x) {
478.520 - }
478.521 -
478.522 - @ManagedAttribute
478.523 - public String getE() {
478.524 - return null;
478.525 - }
478.526 -
478.527 - @ManagedAttribute
478.528 - public int getF() {
478.529 - return 0;
478.530 - }
478.531 -
478.532 - @ManagedAttribute
478.533 - public void setF(int x) {
478.534 - }
478.535 -
478.536 - @ManagedAttribute
478.537 - public void setG(boolean x) {
478.538 - }
478.539 -
478.540 - @ManagedAttribute
478.541 - @Description("H description")
478.542 - public int getH() {
478.543 - return 0;
478.544 - }
478.545 -
478.546 - @ManagedAttribute
478.547 - @Description("H description")
478.548 - public void setH(int x) {
478.549 - }
478.550 -
478.551 - @ManagedOperation
478.552 - @Description("opA description")
478.553 - public int opA(
478.554 - @Description("p1 description") int p1,
478.555 - @Description("p2 description") int p2) {
478.556 - return 0;
478.557 - }
478.558 -
478.559 - @ManagedOperation
478.560 - public void opB(float x) {
478.561 - }
478.562 - }
478.563 -
478.564 - // Negative tests follow.
478.565 -
478.566 - // Inconsistent descriptions
478.567 - public static interface BadInterface {
478.568 - @Description("foo")
478.569 - public String getFoo();
478.570 - @Description("bar")
478.571 - public void setFoo(String x);
478.572 - }
478.573 -
478.574 - public static interface BadMBean extends BadInterface {}
478.575 -
478.576 - public static class Bad implements BadMBean {
478.577 - public String getFoo() {
478.578 - return null;
478.579 - }
478.580 -
478.581 - public void setFoo(String x) {
478.582 - }
478.583 - }
478.584 -
478.585 - public static interface BadMXBean extends BadInterface {}
478.586 -
478.587 - public static class BadMXBeanImpl implements BadMXBean {
478.588 - public String getFoo() {
478.589 - return null;
478.590 - }
478.591 -
478.592 - public void setFoo(String x) {
478.593 - }
478.594 - }
478.595 -
478.596 - private static interface Defaults {
478.597 - public String defaultAttributeDescription(String name);
478.598 - public String defaultOperationDescription(String name);
478.599 - public String defaultParameterDescription(int index);
478.600 - }
478.601 -
478.602 - private static class StandardDefaults implements Defaults {
478.603 - public String defaultAttributeDescription(String name) {
478.604 - return "Attribute exposed for management";
478.605 - }
478.606 -
478.607 - public String defaultOperationDescription(String name) {
478.608 - return "Operation exposed for management";
478.609 - }
478.610 -
478.611 - public String defaultParameterDescription(int index) {
478.612 - return "";
478.613 - }
478.614 - }
478.615 - private static final Defaults standardDefaults = new StandardDefaults();
478.616 -
478.617 - private static class MXBeanDefaults implements Defaults {
478.618 - public String defaultAttributeDescription(String name) {
478.619 - return name;
478.620 - }
478.621 -
478.622 - public String defaultOperationDescription(String name) {
478.623 - return name;
478.624 - }
478.625 -
478.626 - public String defaultParameterDescription(int index) {
478.627 - return "p" + index;
478.628 - }
478.629 - }
478.630 - private static final Defaults mxbeanDefaults = new MXBeanDefaults();
478.631 -
478.632 - private static class TestCase {
478.633 - final String name;
478.634 - final Object mbean;
478.635 - final Defaults defaults;
478.636 - TestCase(String name, Object mbean, Defaults defaults) {
478.637 - this.name = name;
478.638 - this.mbean = mbean;
478.639 - this.defaults = defaults;
478.640 - }
478.641 - }
478.642 -
478.643 - private static class ExceptionTest {
478.644 - final String name;
478.645 - final Object mbean;
478.646 - ExceptionTest(String name, Object mbean) {
478.647 - this.name = name;
478.648 - this.mbean = mbean;
478.649 - }
478.650 - }
478.651 -
478.652 - private static final TestCase[] tests = {
478.653 - new TestCase("Standard MBean", new Test(), standardDefaults),
478.654 - new TestCase("Standard MBean subclass", new TestSub(), standardDefaults),
478.655 - new TestCase("StandardMBean delegating",
478.656 - new StandardMBean(new Test(), TestMBean.class, false),
478.657 - standardDefaults),
478.658 - new TestCase("StandardMBean delegating to subclass",
478.659 - new StandardMBean(new TestSub(), TestMBean.class, false),
478.660 - standardDefaults),
478.661 - new TestCase("StandardMBean subclass", new StandardSub(), standardDefaults),
478.662 -
478.663 - new TestCase("MXBean", new TestMXBeanImpl(), mxbeanDefaults),
478.664 - new TestCase("StandardMBean MXBean delegating",
478.665 - new StandardMBean(new TestMXBeanImpl(), TestMXBean.class, true),
478.666 - mxbeanDefaults),
478.667 - new TestCase("StandardMBean MXBean subclass",
478.668 - new StandardMXSub(), mxbeanDefaults),
478.669 -
478.670 - new TestCase("@MBean", new AnnotatedMBean(), standardDefaults),
478.671 - new TestCase("@MXBean", new AnnotatedMXBean(), mxbeanDefaults),
478.672 - new TestCase("StandardMBean @MBean delegating",
478.673 - new StandardMBean(new AnnotatedMBean(), null, false),
478.674 - standardDefaults),
478.675 - new TestCase("StandardMBean @MXBean delegating",
478.676 - new StandardMBean(new AnnotatedMXBean(), null, true),
478.677 - mxbeanDefaults),
478.678 - };
478.679 -
478.680 - private static final ExceptionTest[] exceptionTests = {
478.681 - new ExceptionTest("Standard MBean with inconsistent get/set", new Bad()),
478.682 - new ExceptionTest("MXBean with inconsistent get/set", new BadMXBeanImpl()),
478.683 - };
478.684 -
478.685 - public static void main(String[] args) throws Exception {
478.686 - System.out.println("=== Testing correct MBeans ===");
478.687 - for (TestCase test : tests) {
478.688 - System.out.println("Testing " + test.name + "...");
478.689 - mbs.registerMBean(test.mbean, name);
478.690 - boolean expectConstructors =
478.691 - (test.mbean.getClass() != StandardMBean.class);
478.692 - check(mbs.getMBeanInfo(name), test.defaults, expectConstructors);
478.693 - mbs.unregisterMBean(name);
478.694 - }
478.695 - System.out.println();
478.696 -
478.697 - System.out.println("=== Testing incorrect MBeans ===");
478.698 - for (ExceptionTest test : exceptionTests) {
478.699 - System.out.println("Testing " + test.name);
478.700 - try {
478.701 - mbs.registerMBean(test.mbean, name);
478.702 - fail("Registration succeeded but should not have");
478.703 - mbs.unregisterMBean(name);
478.704 - } catch (NotCompliantMBeanException e) {
478.705 - // OK
478.706 - } catch (Exception e) {
478.707 - fail("Registration failed with wrong exception: " +
478.708 - "expected NotCompliantMBeanException, got " +
478.709 - e.getClass().getName());
478.710 - }
478.711 - }
478.712 - System.out.println();
478.713 -
478.714 - if (failure == null)
478.715 - System.out.println("TEST PASSED");
478.716 - else
478.717 - throw new Exception("TEST FAILED: " + failure);
478.718 - }
478.719 -
478.720 - private static void check(
478.721 - MBeanInfo mbi, Defaults defaults, boolean expectConstructors)
478.722 - throws Exception {
478.723 - assertEquals("MBean description", mbi.getDescription());
478.724 -
478.725 - // These attributes have descriptions
478.726 - for (String attr : new String[] {"A", "B", "C", "D", "H"}) {
478.727 - MBeanAttributeInfo mbai = getAttributeInfo(mbi, attr);
478.728 - assertEquals(attr + " description", mbai.getDescription());
478.729 - }
478.730 -
478.731 - // These attributes don't have descriptions
478.732 - for (String attr : new String[] {"E", "F", "G"}) {
478.733 - // If we ever change the default description, we'll need to change
478.734 - // this test accordingly.
478.735 - MBeanAttributeInfo mbai = getAttributeInfo(mbi, attr);
478.736 - assertEquals(
478.737 - defaults.defaultAttributeDescription(attr), mbai.getDescription());
478.738 - }
478.739 -
478.740 - // This operation has a description, as do its parameters
478.741 - MBeanOperationInfo opA = getOperationInfo(mbi, "opA");
478.742 - assertEquals("opA description", opA.getDescription());
478.743 - checkSignature(opA.getSignature());
478.744 -
478.745 - // This operation has the default description, as does its parameter
478.746 - MBeanOperationInfo opB = getOperationInfo(mbi, "opB");
478.747 - assertEquals(defaults.defaultOperationDescription("opB"), opB.getDescription());
478.748 - MBeanParameterInfo opB0 = opB.getSignature()[0];
478.749 - assertEquals(defaults.defaultParameterDescription(0), opB0.getDescription());
478.750 -
478.751 - if (expectConstructors) {
478.752 - // The 0-arg and 2-arg constructors have descriptions
478.753 - MBeanConstructorInfo con0 = getConstructorInfo(mbi, 0);
478.754 - assertEquals("0-arg constructor description", con0.getDescription());
478.755 - MBeanConstructorInfo con2 = getConstructorInfo(mbi, 2);
478.756 - assertEquals("2-arg constructor description", con2.getDescription());
478.757 - checkSignature(con2.getSignature());
478.758 -
478.759 - // The 1-arg constructor does not have a description.
478.760 - // The default description for constructors and their
478.761 - // parameters is the same for all types of MBean.
478.762 - MBeanConstructorInfo con1 = getConstructorInfo(mbi, 1);
478.763 - assertEquals("Public constructor of the MBean", con1.getDescription());
478.764 - assertEquals("", con1.getSignature()[0].getDescription());
478.765 - }
478.766 - }
478.767 -
478.768 - private static void checkSignature(MBeanParameterInfo[] params) {
478.769 - for (int i = 0; i < params.length; i++) {
478.770 - MBeanParameterInfo mbpi = params[i];
478.771 - assertEquals("p" + (i+1) + " description", mbpi.getDescription());
478.772 - }
478.773 - }
478.774 -
478.775 - private static MBeanAttributeInfo getAttributeInfo(MBeanInfo mbi, String attr)
478.776 - throws Exception {
478.777 - return getFeatureInfo(mbi.getAttributes(), attr);
478.778 - }
478.779 -
478.780 - private static MBeanOperationInfo getOperationInfo(MBeanInfo mbi, String op)
478.781 - throws Exception {
478.782 - return getFeatureInfo(mbi.getOperations(), op);
478.783 - }
478.784 -
478.785 - private static MBeanConstructorInfo getConstructorInfo(MBeanInfo mbi, int nparams)
478.786 - throws Exception {
478.787 - for (MBeanConstructorInfo mbci : mbi.getConstructors()) {
478.788 - if (mbci.getSignature().length == nparams)
478.789 - return mbci;
478.790 - }
478.791 - throw new Exception("Constructor not found: " + nparams);
478.792 - }
478.793 -
478.794 - private static <T extends MBeanFeatureInfo> T getFeatureInfo(
478.795 - T[] features, String name) throws Exception {
478.796 - for (T feature : features) {
478.797 - if (feature.getName().equals(name))
478.798 - return feature;
478.799 - }
478.800 - throw new Exception("Feature not found: " + name);
478.801 - }
478.802 -
478.803 - private static void assertEquals(Object expected, Object actual) {
478.804 - if (!expected.equals(actual))
478.805 - fail("Expected " + string(expected) + ", got " + string(actual));
478.806 - }
478.807 -
478.808 - private static String string(Object x) {
478.809 - if (x instanceof String)
478.810 - return quote((String) x);
478.811 - else
478.812 - return String.valueOf(x);
478.813 - }
478.814 -
478.815 - private static String quote(String s) {
478.816 - return '"' + s.replace("\\", "\\\\").replace("\"", "\\\"") + '"';
478.817 - }
478.818 -
478.819 - private static void fail(String why) {
478.820 - StackTraceElement[] stack = new Throwable().getStackTrace();
478.821 - int n = 0;
478.822 - for (StackTraceElement elmt : stack) {
478.823 - String method = elmt.getMethodName();
478.824 - if (method.equals("fail") || method.equals("assertEquals") ||
478.825 - method.equals("checkSignature"))
478.826 - continue;
478.827 - n = elmt.getLineNumber();
478.828 - break;
478.829 - }
478.830 - System.out.println("FAILED: " + why + " (line " + n + ")");
478.831 - failure = why;
478.832 - }
478.833 -}
479.1 --- a/test/javax/management/Introspector/ObjectNameTemplateTest.java Mon Nov 23 10:04:47 2009 +0000
479.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
479.3 @@ -1,343 +0,0 @@
479.4 -/*
479.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
479.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
479.7 - *
479.8 - * This code is free software; you can redistribute it and/or modify it
479.9 - * under the terms of the GNU General Public License version 2 only, as
479.10 - * published by the Free Software Foundation.
479.11 - *
479.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
479.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
479.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
479.15 - * version 2 for more details (a copy is included in the LICENSE file that
479.16 - * accompanied this code).
479.17 - *
479.18 - * You should have received a copy of the GNU General Public License version
479.19 - * 2 along with this work; if not, write to the Free Software Foundation,
479.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
479.21 - *
479.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
479.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
479.24 - * have any questions.
479.25 - */
479.26 -
479.27 -/*
479.28 - * @test %M% %I%
479.29 - * @bug 6675526
479.30 - * @summary Test MBeans named with @ObjectNameTemplate
479.31 - * @author Jean-Francois Denise
479.32 - * @run main/othervm ObjectNameTemplateTest
479.33 - */
479.34 -import java.lang.management.ManagementFactory;
479.35 -import java.lang.reflect.Constructor;
479.36 -import java.util.ArrayList;
479.37 -import java.util.List;
479.38 -import javax.management.Attribute;
479.39 -import javax.management.AttributeList;
479.40 -import javax.management.AttributeNotFoundException;
479.41 -import javax.management.DynamicMBean;
479.42 -import javax.management.ImmutableDescriptor;
479.43 -import javax.management.InvalidAttributeValueException;
479.44 -import javax.management.JMX;
479.45 -import javax.management.MBeanException;
479.46 -import javax.management.MBeanInfo;
479.47 -import javax.management.MBeanServer;
479.48 -import javax.management.MXBean;
479.49 -import javax.management.MBean;
479.50 -import javax.management.ManagedAttribute;
479.51 -import javax.management.NotCompliantMBeanException;
479.52 -import javax.management.ObjectName;
479.53 -import javax.management.ObjectNameTemplate;
479.54 -import javax.management.ReflectionException;
479.55 -import javax.management.StandardMBean;
479.56 -
479.57 -public class ObjectNameTemplateTest {
479.58 -
479.59 - private static MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
479.60 - private static final String NAME_TEMPLATE_MULTI =
479.61 - "com.example:type=MultiStdCache,name={Name}";
479.62 - private static final String NAME_TEMPLATE_MONO =
479.63 - "com.example:{Type}={TypeValue}";
479.64 - private static final String NAME_TEMPLATE_QUOTED =
479.65 - "com.example:type=Quotted,name=\"{Name}\"";
479.66 - private static final String NAME_TEMPLATE_WRAPPED =
479.67 - "com.example:type=MgtInterface,id={Id}";
479.68 - private static final String NAME_TEMPLATE_FULL =
479.69 - "{Naming}";
479.70 - private static final String FULL_NAME = "com.example:type=NotAdvised";
479.71 - private static final String NAME1 = "toto1";
479.72 - private static final String NAME2 = "toto2";
479.73 - private static final String TYPE_KEY = "thisIsTheType";
479.74 - private static final String TYPE_VALUE = "aTypeValue";
479.75 - private static final String INVALID_NAME = "?,=*,\n, ";
479.76 - private static final int ID = 999;
479.77 - private static Object[] EMPTY_PARAMS = {};
479.78 - private static String[] EMPTY_SIGNATURE = {};
479.79 - private static final ObjectName OBJECTNAME_CACHE =
479.80 - ObjectName.valueOf("com.example:type=Cache");
479.81 - private static final ObjectName OBJECTNAME_SUBCACHE =
479.82 - ObjectName.valueOf("com.example:type=SubCache");
479.83 - private static final ObjectName OBJECTNAME_CACHEMX =
479.84 - ObjectName.valueOf("com.example:type=CacheMX");
479.85 - private static final ObjectName OBJECTNAME_SUBCACHEMX =
479.86 - ObjectName.valueOf("com.example:type=SubCacheMX");
479.87 - private static final ObjectName OBJECTNAME_DYNACACHE =
479.88 - ObjectName.valueOf("com.example:type=DynaCache");
479.89 - private static final ObjectName OBJECTNAME_STDCACHE =
479.90 - ObjectName.valueOf("com.example:type=StdCache");
479.91 - private static final ObjectName OBJECTNAME_STDCACHEMX =
479.92 - ObjectName.valueOf("com.example:type=StdCacheMX");
479.93 - private static final ObjectName OBJECTNAME_MULTI_1 =
479.94 - ObjectName.valueOf("com.example:" +
479.95 - "type=MultiStdCache,name=" + NAME1);
479.96 - private static final ObjectName OBJECTNAME_MULTI_2 =
479.97 - ObjectName.valueOf("com.example:" +
479.98 - "type=MultiStdCache,name=" + NAME2);
479.99 - private static final ObjectName OBJECTNAME_MONO =
479.100 - ObjectName.valueOf("com.example:" + TYPE_KEY + "=" +
479.101 - TYPE_VALUE);
479.102 - private static final ObjectName OBJECTNAME_QUOTED =
479.103 - ObjectName.valueOf("com.example:type=Quotted," +
479.104 - "name="+ObjectName.quote(INVALID_NAME));
479.105 - private static final ObjectName OBJECTNAME_WRAPPED_RESOURCE =
479.106 - ObjectName.valueOf("com.example:type=MgtInterface,id=" + ID);
479.107 - private static final ObjectName OBJECTNAME_FULL =
479.108 - ObjectName.valueOf(FULL_NAME);
479.109 -
479.110 - private static void test(Class<?> mbean, Object[] params,
479.111 - String[] signature, ObjectName name, String template)
479.112 - throws Exception {
479.113 - mbs.createMBean(mbean.getName(), null, params, signature);
479.114 - test(name, template);
479.115 - List<Class<?>> parameters = new ArrayList<Class<?>>();
479.116 - for (String sig : signature) {
479.117 - parameters.add(Class.forName(sig));
479.118 - }
479.119 - Class<?> classes[] = new Class<?>[parameters.size()];
479.120 - Constructor ctr = mbean.getConstructor(parameters.toArray(classes));
479.121 - Object inst = ctr.newInstance(params);
479.122 - test(inst, name, template);
479.123 - }
479.124 -
479.125 - private static void test(Object obj, ObjectName name, String template)
479.126 - throws Exception {
479.127 - mbs.registerMBean(obj, null);
479.128 - test(name, template);
479.129 - }
479.130 -
479.131 - private static void test(ObjectName name, String template)
479.132 - throws Exception {
479.133 - if (!mbs.isRegistered(name)) {
479.134 - throw new Exception("Wrong " + name + " name");
479.135 - }
479.136 - if (template != null && !mbs.getMBeanInfo(name).getDescriptor().
479.137 - getFieldValue("objectNameTemplate").equals(template)) {
479.138 - throw new Exception("Invalid Derscriptor");
479.139 - }
479.140 - mbs.unregisterMBean(name);
479.141 - }
479.142 -
479.143 - public static void main(String[] args) throws Exception {
479.144 - test(Cache.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_CACHE,
479.145 - OBJECTNAME_CACHE.toString());
479.146 -
479.147 - test(CacheMX.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_CACHEMX,
479.148 - OBJECTNAME_CACHEMX.toString());
479.149 -
479.150 - test(SubCache.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_SUBCACHE,
479.151 - OBJECTNAME_SUBCACHE.toString());
479.152 -
479.153 - test(SubCacheMX.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_SUBCACHEMX,
479.154 - OBJECTNAME_SUBCACHEMX.toString());
479.155 -
479.156 - test(DynaCache.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_DYNACACHE,
479.157 - null);
479.158 -
479.159 - test(StdCacheMX.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_STDCACHEMX,
479.160 - OBJECTNAME_STDCACHEMX.toString());
479.161 -
479.162 - test(StdCache.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_STDCACHE,
479.163 - OBJECTNAME_STDCACHE.toString());
479.164 - String[] sig = {String.class.getName()};
479.165 - Object[] params = {NAME1};
479.166 - test(MultiStdCache.class, params, sig, OBJECTNAME_MULTI_1,
479.167 - NAME_TEMPLATE_MULTI);
479.168 - Object[] params2 = {NAME2};
479.169 - test(MultiStdCache.class, params2, sig, OBJECTNAME_MULTI_2,
479.170 - NAME_TEMPLATE_MULTI);
479.171 -
479.172 - test(MonoStdCache.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_MONO,
479.173 - NAME_TEMPLATE_MONO);
479.174 -
479.175 - test(Quoted.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_QUOTED,
479.176 - NAME_TEMPLATE_QUOTED);
479.177 -
479.178 - test(new StandardMBean(new WrappedResource(), MgtInterface.class),
479.179 - OBJECTNAME_WRAPPED_RESOURCE, NAME_TEMPLATE_WRAPPED);
479.180 -
479.181 - test(FullName.class, EMPTY_PARAMS, EMPTY_SIGNATURE, OBJECTNAME_FULL,
479.182 - NAME_TEMPLATE_FULL);
479.183 - try {
479.184 - test(Wrong.class, EMPTY_PARAMS, EMPTY_SIGNATURE, null, null);
479.185 - throw new Exception("No treceived expected Exception");
479.186 - } catch (NotCompliantMBeanException ncex) {
479.187 - if (!(ncex.getCause() instanceof AttributeNotFoundException)) {
479.188 - throw new Exception("Invalid initCause");
479.189 - }
479.190 - }
479.191 - }
479.192 -
479.193 - @MBean
479.194 - @ObjectNameTemplate("{Naming}")
479.195 - public static class FullName {
479.196 -
479.197 - @ManagedAttribute
479.198 - public String getNaming() {
479.199 - return FULL_NAME;
479.200 - }
479.201 - }
479.202 -
479.203 - @ObjectNameTemplate("com.example:type=MgtInterface,id={Id}")
479.204 - public interface MgtInterface {
479.205 -
479.206 - public int getId();
479.207 - }
479.208 -
479.209 - public static class WrappedResource implements MgtInterface {
479.210 -
479.211 - public int getId() {
479.212 - return ID;
479.213 - }
479.214 - }
479.215 -
479.216 - @MBean
479.217 - @ObjectNameTemplate("com.example:type=Cache")
479.218 - public static class Cache {
479.219 - }
479.220 -
479.221 - @ObjectNameTemplate("com.example:type=SubCache")
479.222 - public static class SubCache extends Cache {
479.223 - }
479.224 -
479.225 - @MXBean
479.226 - @ObjectNameTemplate("com.example:type=CacheMX")
479.227 - public static class CacheMX {
479.228 - }
479.229 -
479.230 - @ObjectNameTemplate("com.example:type=SubCacheMX")
479.231 - public static class SubCacheMX extends CacheMX {
479.232 - }
479.233 -
479.234 - @ObjectNameTemplate("com.example:type=StdCache")
479.235 - public interface StdCacheMBean {
479.236 - }
479.237 -
479.238 - public static class StdCache implements StdCacheMBean {
479.239 - }
479.240 -
479.241 - @ObjectNameTemplate("com.example:type=StdCacheMX")
479.242 - public interface StdCacheMXBean {
479.243 - }
479.244 -
479.245 - public static class StdCacheMX implements StdCacheMXBean {
479.246 - }
479.247 -
479.248 - public static class DynaCache implements DynamicMBean {
479.249 -
479.250 - public Object getAttribute(String attribute) throws AttributeNotFoundException, MBeanException, ReflectionException {
479.251 - throw new UnsupportedOperationException("Not supported yet.");
479.252 - }
479.253 -
479.254 - public void setAttribute(Attribute attribute) throws AttributeNotFoundException, InvalidAttributeValueException, MBeanException, ReflectionException {
479.255 - throw new UnsupportedOperationException("Not supported yet.");
479.256 - }
479.257 -
479.258 - public AttributeList getAttributes(String[] attributes) {
479.259 - throw new UnsupportedOperationException("Not supported yet.");
479.260 - }
479.261 -
479.262 - public AttributeList setAttributes(AttributeList attributes) {
479.263 - throw new UnsupportedOperationException("Not supported yet.");
479.264 - }
479.265 -
479.266 - public Object invoke(String actionName, Object[] params, String[] signature) throws MBeanException, ReflectionException {
479.267 - throw new UnsupportedOperationException("Not supported yet.");
479.268 - }
479.269 -
479.270 - public MBeanInfo getMBeanInfo() {
479.271 - ImmutableDescriptor d = new ImmutableDescriptor(JMX.OBJECT_NAME_TEMPLATE + "=com.example:type=DynaCache");
479.272 -
479.273 - return new MBeanInfo("DynaCache", "Description", null, null, null, null, d);
479.274 - }
479.275 - }
479.276 -
479.277 - @ObjectNameTemplate("com.example:type=MultiStdCache,name={Name}")
479.278 - public interface MultiStdCacheMXBean {
479.279 -
479.280 - public String getName();
479.281 - }
479.282 -
479.283 - public static class MultiStdCache implements MultiStdCacheMXBean {
479.284 -
479.285 - private String name;
479.286 -
479.287 - public MultiStdCache(String name) {
479.288 - this.name = name;
479.289 - }
479.290 -
479.291 - public String getName() {
479.292 - return name;
479.293 - }
479.294 - }
479.295 -
479.296 - @ObjectNameTemplate("com.example:{Type}={TypeValue}")
479.297 - public interface MonoStdCacheMXBean {
479.298 -
479.299 - public String getTypeValue();
479.300 -
479.301 - public String getType();
479.302 - }
479.303 -
479.304 - public static class MonoStdCache implements MonoStdCacheMXBean {
479.305 -
479.306 - public String getTypeValue() {
479.307 - return TYPE_VALUE;
479.308 - }
479.309 -
479.310 - public String getType() {
479.311 - return TYPE_KEY;
479.312 - }
479.313 - }
479.314 -
479.315 - @ObjectNameTemplate("com.example:type=Quotted,name=\"{Name}\"")
479.316 - public interface QuottedMXBean {
479.317 -
479.318 - public String getName();
479.319 - }
479.320 -
479.321 - public static class Quoted implements QuottedMXBean {
479.322 -
479.323 - public String getName() {
479.324 - return INVALID_NAME;
479.325 - }
479.326 - }
479.327 -
479.328 - @ObjectNameTemplate("com.example:{Type}={TypeValue}, name={Name}")
479.329 - public interface WrongMXBean {
479.330 -
479.331 - public String getTypeValue();
479.332 -
479.333 - public String getType();
479.334 - }
479.335 -
479.336 - public static class Wrong implements WrongMXBean {
479.337 -
479.338 - public String getTypeValue() {
479.339 - return TYPE_VALUE;
479.340 - }
479.341 -
479.342 - public String getType() {
479.343 - return TYPE_KEY;
479.344 - }
479.345 - }
479.346 -}
480.1 --- a/test/javax/management/Introspector/ParameterNameTest.java Mon Nov 23 10:04:47 2009 +0000
480.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
480.3 @@ -1,116 +0,0 @@
480.4 -/*
480.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
480.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
480.7 - *
480.8 - * This code is free software; you can redistribute it and/or modify it
480.9 - * under the terms of the GNU General Public License version 2 only, as
480.10 - * published by the Free Software Foundation.
480.11 - *
480.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
480.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
480.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
480.15 - * version 2 for more details (a copy is included in the LICENSE file that
480.16 - * accompanied this code).
480.17 - *
480.18 - * You should have received a copy of the GNU General Public License version
480.19 - * 2 along with this work; if not, write to the Free Software Foundation,
480.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
480.21 - *
480.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
480.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
480.24 - * have any questions.
480.25 - */
480.26 -
480.27 -/*
480.28 - * @test %M% %I%
480.29 - * @bug 6323980
480.30 - * @summary Test that parameter names can be specified with @Name.
480.31 - * @author Eamonn McManus
480.32 - */
480.33 -
480.34 -import javax.management.MBean;
480.35 -import javax.management.MBeanInfo;
480.36 -import javax.management.MBeanOperationInfo;
480.37 -import javax.management.MBeanParameterInfo;
480.38 -import javax.management.MBeanServer;
480.39 -import javax.management.MBeanServerFactory;
480.40 -import javax.management.MXBean;
480.41 -import javax.management.ObjectName;
480.42 -
480.43 -import annot.Name;
480.44 -import javax.management.ManagedOperation;
480.45 -
480.46 -public class ParameterNameTest {
480.47 - public static interface NoddyMBean {
480.48 - public int add(int x, @Name("y") int y);
480.49 - }
480.50 -
480.51 - public static class Noddy implements NoddyMBean {
480.52 - public int add(int x, int y) {
480.53 - return x + y;
480.54 - }
480.55 - }
480.56 -
480.57 - public static interface NoddyMXBean {
480.58 - public int add(int x, @Name("y") int y);
480.59 - }
480.60 -
480.61 - public static class NoddyImpl implements NoddyMXBean {
480.62 - public int add(int x, int y) {
480.63 - return x + y;
480.64 - }
480.65 - }
480.66 -
480.67 - @MBean
480.68 - public static class NoddyAnnot {
480.69 - @ManagedOperation
480.70 - public int add(int x, @Name("y") int y) {
480.71 - return x + y;
480.72 - }
480.73 - }
480.74 -
480.75 - @MXBean
480.76 - public static class NoddyAnnotMX {
480.77 - @ManagedOperation
480.78 - public int add(int x, @Name("y") int y) {
480.79 - return x + y;
480.80 - }
480.81 - }
480.82 -
480.83 - private static final Object[] mbeans = {
480.84 - new Noddy(), new NoddyImpl(), new NoddyAnnot(), new NoddyAnnotMX(),
480.85 - };
480.86 -
480.87 - public static void main(String[] args) throws Exception {
480.88 - MBeanServer mbs = MBeanServerFactory.newMBeanServer();
480.89 - ObjectName name = new ObjectName("a:b=c");
480.90 - for (Object mbean : mbeans) {
480.91 - System.out.println("Testing " + mbean.getClass().getName());
480.92 - mbs.registerMBean(mbean, name);
480.93 - MBeanInfo mbi = mbs.getMBeanInfo(name);
480.94 - MBeanOperationInfo[] mbois = mbi.getOperations();
480.95 - assertEquals(1, mbois.length);
480.96 - MBeanParameterInfo[] mbpis = mbois[0].getSignature();
480.97 - assertEquals(2, mbpis.length);
480.98 - boolean mx = Boolean.parseBoolean(
480.99 - (String) mbi.getDescriptor().getFieldValue("mxbean"));
480.100 - assertEquals(mx ? "p0" : "p1", mbpis[0].getName());
480.101 - assertEquals("y", mbpis[1].getName());
480.102 - mbs.unregisterMBean(name);
480.103 - }
480.104 - System.out.println("TEST PASSED");
480.105 - }
480.106 -
480.107 - private static void assertEquals(Object expect, Object actual)
480.108 - throws Exception {
480.109 - boolean eq;
480.110 - if (expect == null)
480.111 - eq = (actual == null);
480.112 - else
480.113 - eq = expect.equals(actual);
480.114 - if (!eq) {
480.115 - throw new Exception(
480.116 - "TEST FAILED: expected " + expect + ", found " + actual);
480.117 - }
480.118 - }
480.119 -}
481.1 --- a/test/javax/management/Introspector/ResourceInjectionTest.java Mon Nov 23 10:04:47 2009 +0000
481.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
481.3 @@ -1,656 +0,0 @@
481.4 -/*
481.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
481.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
481.7 - *
481.8 - * This code is free software; you can redistribute it and/or modify it
481.9 - * under the terms of the GNU General Public License version 2 only, as
481.10 - * published by the Free Software Foundation.
481.11 - *
481.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
481.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
481.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
481.15 - * version 2 for more details (a copy is included in the LICENSE file that
481.16 - * accompanied this code).
481.17 - *
481.18 - * You should have received a copy of the GNU General Public License version
481.19 - * 2 along with this work; if not, write to the Free Software Foundation,
481.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
481.21 - *
481.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
481.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
481.24 - * have any questions.
481.25 - */
481.26 -
481.27 -/*
481.28 - * @test %M% %I%
481.29 - * @bug 6323980
481.30 - * @summary Test resource injection via @Resource
481.31 - * @author Eamonn McManus
481.32 - * @run main/othervm -ea ResourceInjectionTest
481.33 - */
481.34 -
481.35 -import java.io.File;
481.36 -import java.io.PrintWriter;
481.37 -import java.io.Serializable;
481.38 -import java.lang.annotation.Retention;
481.39 -import java.lang.annotation.RetentionPolicy;
481.40 -import java.lang.reflect.InvocationTargetException;
481.41 -import java.lang.reflect.Method;
481.42 -import java.lang.reflect.Modifier;
481.43 -import java.util.Arrays;
481.44 -import javax.annotation.Resource;
481.45 -import javax.management.Attribute;
481.46 -import javax.management.AttributeList;
481.47 -import javax.management.AttributeNotFoundException;
481.48 -import javax.management.DynamicMBean;
481.49 -import javax.management.InstanceNotFoundException;
481.50 -import javax.management.MBean;
481.51 -import javax.management.MBeanException;
481.52 -import javax.management.MBeanInfo;
481.53 -import javax.management.MBeanRegistrationException;
481.54 -import javax.management.MBeanServer;
481.55 -import javax.management.MBeanServerFactory;
481.56 -import javax.management.MXBean;
481.57 -import javax.management.MalformedObjectNameException;
481.58 -import javax.management.ManagedAttribute;
481.59 -import javax.management.ManagedOperation;
481.60 -import javax.management.NotCompliantMBeanException;
481.61 -import javax.management.Notification;
481.62 -import javax.management.NotificationEmitter;
481.63 -import javax.management.NotificationListener;
481.64 -import javax.management.ObjectName;
481.65 -import javax.management.ReflectionException;
481.66 -import javax.management.SendNotification;
481.67 -import javax.management.StandardEmitterMBean;
481.68 -import javax.management.StandardMBean;
481.69 -import javax.management.openmbean.MXBeanMappingFactory;
481.70 -
481.71 -public class ResourceInjectionTest {
481.72 - private static MBeanServer mbs;
481.73 - private static final ObjectName objectName;
481.74 - static {
481.75 - try {
481.76 - objectName = new ObjectName("test:type=Test");
481.77 - } catch (MalformedObjectNameException e) {
481.78 - throw new RuntimeException(e);
481.79 - }
481.80 - }
481.81 -
481.82 - /* This is somewhat nasty. In the current state of affairs, a
481.83 - * StandardEmitterMBean can only get the
481.84 - * MBeanServer to rewrite the source of a Notification from
481.85 - * the originating object's reference to its ObjectName IF
481.86 - * StandardEmitterMBean.getResource() returns a reference to the
481.87 - * wrapped object. By default it doesn't, and you need to specify
481.88 - * the option below to make it do so. We may hope that this is
481.89 - * obscure enough for users to run into it rarely if ever.
481.90 - */
481.91 - private static final StandardMBean.Options withWrappedVisible;
481.92 - private static final StandardMBean.Options withWrappedVisibleMX;
481.93 - static {
481.94 - withWrappedVisible = new StandardMBean.Options();
481.95 - withWrappedVisible.setWrappedObjectVisible(true);
481.96 - withWrappedVisibleMX = withWrappedVisible.clone();
481.97 - withWrappedVisibleMX.setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT);
481.98 - }
481.99 -
481.100 - @Retention(RetentionPolicy.RUNTIME)
481.101 - private static @interface ExpectException {
481.102 - Class<? extends Exception> value();
481.103 - }
481.104 -
481.105 - public static void main(String[] args) throws Exception {
481.106 - if (!ResourceInjectionTest.class.desiredAssertionStatus())
481.107 - throw new Exception("Test must be run with -ea");
481.108 -
481.109 - File policyFile = File.createTempFile("jmxperms", ".policy");
481.110 - policyFile.deleteOnExit();
481.111 - PrintWriter pw = new PrintWriter(policyFile);
481.112 - pw.println("grant {");
481.113 - pw.println(" permission javax.management.MBeanPermission \"*\", \"*\";");
481.114 - pw.println(" permission javax.management.MBeanServerPermission \"*\";");
481.115 - pw.println(" permission javax.management.MBeanTrustPermission \"*\";");
481.116 - pw.println("};");
481.117 - pw.close();
481.118 -
481.119 - System.setProperty("java.security.policy", policyFile.getAbsolutePath());
481.120 - System.setSecurityManager(new SecurityManager());
481.121 -
481.122 - String failure = null;
481.123 -
481.124 - for (Method m : ResourceInjectionTest.class.getDeclaredMethods()) {
481.125 - if (Modifier.isStatic(m.getModifiers()) &&
481.126 - m.getName().startsWith("test") &&
481.127 - m.getParameterTypes().length == 0) {
481.128 - ExpectException expexc = m.getAnnotation(ExpectException.class);
481.129 - mbs = MBeanServerFactory.newMBeanServer();
481.130 - try {
481.131 - m.invoke(null);
481.132 - if (expexc != null) {
481.133 - failure =
481.134 - m.getName() + " did not got expected exception " +
481.135 - expexc.value().getName();
481.136 - System.out.println(failure);
481.137 - } else
481.138 - System.out.println(m.getName() + " OK");
481.139 - } catch (InvocationTargetException ite) {
481.140 - Throwable t = ite.getCause();
481.141 - String prob = null;
481.142 - if (expexc != null) {
481.143 - if (expexc.value().isInstance(t)) {
481.144 - System.out.println(m.getName() + " OK (got expected " +
481.145 - expexc.value().getName() + ")");
481.146 - } else
481.147 - prob = "got wrong exception";
481.148 - } else
481.149 - prob = "got exception";
481.150 - if (prob != null) {
481.151 - failure = m.getName() + ": " + prob + " " +
481.152 - t.getClass().getName();
481.153 - System.out.println(failure);
481.154 - t.printStackTrace(System.out);
481.155 - }
481.156 - }
481.157 - }
481.158 - }
481.159 - if (failure == null)
481.160 - System.out.println("TEST PASSED");
481.161 - else
481.162 - throw new Exception("TEST FAILED: " + failure);
481.163 - }
481.164 -
481.165 - private static interface Send {
481.166 - public void send();
481.167 - }
481.168 -
481.169 - // Test @Resource in MBean defined by annotations
481.170 -
481.171 - @MBean
481.172 - public static class Annotated {
481.173 - @Resource
481.174 - private volatile MBeanServer mbeanServer;
481.175 - @Resource
481.176 - private volatile ObjectName myName;
481.177 -
481.178 - @ManagedAttribute
481.179 - public ObjectName getMyName() {
481.180 - return myName;
481.181 - }
481.182 -
481.183 - @ManagedOperation
481.184 - public void unregisterSelf()
481.185 - throws InstanceNotFoundException, MBeanRegistrationException {
481.186 - mbeanServer.unregisterMBean(myName);
481.187 - }
481.188 - }
481.189 -
481.190 - private static void testAnnotated() throws Exception {
481.191 - testMBean(new Annotated());
481.192 - }
481.193 -
481.194 - private static void testAnnotatedWrapped() throws Exception {
481.195 - testMBean(new StandardMBean(new Annotated(), null));
481.196 - }
481.197 -
481.198 - @MBean
481.199 - public static class AnnotatedSend extends Annotated implements Send {
481.200 - @Resource
481.201 - private volatile SendNotification sender;
481.202 -
481.203 - @ManagedOperation
481.204 - public void send() {
481.205 - sender.sendNotification(new Notification("type", this, 0L));
481.206 - }
481.207 - }
481.208 -
481.209 - private static void testAnnotatedSend() throws Exception {
481.210 - testMBean(new AnnotatedSend());
481.211 - }
481.212 -
481.213 - private static void testAnnotatedSendWrapped() throws Exception {
481.214 - testMBean(new StandardEmitterMBean(
481.215 - new AnnotatedSend(), null, withWrappedVisible, null));
481.216 - }
481.217 -
481.218 - // Test @Resource in MXBean defined by annotations
481.219 -
481.220 - @MXBean
481.221 - public static class AnnotatedMX {
481.222 - @Resource
481.223 - private volatile MBeanServer mbeanServer;
481.224 - @Resource
481.225 - private volatile ObjectName myName;
481.226 -
481.227 - @ManagedAttribute
481.228 - public ObjectName getMyName() {
481.229 - return myName;
481.230 - }
481.231 -
481.232 - @ManagedOperation
481.233 - public void unregisterSelf()
481.234 - throws InstanceNotFoundException, MBeanRegistrationException {
481.235 - mbeanServer.unregisterMBean(myName);
481.236 - }
481.237 - }
481.238 -
481.239 - private static void testAnnotatedMX() throws Exception {
481.240 - testMBean(new AnnotatedMX());
481.241 - }
481.242 -
481.243 - private static void testAnnotatedMXWrapped() throws Exception {
481.244 - testMBean(new StandardMBean(new AnnotatedMX(), null, true));
481.245 - }
481.246 -
481.247 - public static class AnnotatedMXSend extends AnnotatedMX implements Send {
481.248 - @Resource
481.249 - private volatile SendNotification sender;
481.250 -
481.251 - @ManagedOperation
481.252 - public void send() {
481.253 - sender.sendNotification(new Notification("type", this, 0L));
481.254 - }
481.255 - }
481.256 -
481.257 - private static void testAnnotatedMXSend() throws Exception {
481.258 - testMBean(new AnnotatedMXSend());
481.259 - }
481.260 -
481.261 - private static void testAnnotatedMXSendWrapped() throws Exception {
481.262 - testMBean(new StandardEmitterMBean(
481.263 - new AnnotatedMXSend(), null, withWrappedVisibleMX, null));
481.264 - }
481.265 -
481.266 - // Test @Resource in Standard MBean
481.267 -
481.268 - public static interface SimpleStandardMBean {
481.269 - public ObjectName getMyName();
481.270 - public void unregisterSelf() throws Exception;
481.271 - }
481.272 -
481.273 - public static class SimpleStandard implements SimpleStandardMBean {
481.274 - @Resource(type = MBeanServer.class)
481.275 - private volatile Object mbeanServer;
481.276 - @Resource(type = ObjectName.class)
481.277 - private volatile Object myName;
481.278 -
481.279 - public ObjectName getMyName() {
481.280 - return (ObjectName) myName;
481.281 - }
481.282 -
481.283 - public void unregisterSelf() throws Exception {
481.284 - ((MBeanServer) mbeanServer).unregisterMBean(getMyName());
481.285 - }
481.286 - }
481.287 -
481.288 - private static void testStandard() throws Exception {
481.289 - testMBean(new SimpleStandard());
481.290 - }
481.291 -
481.292 - private static void testStandardWrapped() throws Exception {
481.293 - testMBean(new StandardMBean(new SimpleStandard(), SimpleStandardMBean.class));
481.294 - }
481.295 -
481.296 - public static interface SimpleStandardSendMBean extends SimpleStandardMBean {
481.297 - public void send();
481.298 - }
481.299 -
481.300 - public static class SimpleStandardSend
481.301 - extends SimpleStandard implements SimpleStandardSendMBean {
481.302 - @Resource(type = SendNotification.class)
481.303 - private volatile Object sender;
481.304 -
481.305 - public void send() {
481.306 - ((SendNotification) sender).sendNotification(
481.307 - new Notification("type", this, 0L));
481.308 - }
481.309 - }
481.310 -
481.311 - private static void testStandardSend() throws Exception {
481.312 - testMBean(new SimpleStandardSend());
481.313 - }
481.314 -
481.315 - private static void testStandardSendWrapped() throws Exception {
481.316 - testMBean(new StandardEmitterMBean(
481.317 - new SimpleStandardSend(), SimpleStandardSendMBean.class,
481.318 - withWrappedVisible, null));
481.319 - }
481.320 -
481.321 - // Test @Resource in MXBean
481.322 -
481.323 - public static interface SimpleMXBean {
481.324 - public ObjectName getMyName();
481.325 - public void unregisterSelf() throws Exception;
481.326 - }
481.327 -
481.328 - public static class SimpleMX implements SimpleMXBean {
481.329 - @Resource(type = MBeanServer.class)
481.330 - private volatile Object mbeanServer;
481.331 - @Resource(type = ObjectName.class)
481.332 - private volatile Object myName;
481.333 -
481.334 - public ObjectName getMyName() {
481.335 - return (ObjectName) myName;
481.336 - }
481.337 -
481.338 - public void unregisterSelf() throws Exception {
481.339 - ((MBeanServer) mbeanServer).unregisterMBean(getMyName());
481.340 - }
481.341 - }
481.342 -
481.343 - private static void testMX() throws Exception {
481.344 - testMBean(new SimpleMX());
481.345 - }
481.346 -
481.347 - private static void testMXWrapped() throws Exception {
481.348 - testMBean(new StandardMBean(new SimpleMX(), SimpleMXBean.class, true));
481.349 - }
481.350 -
481.351 - public static interface SimpleMXBeanSend extends SimpleMXBean {
481.352 - public void send();
481.353 - }
481.354 -
481.355 - public MBeanServer getMbs() {
481.356 - return mbs;
481.357 - }
481.358 -
481.359 - public static class SimpleMXSend extends SimpleMX implements SimpleMXBeanSend {
481.360 - @Resource(type = SendNotification.class)
481.361 - private volatile Object sender;
481.362 -
481.363 - public void send() {
481.364 - ((SendNotification) sender).sendNotification(
481.365 - new Notification("type", this, 0L));
481.366 - }
481.367 - }
481.368 -
481.369 - private static void testMXSend() throws Exception {
481.370 - testMBean(new SimpleMXSend());
481.371 - }
481.372 -
481.373 - private static void testMXSendWrapped() throws Exception {
481.374 - testMBean(new StandardEmitterMBean(
481.375 - new SimpleMXSend(), SimpleMXBeanSend.class,
481.376 - withWrappedVisibleMX, null));
481.377 - }
481.378 -
481.379 - // Test @Resource in Dynamic MBean
481.380 -
481.381 - private static class SimpleDynamic implements DynamicMBean {
481.382 - private MBeanServer mbeanServer;
481.383 - private ObjectName myName;
481.384 -
481.385 - @Resource
481.386 - private synchronized void setMBeanServer(MBeanServer mbs) {
481.387 - mbeanServer = mbs;
481.388 - }
481.389 -
481.390 - @Resource(type = ObjectName.class)
481.391 - private synchronized void setObjectName(Serializable name) {
481.392 - myName = (ObjectName) name;
481.393 - }
481.394 -
481.395 - public synchronized Object getAttribute(String attribute)
481.396 - throws AttributeNotFoundException {
481.397 - if (attribute.equals("MyName"))
481.398 - return myName;
481.399 - throw new AttributeNotFoundException(attribute);
481.400 - }
481.401 -
481.402 - public void setAttribute(Attribute attribute)
481.403 - throws AttributeNotFoundException {
481.404 - throw new AttributeNotFoundException(attribute.getName());
481.405 - }
481.406 -
481.407 - public synchronized AttributeList getAttributes(String[] attributes) {
481.408 - AttributeList list = new AttributeList();
481.409 - for (String name : attributes) {
481.410 - if (name.equals("MyName"))
481.411 - list.add(new Attribute("MyName", myName));
481.412 - }
481.413 - return list;
481.414 - }
481.415 -
481.416 - public AttributeList setAttributes(AttributeList attributes) {
481.417 - return new AttributeList();
481.418 - }
481.419 -
481.420 - public synchronized Object invoke(
481.421 - String actionName, Object[] params, String[] signature)
481.422 - throws MBeanException, ReflectionException {
481.423 - if (actionName.equals("unregisterSelf") &&
481.424 - (params == null || params.length == 0) &&
481.425 - (signature == null || signature.length == 0)) {
481.426 - try {
481.427 - mbeanServer.unregisterMBean(myName);
481.428 - return null;
481.429 - } catch (Exception x) {
481.430 - throw new MBeanException(x);
481.431 - }
481.432 - } else {
481.433 - Exception x = new NoSuchMethodException(
481.434 - actionName + Arrays.toString(signature));
481.435 - throw new MBeanException(x);
481.436 - }
481.437 - }
481.438 -
481.439 - public MBeanInfo getMBeanInfo() {
481.440 - DynamicMBean mbean = new StandardMBean(
481.441 - new SimpleStandard(), SimpleStandardMBean.class, false);
481.442 - return mbean.getMBeanInfo();
481.443 - }
481.444 - }
481.445 -
481.446 - private static void testDynamic() throws Exception {
481.447 - testMBean(new SimpleDynamic());
481.448 - }
481.449 -
481.450 - private static class SimpleDynamicSend extends SimpleDynamic {
481.451 - private SendNotification sender;
481.452 -
481.453 - @Resource
481.454 - private synchronized void setSender(SendNotification sender) {
481.455 - this.sender = sender;
481.456 - }
481.457 -
481.458 - @Override
481.459 - public synchronized Object invoke(
481.460 - String actionName, Object[] params, String[] signature)
481.461 - throws MBeanException, ReflectionException {
481.462 - if (actionName.equals("send")) {
481.463 - sender.sendNotification(new Notification("type", this, 0L));
481.464 - return null;
481.465 - } else
481.466 - return super.invoke(actionName, params, signature);
481.467 - }
481.468 - }
481.469 -
481.470 - private static void testDynamicSend() throws Exception {
481.471 - testMBean(new SimpleDynamicSend());
481.472 - }
481.473 -
481.474 - // Test that @Resource classes don't have to be public
481.475 - // They can even be defined within methods!
481.476 - // But you can't have any @ManagedAttributes or @ManagedOperations
481.477 - // in such MBeans so their utility is limited.
481.478 -
481.479 - private static void testNonPublic() throws Exception {
481.480 - @MBean
481.481 - class NonPublic {
481.482 - @Resource
481.483 - ObjectName myName;
481.484 - }
481.485 - assert !Modifier.isPublic(NonPublic.class.getModifiers());
481.486 - NonPublic mbean = new NonPublic();
481.487 - mbs.registerMBean(mbean, objectName);
481.488 - assert objectName.equals(mbean.myName);
481.489 - }
481.490 -
481.491 - // Test inheritance and multiple injections of the same value
481.492 -
481.493 - private static class ManyResources extends AnnotatedSend {
481.494 - @Resource
481.495 - private volatile ObjectName myName; // same name as in parent!
481.496 - @Resource(type=ObjectName.class)
481.497 - private volatile Object myOtherName;
481.498 - private volatile ObjectName myThirdName;
481.499 - private volatile ObjectName myFourthName;
481.500 - private volatile int methodCalls;
481.501 - @Resource
481.502 - private volatile SendNotification send1;
481.503 - @Resource(type = SendNotification.class)
481.504 - private volatile Object send2;
481.505 -
481.506 - @Resource
481.507 - void setMyName(ObjectName name) {
481.508 - myThirdName = name;
481.509 - methodCalls++;
481.510 - }
481.511 -
481.512 - @Resource(type=ObjectName.class)
481.513 - private void setMyNameAgain(ObjectName name) {
481.514 - myFourthName = name;
481.515 - methodCalls++;
481.516 - }
481.517 -
481.518 - void check() {
481.519 - assert objectName.equals(myName) : myName;
481.520 - for (ObjectName name : new ObjectName[] {
481.521 - (ObjectName)myOtherName, myThirdName, myFourthName
481.522 - }) {
481.523 - assert myName == name : name;
481.524 - }
481.525 - assert methodCalls == 2 : methodCalls;
481.526 - assert send1 != null && send2 == send1;
481.527 - }
481.528 - }
481.529 -
481.530 - private static void testManyResources() throws Exception {
481.531 - ManyResources mr = new ManyResources();
481.532 - testMBean(mr);
481.533 - mr.check();
481.534 - }
481.535 -
481.536 - // Test that method override doesn't lead to multiple calls of the same method
481.537 -
481.538 - private static class ManyResourcesSub extends ManyResources {
481.539 - private boolean called;
481.540 -
481.541 - @Override
481.542 - @Resource
481.543 - void setMyName(ObjectName name) {
481.544 - super.setMyName(name);
481.545 - called = true;
481.546 - }
481.547 -
481.548 - void check2() {
481.549 - assert called;
481.550 - }
481.551 - }
481.552 -
481.553 - private static void testOverride() throws Exception {
481.554 - ManyResourcesSub mrs = new ManyResourcesSub();
481.555 - testMBean(mrs);
481.556 - mrs.check();
481.557 - mrs.check2();
481.558 - }
481.559 -
481.560 - // Test that @Resource is illegal on static fields
481.561 -
481.562 - @MBean
481.563 - public static class StaticResource {
481.564 - @Resource
481.565 - private static ObjectName name;
481.566 - }
481.567 -
481.568 - @ExpectException(NotCompliantMBeanException.class)
481.569 - private static void testStaticResource() throws Exception {
481.570 - testMBean(new StaticResource());
481.571 - }
481.572 -
481.573 - // Test that @Resource is illegal on static methods
481.574 -
481.575 - @MBean
481.576 - public static class StaticResourceMethod {
481.577 - @Resource
481.578 - private static void setObjectName(ObjectName name) {}
481.579 - }
481.580 -
481.581 - @ExpectException(NotCompliantMBeanException.class)
481.582 - private static void testStaticResourceMethod() throws Exception {
481.583 - testMBean(new StaticResourceMethod());
481.584 - }
481.585 -
481.586 - // Test that @Resource is illegal on methods that don't return void
481.587 -
481.588 - @MBean
481.589 - public static class NonVoidMethod {
481.590 - @Resource
481.591 - private String setObjectName(ObjectName name) {
481.592 - return "oops";
481.593 - }
481.594 - }
481.595 -
481.596 - @ExpectException(NotCompliantMBeanException.class)
481.597 - private static void testNonVoidMethod() throws Exception {
481.598 - testMBean(new NonVoidMethod());
481.599 - }
481.600 -
481.601 - // Test that @Resource is illegal on methods with no arguments
481.602 -
481.603 - @MBean
481.604 - public static class NoArgMethod {
481.605 - @Resource(type=ObjectName.class)
481.606 - private void setObjectName() {}
481.607 - }
481.608 -
481.609 - @ExpectException(NotCompliantMBeanException.class)
481.610 - private static void testNoArgMethod() throws Exception {
481.611 - testMBean(new NoArgMethod());
481.612 - }
481.613 -
481.614 - // Test that @Resource is illegal on methods with more than one argument
481.615 -
481.616 - @MBean
481.617 - public static class MultiArgMethod {
481.618 - @Resource
481.619 - private void setObjectName(ObjectName name, String what) {}
481.620 - }
481.621 -
481.622 - @ExpectException(NotCompliantMBeanException.class)
481.623 - private static void testMultiArgMethod() throws Exception {
481.624 - testMBean(new MultiArgMethod());
481.625 - }
481.626 -
481.627 - private static class CountListener implements NotificationListener {
481.628 - volatile int count;
481.629 - public void handleNotification(Notification notification, Object handback) {
481.630 - count++;
481.631 - }
481.632 - }
481.633 -
481.634 - private static void testMBean(Object mbean) throws Exception {
481.635 - mbs.registerMBean(mbean, objectName);
481.636 -
481.637 - final ObjectName name = (ObjectName) mbs.getAttribute(objectName, "MyName");
481.638 - assert objectName.equals(name) : name;
481.639 -
481.640 - if (mbean instanceof Send || mbean instanceof NotificationEmitter) {
481.641 - assert mbs.isInstanceOf(name, NotificationEmitter.class.getName());
481.642 - CountListener countL = new CountListener();
481.643 - mbs.addNotificationListener(name, countL, null, null);
481.644 - NotificationListener checkSource = new NotificationListener() {
481.645 - public void handleNotification(Notification n, Object h) {
481.646 - assert n.getSource().equals(name) : n.getSource();
481.647 - }
481.648 - };
481.649 - mbs.addNotificationListener(name, checkSource, null, null);
481.650 - mbs.invoke(objectName, "send", null, null);
481.651 - assert countL.count == 1;
481.652 - mbs.removeNotificationListener(name, checkSource);
481.653 - mbs.removeNotificationListener(name, countL, null, null);
481.654 - }
481.655 -
481.656 - mbs.invoke(objectName, "unregisterSelf", null, null);
481.657 - assert !mbs.isRegistered(objectName);
481.658 - }
481.659 -}
482.1 --- a/test/javax/management/MBeanServer/AttributeListMapTest.java Mon Nov 23 10:04:47 2009 +0000
482.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
482.3 @@ -1,115 +0,0 @@
482.4 -/*
482.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
482.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
482.7 - *
482.8 - * This code is free software; you can redistribute it and/or modify it
482.9 - * under the terms of the GNU General Public License version 2 only, as
482.10 - * published by the Free Software Foundation.
482.11 - *
482.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
482.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
482.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
482.15 - * version 2 for more details (a copy is included in the LICENSE file that
482.16 - * accompanied this code).
482.17 - *
482.18 - * You should have received a copy of the GNU General Public License version
482.19 - * 2 along with this work; if not, write to the Free Software Foundation,
482.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
482.21 - *
482.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
482.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
482.24 - * have any questions.
482.25 - */
482.26 -
482.27 -/*
482.28 - * @test
482.29 - * @bug 6336968
482.30 - * @summary Test AttributeList.toMap
482.31 - * @author Eamonn McManus
482.32 - */
482.33 -
482.34 -import java.math.BigInteger;
482.35 -import java.util.Arrays;
482.36 -import java.util.HashMap;
482.37 -import java.util.HashSet;
482.38 -import java.util.Map;
482.39 -import javax.management.Attribute;
482.40 -import javax.management.AttributeList;
482.41 -
482.42 -public class AttributeListMapTest {
482.43 -
482.44 - private static String failure;
482.45 -
482.46 - public static void main(String[] args) throws Exception {
482.47 - AttributeList attrs = new AttributeList(Arrays.asList(
482.48 - new Attribute("Str", "Five"),
482.49 - new Attribute("Int", 5),
482.50 - new Attribute("Flt", 5.0)));
482.51 -
482.52 - Map<String, Object> map = attrs.toMap();
482.53 - final Map<String, Object> expectMap = new HashMap<String, Object>();
482.54 - for (Attribute attr : attrs.asList())
482.55 - expectMap.put(attr.getName(), attr.getValue());
482.56 - assertEquals("Initial map", expectMap, map);
482.57 - assertEquals("Initial map size", 3, map.size());
482.58 - assertEquals("Name set", expectMap.keySet(), map.keySet());
482.59 - assertEquals("Values", new HashSet<Object>(expectMap.values()),
482.60 - new HashSet<Object>(map.values()));
482.61 - assertEquals("Entry set", expectMap.entrySet(), map.entrySet());
482.62 -
482.63 - AttributeList attrs2 = new AttributeList(map);
482.64 - assertEquals("AttributeList from Map", attrs, attrs2);
482.65 - // This assumes that the Map conserves the order of the attributes,
482.66 - // which is not specified but true because we use LinkedHashMap.
482.67 -
482.68 - // Check that toMap fails if the list contains non-Attribute elements.
482.69 - AttributeList attrs3 = new AttributeList(attrs);
482.70 - attrs3.add("Hello"); // allowed but curious
482.71 - try {
482.72 - map = attrs3.toMap();
482.73 - fail("toMap succeeded on list with non-Attribute elements");
482.74 - } catch (Exception e) {
482.75 - assertEquals("Exception for toMap with non-Atttribute elements",
482.76 - IllegalArgumentException.class, e.getClass());
482.77 - }
482.78 -
482.79 - // Check that the Map does not reflect changes made to the list after
482.80 - // the Map was obtained.
482.81 - AttributeList attrs4 = new AttributeList(attrs);
482.82 - map = attrs4.toMap();
482.83 - attrs4.add(new Attribute("Big", new BigInteger("5")));
482.84 - assertEquals("Map after adding element to list", expectMap, map);
482.85 -
482.86 - // Check that if there is more than one Attribute with the same name
482.87 - // then toMap() chooses the last of them.
482.88 - AttributeList attrs5 = new AttributeList(attrs);
482.89 - attrs5.add(new Attribute("Str", "Cinq"));
482.90 - map = attrs5.toMap();
482.91 - assertEquals("Size of Map for list with duplicate attribute name",
482.92 - 3, map.size());
482.93 - Object value = map.get("Str");
482.94 - assertEquals("Value of Str in Map for list with two values for it",
482.95 - "Cinq", value);
482.96 -
482.97 - if (failure == null)
482.98 - System.out.println("TEST PASSED");
482.99 - else
482.100 - throw new Exception("TEST FAILED: " + failure);
482.101 - }
482.102 -
482.103 - private static void assertEquals(String what, Object expect, Object actual) {
482.104 - if (eq(expect, actual))
482.105 - System.out.println("OK: " + what);
482.106 - else
482.107 - fail(what + ": expected " + expect + ", got " + actual);
482.108 - }
482.109 -
482.110 - private static boolean eq(Object x, Object y) {
482.111 - return (x == null) ? (y == null) : x.equals(y);
482.112 - }
482.113 -
482.114 - private static void fail(String why) {
482.115 - System.out.println("FAIL: " + why);
482.116 - failure = why;
482.117 - }
482.118 -}
483.1 --- a/test/javax/management/MBeanServer/DynamicWrapperMBeanTest.java Mon Nov 23 10:04:47 2009 +0000
483.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
483.3 @@ -1,405 +0,0 @@
483.4 -/*
483.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
483.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
483.7 - *
483.8 - * This code is free software; you can redistribute it and/or modify it
483.9 - * under the terms of the GNU General Public License version 2 only, as
483.10 - * published by the Free Software Foundation.
483.11 - *
483.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
483.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
483.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
483.15 - * version 2 for more details (a copy is included in the LICENSE file that
483.16 - * accompanied this code).
483.17 - *
483.18 - * You should have received a copy of the GNU General Public License version
483.19 - * 2 along with this work; if not, write to the Free Software Foundation,
483.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
483.21 - *
483.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
483.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
483.24 - * have any questions.
483.25 - */
483.26 -
483.27 -/*
483.28 - * @test DynamicWrapperMBeanTest
483.29 - * @bug 6624232 6776225
483.30 - * @summary Test the DynamicWrapperMBean interface
483.31 - * @author Eamonn McManus
483.32 - */
483.33 -
483.34 -import java.lang.management.ManagementFactory;
483.35 -import javax.annotation.Resource;
483.36 -import javax.management.JMX;
483.37 -import javax.management.ListenerNotFoundException;
483.38 -import javax.management.MBeanNotificationInfo;
483.39 -import javax.management.MBeanServer;
483.40 -import javax.management.Notification;
483.41 -import javax.management.NotificationBroadcaster;
483.42 -import javax.management.NotificationBroadcasterSupport;
483.43 -import javax.management.NotificationEmitter;
483.44 -import javax.management.NotificationFilter;
483.45 -import javax.management.NotificationInfo;
483.46 -import javax.management.NotificationListener;
483.47 -import javax.management.ObjectName;
483.48 -import javax.management.SendNotification;
483.49 -import javax.management.StandardEmitterMBean;
483.50 -import javax.management.StandardMBean;
483.51 -import javax.management.modelmbean.ModelMBeanInfo;
483.52 -import javax.management.modelmbean.ModelMBeanInfoSupport;
483.53 -import javax.management.modelmbean.ModelMBeanOperationInfo;
483.54 -import javax.management.modelmbean.RequiredModelMBean;
483.55 -import static javax.management.StandardMBean.Options;
483.56 -
483.57 -public class DynamicWrapperMBeanTest {
483.58 - private static String failure;
483.59 -
483.60 - public static void main(String[] args) throws Exception {
483.61 - wrapTest();
483.62 - notifTest();
483.63 -
483.64 - if (failure == null)
483.65 - System.out.println("TEST PASSED");
483.66 - else
483.67 - throw new Exception("TEST FAILED: " + failure);
483.68 - }
483.69 -
483.70 - private static final Options wrappedVisOpts = new Options();
483.71 - private static final Options wrappedInvisOpts = new Options();
483.72 - static {
483.73 - wrappedVisOpts.setWrappedObjectVisible(true);
483.74 - wrappedInvisOpts.setWrappedObjectVisible(false);
483.75 - }
483.76 -
483.77 - public static interface WrappedMBean {
483.78 - public void sayHello();
483.79 - }
483.80 - public static class Wrapped implements WrappedMBean {
483.81 - public void sayHello() {
483.82 - System.out.println("Hello");
483.83 - }
483.84 - }
483.85 -
483.86 - private static void wrapTest() throws Exception {
483.87 - if (Wrapped.class.getClassLoader() ==
483.88 - StandardMBean.class.getClassLoader()) {
483.89 - throw new Exception(
483.90 - "TEST ERROR: Resource and StandardMBean have same ClassLoader");
483.91 - }
483.92 -
483.93 - assertEquals("Options withWrappedObjectVisible(false)",
483.94 - new Options(), wrappedInvisOpts);
483.95 -
483.96 - Wrapped resource = new Wrapped();
483.97 -
483.98 - StandardMBean visible =
483.99 - new StandardMBean(resource, WrappedMBean.class, wrappedVisOpts);
483.100 - StandardMBean invisible =
483.101 - new StandardMBean(resource, WrappedMBean.class, wrappedInvisOpts);
483.102 -
483.103 - assertEquals("getResource withWrappedObjectVisible(true)",
483.104 - resource, visible.getWrappedObject());
483.105 - assertEquals("getResource withWrappedObjectVisible(false)",
483.106 - invisible, invisible.getWrappedObject());
483.107 -
483.108 - System.out.println("===Testing StandardMBean===");
483.109 -
483.110 - ObjectName visibleName = new ObjectName("a:type=visible");
483.111 - ObjectName invisibleName = new ObjectName("a:type=invisible");
483.112 - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
483.113 - mbs.registerMBean(visible, visibleName);
483.114 - mbs.registerMBean(invisible, invisibleName);
483.115 -
483.116 - assertEquals("ClassLoader for visible resource",
483.117 - Wrapped.class.getClassLoader(),
483.118 - mbs.getClassLoaderFor(visibleName));
483.119 - assertEquals("ClassLoader for invisible resource",
483.120 - StandardMBean.class.getClassLoader(),
483.121 - mbs.getClassLoaderFor(invisibleName));
483.122 -
483.123 - assertEquals("isInstanceOf(WrappedMBean) for visible wrapped",
483.124 - true, mbs.isInstanceOf(visibleName, WrappedMBean.class.getName()));
483.125 - assertEquals("isInstanceOf(WrappedMBean) for invisible wrapped",
483.126 - false, mbs.isInstanceOf(invisibleName, WrappedMBean.class.getName()));
483.127 - assertEquals("isInstanceOf(StandardMBean) for visible wrapped",
483.128 - false, mbs.isInstanceOf(visibleName, StandardMBean.class.getName()));
483.129 - assertEquals("isInstanceOf(StandardMBean) for invisible wrapped",
483.130 - true, mbs.isInstanceOf(invisibleName, StandardMBean.class.getName()));
483.131 -
483.132 - mbs.unregisterMBean(visibleName);
483.133 - mbs.unregisterMBean(invisibleName);
483.134 -
483.135 - System.out.println("===Testing RequiredModelMBean===");
483.136 -
483.137 - // Godawful Model MBeans...
483.138 - ModelMBeanOperationInfo mmboi = new ModelMBeanOperationInfo(
483.139 - "say hello to the nice man", Wrapped.class.getMethod("sayHello"));
483.140 - ModelMBeanInfo visibleMmbi = new ModelMBeanInfoSupport(
483.141 - Wrapped.class.getName(), "Visible wrapped", null, null,
483.142 - new ModelMBeanOperationInfo[] {mmboi}, null);
483.143 - ModelMBeanInfo invisibleMmbi = new ModelMBeanInfoSupport(
483.144 - Wrapped.class.getName(), "Invisible wrapped", null, null,
483.145 - new ModelMBeanOperationInfo[] {mmboi}, null);
483.146 - RequiredModelMBean visibleRmmb = new RequiredModelMBean(visibleMmbi);
483.147 - RequiredModelMBean invisibleRmmb = new RequiredModelMBean(invisibleMmbi);
483.148 - visibleRmmb.setManagedResource(resource, "VisibleObjectReference");
483.149 - invisibleRmmb.setManagedResource(resource, "ObjectReference");
483.150 -
483.151 - mbs.registerMBean(visibleRmmb, visibleName);
483.152 - mbs.registerMBean(invisibleRmmb, invisibleName);
483.153 -
483.154 - assertEquals("ClassLoader for visible wrapped",
483.155 - Wrapped.class.getClassLoader(),
483.156 - mbs.getClassLoaderFor(visibleName));
483.157 - assertEquals("ClassLoader for invisible wrapped",
483.158 - StandardMBean.class.getClassLoader(),
483.159 - mbs.getClassLoaderFor(invisibleName));
483.160 -
483.161 - assertEquals("isInstanceOf(WrappedMBean) for visible resource",
483.162 - true, mbs.isInstanceOf(visibleName, WrappedMBean.class.getName()));
483.163 - assertEquals("isInstanceOf(WrappedMBean) for invisible resource",
483.164 - false, mbs.isInstanceOf(invisibleName, WrappedMBean.class.getName()));
483.165 - assertEquals("isInstanceOf(RequiredModelMBean) for visible resource",
483.166 - false, mbs.isInstanceOf(visibleName, RequiredModelMBean.class.getName()));
483.167 - assertEquals("isInstanceOf(RequiredModelMBean) for invisible resource",
483.168 - true, mbs.isInstanceOf(invisibleName, RequiredModelMBean.class.getName()));
483.169 -
483.170 - mbs.unregisterMBean(visibleName);
483.171 - mbs.unregisterMBean(invisibleName);
483.172 - }
483.173 -
483.174 - private static enum WrapType {
483.175 - NBS("NotificationBroadcasterSupport"),
483.176 - INJ("@Resource SendNotification"),
483.177 - STD_MBEAN_NBS("StandardMBean delegating to NotificationBroadcasterSupport"),
483.178 - STD_MBEAN_INJ("StandardMBean delegating to @Resource SendNotification"),
483.179 - STD_MBEAN_SUB_NBS("StandardMBean subclass implementing NotificationBroadcaster"),
483.180 - STD_MBEAN_SUB_INJ("StandardMBean subclass with @Resource SendNotification"),
483.181 - STD_EMIT_MBEAN_NBS("StandardEmitterMBean delegating to NotificationBroadcasterSupport"),
483.182 - STD_EMIT_MBEAN_INJ("StandardEmitterMBean delegating to @Resource SendNotification"),
483.183 - STD_EMIT_MBEAN_SUB("StandardEmitterMBean subclass"),
483.184 - STD_EMIT_MBEAN_SUB_INJ("StandardEmitterMBean subclass with @Resource SendNotification");
483.185 -
483.186 - WrapType(String s) {
483.187 - this.s = s;
483.188 - }
483.189 -
483.190 - @Override
483.191 - public String toString() {
483.192 - return s;
483.193 - }
483.194 -
483.195 - private final String s;
483.196 - }
483.197 -
483.198 - @NotificationInfo(
483.199 - types = {"foo", "bar"}
483.200 - )
483.201 - public static interface BroadcasterMBean {
483.202 - public void send(Notification n);
483.203 - }
483.204 -
483.205 - public static class Broadcaster
483.206 - extends NotificationBroadcasterSupport implements BroadcasterMBean {
483.207 - public void send(Notification n) {
483.208 - super.sendNotification(n);
483.209 - }
483.210 - }
483.211 -
483.212 - public static interface SendNotifMBean extends BroadcasterMBean {
483.213 - }
483.214 -
483.215 - public static class SendNotif implements SendNotifMBean {
483.216 - @Resource
483.217 - private volatile SendNotification sendNotif;
483.218 -
483.219 - public void send(Notification n) {
483.220 - sendNotif.sendNotification(n);
483.221 - }
483.222 - }
483.223 -
483.224 - public static class StdBroadcaster
483.225 - extends StandardMBean
483.226 - implements BroadcasterMBean, NotificationBroadcaster {
483.227 - private final NotificationBroadcasterSupport nbs =
483.228 - new NotificationBroadcasterSupport();
483.229 -
483.230 - public StdBroadcaster() throws Exception {
483.231 - super(BroadcasterMBean.class);
483.232 - }
483.233 -
483.234 - public void send(Notification n) {
483.235 - nbs.sendNotification(n);
483.236 - }
483.237 -
483.238 - public void addNotificationListener(NotificationListener listener,
483.239 - NotificationFilter filter, Object handback) {
483.240 - nbs.addNotificationListener(listener, filter, handback);
483.241 - }
483.242 -
483.243 - public MBeanNotificationInfo[] getNotificationInfo() {
483.244 - return null;
483.245 - }
483.246 -
483.247 - public void removeNotificationListener(NotificationListener listener)
483.248 - throws ListenerNotFoundException {
483.249 - nbs.removeNotificationListener(listener);
483.250 - }
483.251 - }
483.252 -
483.253 - public static class StdSendNotif
483.254 - extends StandardMBean implements SendNotifMBean {
483.255 - @Resource
483.256 - private volatile SendNotification sendNotif;
483.257 -
483.258 - public StdSendNotif() throws Exception {
483.259 - super(SendNotifMBean.class);
483.260 - }
483.261 -
483.262 - public void send(Notification n) {
483.263 - sendNotif.sendNotification(n);
483.264 - }
483.265 - }
483.266 -
483.267 - public static class StdEmitterBroadcaster // :-)
483.268 - extends StandardEmitterMBean
483.269 - implements BroadcasterMBean {
483.270 -
483.271 - public StdEmitterBroadcaster() throws Exception {
483.272 - super(BroadcasterMBean.class, null);
483.273 - }
483.274 -
483.275 - public void send(Notification n) {
483.276 - super.sendNotification(n);
483.277 - }
483.278 - }
483.279 -
483.280 - // This case is unlikely - if you're using @Resource SendNotification
483.281 - // then there's no point in using StandardEmitterMBean, since
483.282 - // StandardMBean would suffice.
483.283 - public static class StdEmitterSendNotif
483.284 - extends StandardEmitterMBean implements SendNotifMBean {
483.285 - @Resource
483.286 - private volatile SendNotification sendNotif;
483.287 -
483.288 - public StdEmitterSendNotif() {
483.289 - super(SendNotifMBean.class, null);
483.290 - }
483.291 -
483.292 - public void send(Notification n) {
483.293 - sendNotif.sendNotification(n);
483.294 - }
483.295 - }
483.296 -
483.297 - // Test that JMX.isNotificationSource and
483.298 - // mbs.isInstanceOf("NotificationBroadcaster") work correctly even when
483.299 - // the MBean is a broadcaster by virtue of its wrapped resource.
483.300 - // Test that we find the MBeanNotificationInfo[] from the @NotificationInfo
483.301 - // annotation on BroadcasterMBean. We cover a large number of different
483.302 - // MBean types, but all ultimately implement that interface.
483.303 - private static void notifTest() throws Exception {
483.304 - System.out.println("===Testing notification senders===");
483.305 -
483.306 - for (WrapType wrapType : WrapType.values()) {
483.307 - System.out.println("---" + wrapType);
483.308 -
483.309 - final Object mbean;
483.310 -
483.311 - switch (wrapType) {
483.312 - case NBS:
483.313 - // An MBean that extends NotificationBroadcasterSupport
483.314 - mbean = new Broadcaster();
483.315 - break;
483.316 - case INJ:
483.317 - // An MBean that injects SendNotification
483.318 - mbean = new SendNotif();
483.319 - break;
483.320 - case STD_MBEAN_NBS:
483.321 - // A StandardMBean that delegates to a NotificationBroadcasterSupport
483.322 - mbean = new StandardMBean(
483.323 - new Broadcaster(), BroadcasterMBean.class, wrappedVisOpts);
483.324 - break;
483.325 - case STD_MBEAN_INJ:
483.326 - // A StandardMBean that delegates to an object that injects
483.327 - // SendNotification
483.328 - mbean = new StandardMBean(
483.329 - new SendNotif(), BroadcasterMBean.class, wrappedVisOpts);
483.330 - break;
483.331 - case STD_EMIT_MBEAN_NBS: {
483.332 - // A StandardEmitterMBean that delegates to a NotificationBroadcasterSupport
483.333 - Broadcaster broadcaster = new Broadcaster();
483.334 - mbean = new StandardEmitterMBean(
483.335 - broadcaster, BroadcasterMBean.class, wrappedVisOpts,
483.336 - broadcaster);
483.337 - break;
483.338 - }
483.339 - case STD_EMIT_MBEAN_INJ: {
483.340 - // A StandardEmitterMBean that delegates to an object that injects
483.341 - // SendNotification
483.342 - SendNotif sendNotif = new SendNotif();
483.343 - mbean = new StandardEmitterMBean(
483.344 - sendNotif, BroadcasterMBean.class, wrappedVisOpts,
483.345 - null);
483.346 - break;
483.347 - }
483.348 - case STD_MBEAN_SUB_NBS:
483.349 - // A subclass of StandardMBean that implements NotificationBroadcaster
483.350 - mbean = new StdBroadcaster();
483.351 - break;
483.352 - case STD_MBEAN_SUB_INJ:
483.353 - // A subclass of StandardMBean that injects SendNotification
483.354 - mbean = new StdSendNotif();
483.355 - break;
483.356 - case STD_EMIT_MBEAN_SUB:
483.357 - // A subclass of StandardEmitterMBean
483.358 - mbean = new StdEmitterBroadcaster();
483.359 - break;
483.360 - case STD_EMIT_MBEAN_SUB_INJ:
483.361 - // A subclass of StandardEmitterMBean that injects SendNotification
483.362 - // (which is a rather strange thing to do and probably a user
483.363 - // misunderstanding but we should do the right thing anyway).
483.364 - mbean = new StdEmitterSendNotif();
483.365 - break;
483.366 - default:
483.367 - throw new AssertionError();
483.368 - }
483.369 -
483.370 - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
483.371 -
483.372 - final ObjectName name = new ObjectName("a:type=Sender");
483.373 - mbs.registerMBean(mbean, name);
483.374 - boolean isBroadcaster = mbs.isInstanceOf(
483.375 - name, NotificationBroadcaster.class.getName());
483.376 - assertEquals("JMX.isNotificationSource(mbean)",
483.377 - true, JMX.isNotificationSource(mbean));
483.378 - assertEquals("isInstanceOf(NotificationBroadcaster)",
483.379 - true, isBroadcaster);
483.380 - MBeanNotificationInfo[] mbnis =
483.381 - mbs.getMBeanInfo(name).getNotifications();
483.382 - assertEquals("MBeanNotificationInfo not empty",
483.383 - true, (mbnis.length > 0));
483.384 -
483.385 - mbs.unregisterMBean(name);
483.386 - }
483.387 - }
483.388 -
483.389 - private static void assertEquals(String what, Object expect, Object actual) {
483.390 - if (equal(expect, actual))
483.391 - System.out.println("OK: " + what + " = " + expect);
483.392 - else
483.393 - fail(what + " should be " + expect + ", is " + actual);
483.394 - }
483.395 -
483.396 - private static boolean equal(Object x, Object y) {
483.397 - if (x == y)
483.398 - return true;
483.399 - if (x == null || y == null)
483.400 - return false;
483.401 - return x.equals(y);
483.402 - }
483.403 -
483.404 - private static void fail(String why) {
483.405 - failure = why;
483.406 - System.out.println("FAIL: " + why);
483.407 - }
483.408 -}
484.1 --- a/test/javax/management/MBeanServer/InstanceNotFoundExceptionTest.java Mon Nov 23 10:04:47 2009 +0000
484.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
484.3 @@ -1,76 +0,0 @@
484.4 -/*
484.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
484.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
484.7 - *
484.8 - * This code is free software; you can redistribute it and/or modify it
484.9 - * under the terms of the GNU General Public License version 2 only, as
484.10 - * published by the Free Software Foundation.
484.11 - *
484.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
484.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
484.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
484.15 - * version 2 for more details (a copy is included in the LICENSE file that
484.16 - * accompanied this code).
484.17 - *
484.18 - * You should have received a copy of the GNU General Public License version
484.19 - * 2 along with this work; if not, write to the Free Software Foundation,
484.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
484.21 - *
484.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
484.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
484.24 - * have any questions.
484.25 - */
484.26 -
484.27 -/*
484.28 - * @test
484.29 - * @bug 6669137
484.30 - * @summary Test the constructors of InstanceNotFoundExceptionTest.
484.31 - * @author Daniel Fuchs
484.32 - * @compile InstanceNotFoundExceptionTest.java
484.33 - * @run main InstanceNotFoundExceptionTest
484.34 - */
484.35 -
484.36 -import javax.management.InstanceNotFoundException;
484.37 -import javax.management.ObjectName;
484.38 -
484.39 -public class InstanceNotFoundExceptionTest {
484.40 - public static void main(String[] args) throws Exception {
484.41 - final InstanceNotFoundException x =
484.42 - new InstanceNotFoundException();
484.43 - System.out.println("InstanceNotFoundException(): "+x.getMessage());
484.44 -
484.45 - final String msg = "who is toto?";
484.46 - final InstanceNotFoundException x2 =
484.47 - new InstanceNotFoundException(msg);
484.48 - if (!msg.equals(x2.getMessage()))
484.49 - throw new Exception("Bad message: expected "+msg+
484.50 - ", got "+x2.getMessage());
484.51 - System.out.println("InstanceNotFoundException(" +
484.52 - msg+"): "+x2.getMessage());
484.53 -
484.54 - final InstanceNotFoundException x3 =
484.55 - new InstanceNotFoundException((String)null);
484.56 - if (x3.getMessage() != null)
484.57 - throw new Exception("Bad message: expected "+null+
484.58 - ", got "+x3.getMessage());
484.59 - System.out.println("InstanceNotFoundException((String)null): "+
484.60 - x3.getMessage());
484.61 -
484.62 - final ObjectName n = new ObjectName("who is toto?:type=msg");
484.63 - final InstanceNotFoundException x4 =
484.64 - new InstanceNotFoundException(n);
484.65 - if (!String.valueOf(n).equals(x4.getMessage()))
484.66 - throw new Exception("Bad message: expected "+n+
484.67 - ", got "+x4.getMessage());
484.68 - System.out.println("InstanceNotFoundException(" +
484.69 - n+"): "+x4.getMessage());
484.70 -
484.71 - final InstanceNotFoundException x5 =
484.72 - new InstanceNotFoundException((ObjectName)null);
484.73 - if (!String.valueOf((ObjectName)null).equals(x5.getMessage()))
484.74 - throw new Exception("Bad message: expected " +
484.75 - String.valueOf((ObjectName)null)+" got "+x5.getMessage());
484.76 - System.out.println("InstanceNotFoundException((ObjectName)null): "+
484.77 - x5.getMessage());
484.78 - }
484.79 -}
485.1 --- a/test/javax/management/MBeanServer/MBeanExceptionTest.java Mon Nov 23 10:04:47 2009 +0000
485.2 +++ b/test/javax/management/MBeanServer/MBeanExceptionTest.java Wed Nov 25 11:08:25 2009 -0800
485.3 @@ -34,8 +34,16 @@
485.4
485.5 import java.util.Collections;
485.6 import java.util.Set;
485.7 -import javax.management.*;
485.8 -import javax.management.namespace.MBeanServerSupport;
485.9 +import javax.management.Attribute;
485.10 +import javax.management.AttributeList;
485.11 +import javax.management.DynamicMBean;
485.12 +import javax.management.MBeanException;
485.13 +import javax.management.MBeanInfo;
485.14 +import javax.management.MBeanServer;
485.15 +import javax.management.MBeanServerFactory;
485.16 +import javax.management.ObjectName;
485.17 +import javax.management.RuntimeMBeanException;
485.18 +import javax.management.StandardMBean;
485.19
485.20 public class MBeanExceptionTest {
485.21 public static void main(String[] args) throws Exception {
485.22 @@ -62,46 +70,41 @@
485.23
485.24 final boolean[] booleans = {false, true};
485.25
485.26 - for (boolean mbss : booleans) {
485.27 - for (boolean runtimeX : booleans) {
485.28 - Class<? extends Exception> excC =
485.29 - runtimeX ? RuntimeMBeanException.class : MBeanException.class;
485.30 - String excS =
485.31 - runtimeX ? "a RuntimeMBeanException" : "an MBeanException";
485.32 - String mbsS =
485.33 - mbss ? "a conformant MBeanServerSupport" : "a plain MBeanServer";
485.34 - MBeanServer xmbs =
485.35 - mbss ? new CreateExceptionMBS() : mbs;
485.36 + for (boolean runtimeX : booleans) {
485.37 + Class<? extends Exception> excC =
485.38 + runtimeX ? RuntimeMBeanException.class : MBeanException.class;
485.39 + String excS =
485.40 + runtimeX ? "a RuntimeMBeanException" : "an MBeanException";
485.41 + String mbsS = "a plain MBeanServer";
485.42 + System.out.println(
485.43 + "Test that, with " + mbsS + ", " + excS + " is wrapped " +
485.44 + "in " + excS);
485.45 + // E.g. "Test that, with a plain MBeanServer, an MBeanException
485.46 + // is wrapped in an MBeanException".
485.47 + try {
485.48 + mbs.createMBean(
485.49 + Except.class.getName(), new ObjectName(":name=Oops"),
485.50 + new Object[] {runtimeX},
485.51 + new String[] {boolean.class.getName()});
485.52 System.out.println(
485.53 - "Test that, with " + mbsS + ", " + excS + " is wrapped " +
485.54 - "in " + excS);
485.55 - // E.g. "Test that, with a plain MBeanServer, an MBeanException
485.56 - // is wrapped in an MBeanException".
485.57 - try {
485.58 - mbs.createMBean(
485.59 - Except.class.getName(), new ObjectName(":name=Oops"),
485.60 - new Object[] {runtimeX},
485.61 - new String[] {boolean.class.getName()});
485.62 + "FAIL: createMBean succeeded but should not have");
485.63 + failures++;
485.64 + } catch (Exception e) {
485.65 + if (!excC.isInstance(e)) {
485.66 System.out.println(
485.67 - "FAIL: createMBean succeeded but should not have");
485.68 + "FAIL: expected " + excC.getName() + " from " +
485.69 + "createMBean, got " + e);
485.70 failures++;
485.71 - } catch (Exception e) {
485.72 - if (!excC.isInstance(e)) {
485.73 + } else {
485.74 + Throwable cause = e.getCause();
485.75 + if (!excC.isInstance(cause)) {
485.76 System.out.println(
485.77 - "FAIL: expected " + excC.getName() + " from " +
485.78 - "createMBean, got " + e);
485.79 + "FAIL: expected " + excC.getName() +
485.80 + " as cause of " + excC.getName() +
485.81 + ", got " + e);
485.82 failures++;
485.83 - } else {
485.84 - Throwable cause = e.getCause();
485.85 - if (!excC.isInstance(cause)) {
485.86 - System.out.println(
485.87 - "FAIL: expected " + excC.getName() +
485.88 - " as cause of " + excC.getName() +
485.89 - ", got " + e);
485.90 - failures++;
485.91 - } else
485.92 - System.out.println("...ok");
485.93 - }
485.94 + } else
485.95 + System.out.println("...ok");
485.96 }
485.97 }
485.98 }
485.99 @@ -280,28 +283,4 @@
485.100 private static final RuntimeException theUncheckedException =
485.101 new UnsupportedOperationException("The unchecked exception " +
485.102 "that should be seen");
485.103 -
485.104 - private static class CreateExceptionMBS extends MBeanServerSupport {
485.105 - @Override
485.106 - protected Set<ObjectName> getNames() {
485.107 - return Collections.emptySet();
485.108 - }
485.109 -
485.110 - @Override
485.111 - public DynamicMBean getDynamicMBeanFor(ObjectName name)
485.112 - throws InstanceNotFoundException {
485.113 - throw new InstanceNotFoundException(name);
485.114 - }
485.115 -
485.116 - @Override
485.117 - public ObjectInstance createMBean(String className,
485.118 - ObjectName name, ObjectName loaderName, Object[] params,
485.119 - String[] signature, boolean useCLR)
485.120 - throws ReflectionException, InstanceAlreadyExistsException,
485.121 - MBeanRegistrationException, MBeanException,
485.122 - NotCompliantMBeanException, InstanceNotFoundException {
485.123 - Exception wrapped = new MBeanException(new Exception(), "Bang");
485.124 - throw new MBeanException(wrapped, "Bang");
485.125 - }
485.126 - }
485.127 }
486.1 --- a/test/javax/management/MBeanServerFactory/NamedMBeanServerTest.java Mon Nov 23 10:04:47 2009 +0000
486.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
486.3 @@ -1,441 +0,0 @@
486.4 -/*
486.5 - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
486.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
486.7 - *
486.8 - * This code is free software; you can redistribute it and/or modify it
486.9 - * under the terms of the GNU General Public License version 2 only, as
486.10 - * published by the Free Software Foundation.
486.11 - *
486.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
486.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
486.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
486.15 - * version 2 for more details (a copy is included in the LICENSE file that
486.16 - * accompanied this code).
486.17 - *
486.18 - * You should have received a copy of the GNU General Public License version
486.19 - * 2 along with this work; if not, write to the Free Software Foundation,
486.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
486.21 - *
486.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
486.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
486.24 - * have any questions.
486.25 - */
486.26 -
486.27 -/*
486.28 - * @test
486.29 - * @summary Test named MBeanServers.
486.30 - * @author Daniel Fuchs
486.31 - * @bug 6299231
486.32 - * @run clean NamedMBeanServerTest
486.33 - * @run build NamedMBeanServerTest
486.34 - * @run main NamedMBeanServerTest
486.35 - */
486.36 -
486.37 -import java.util.Arrays;
486.38 -import java.util.EnumSet;
486.39 -import java.util.HashMap;
486.40 -import java.util.HashSet;
486.41 -import java.util.LinkedHashMap;
486.42 -import java.util.List;
486.43 -import java.util.Map;
486.44 -import java.util.Set;
486.45 -import javax.management.MBeanServer;
486.46 -import javax.management.MBeanServerBuilder;
486.47 -import javax.management.MBeanServerDelegate;
486.48 -import javax.management.MBeanServerFactory;
486.49 -
486.50 -/**
486.51 - * This test can probably be leveraged in the JCK to test compatibilty
486.52 - * of MBeanServerFactory *Name* method implementation.
486.53 - * @author dfuchs
486.54 - */
486.55 -public class NamedMBeanServerTest {
486.56 -
486.57 - /**
486.58 - * One enum value for each way of creating an MBeanServer through the
486.59 - * MBeanServerFactory
486.60 - */
486.61 - public static enum Creator {
486.62 - newMBeanServer() {
486.63 - public MBeanServer create(String domain) {
486.64 - return MBeanServerFactory.newMBeanServer(domain);
486.65 - }
486.66 - public String test(MBeanServer server, String domain) {
486.67 - System.out.println(toString()+"("+domain+")");
486.68 - return test(server,
486.69 - MBeanServerFactory.DEFAULT_MBEANSERVER_NAME,
486.70 - domain);
486.71 - }
486.72 - public MBeanServer[] servers(Config config) {
486.73 - return config.ndServers;
486.74 - }
486.75 - public String[] strings(Config config) {
486.76 - return domains(config);
486.77 - }
486.78 - public String[] domains(Config config) {
486.79 - return config.newDomains;
486.80 - }
486.81 - public String[] names(Config config) {
486.82 - return null;
486.83 - }
486.84 - },
486.85 - createMBeanServer() {
486.86 - public MBeanServer create(String domain) {
486.87 - return MBeanServerFactory.createMBeanServer(domain);
486.88 - }
486.89 - public String test(MBeanServer server, String domain) {
486.90 - System.out.println(toString()+"("+domain+")");
486.91 - return test(server,MBeanServerFactory.DEFAULT_MBEANSERVER_NAME,
486.92 - domain);
486.93 - }
486.94 - public MBeanServer[] servers(Config config) {
486.95 - return config.cdServers;
486.96 - }
486.97 - public String[] strings(Config config) {
486.98 - return domains(config);
486.99 - }
486.100 - public String[] domains(Config config) {
486.101 - return config.createDomains;
486.102 - }
486.103 - public String[] names(Config config) {
486.104 - return null;
486.105 - }
486.106 - },
486.107 - newNamedMBeanServer() {
486.108 - public MBeanServer create(String name) {
486.109 - return MBeanServerFactory.newNamedMBeanServer(name,null);
486.110 - }
486.111 - public String test(MBeanServer server, String name) {
486.112 - System.out.println(toString()+"("+name+",null)");
486.113 - return test(server,name,"DefaultDomain");
486.114 - }
486.115 - public MBeanServer[] servers(Config config) {
486.116 - return config.nnServers;
486.117 - }
486.118 - public String[] strings(Config config) {
486.119 - return names(config);
486.120 - }
486.121 - public String[] domains(Config config) {
486.122 - return null;
486.123 - }
486.124 - public String[] names(Config config) {
486.125 - return config.newNames;
486.126 - }
486.127 - },
486.128 - createNamedMBeanServer() {
486.129 - public MBeanServer create(String name) {
486.130 - return MBeanServerFactory.createNamedMBeanServer(name,null);
486.131 - }
486.132 - public String test(MBeanServer server, String name) {
486.133 - System.out.println(toString()+"("+name+",null)");
486.134 - return test(server,name,"DefaultDomain");
486.135 - }
486.136 - public MBeanServer[] servers(Config config) {
486.137 - return config.cnServers;
486.138 - }
486.139 - public String[] strings(Config config) {
486.140 - return names(config);
486.141 - }
486.142 - public String[] domains(Config config) {
486.143 - return null;
486.144 - }
486.145 - public String[] names(Config config) {
486.146 - return config.createNames;
486.147 - }
486.148 - };
486.149 -
486.150 - // creates an MBeanServer using the specified input string.
486.151 - // either a domain, (for UNNAMED) or a mbeanServerName (for NAMED)
486.152 - public abstract MBeanServer create(String string);
486.153 -
486.154 - // test the created server against the string used as input to create
486.155 - // it.
486.156 - public abstract String test(MBeanServer server, String ref);
486.157 -
486.158 - public abstract MBeanServer[] servers(Config config);
486.159 - public abstract String[] strings(Config config);
486.160 - public abstract String[] names(Config config);
486.161 - public abstract String[] domains(Config config);
486.162 -
486.163 - public MBeanServer[] servers(Config config, String... refs) {
486.164 - final MBeanServer[] servers = servers(config);
486.165 - final String[] strings = strings(config);
486.166 - final MBeanServer[] res = new MBeanServer[refs.length];
486.167 - for (int i=0;i<refs.length;i++) {
486.168 - for (int j=0;j<strings.length;j++) {
486.169 - if (strings[j].equals(refs[i]))
486.170 - res[i]=servers[j];
486.171 - }
486.172 - if (res[i] == null)
486.173 - throw new IllegalArgumentException(refs[i]);
486.174 - }
486.175 - return res;
486.176 - }
486.177 -
486.178 - String test(MBeanServer server, String name, String domain) {
486.179 - // whether the MBeanServer was created throug a "create" method
486.180 - boolean registered = REFERENCED.contains(this);
486.181 - if (!server.getDefaultDomain().equals(domain)) {
486.182 - return "Unexpected default domain: " +
486.183 - server.getDefaultDomain() + ", should be: " + domain;
486.184 - }
486.185 - if (!MBeanServerFactory.getMBeanServerName(server).
486.186 - equals(name)) {
486.187 - return " Unexpected name: " +
486.188 - MBeanServerFactory.getMBeanServerName(server) +
486.189 - ", should be: " + name;
486.190 - }
486.191 - List<MBeanServer> found =
486.192 - MBeanServerFactory.findMBeanServerByName(name);
486.193 - if (!registered && found.contains(server))
486.194 - return " Server "+name+" found by name - " +
486.195 - "but should not be registered";
486.196 - if (!registered &&
486.197 - !name.equals(MBeanServerFactory.DEFAULT_MBEANSERVER_NAME) &&
486.198 - found.size()>0)
486.199 - return " Server "+name+" had too many matches: " + found.size();
486.200 - if (registered && !found.contains(server))
486.201 - return " Server "+name+" not found by name - " +
486.202 - "but is registered!";
486.203 - if (registered &&
486.204 - !name.equals(MBeanServerFactory.DEFAULT_MBEANSERVER_NAME) &&
486.205 - !(found.size()==1))
486.206 - return " Server "+name+" had too many matches: " + found.size();
486.207 - return null;
486.208 - }
486.209 -
486.210 - public static final EnumSet<Creator> NAMED =
486.211 - EnumSet.of(createNamedMBeanServer, newNamedMBeanServer);
486.212 - public static final EnumSet<Creator> UNNAMED =
486.213 - EnumSet.complementOf(NAMED);
486.214 - public static final EnumSet<Creator> REFERENCED =
486.215 - EnumSet.of(createMBeanServer, createNamedMBeanServer);
486.216 - public static final EnumSet<Creator> UNREFERENCED =
486.217 - EnumSet.complementOf(REFERENCED);
486.218 -
486.219 - }
486.220 -
486.221 - public static class Config {
486.222 - final String[] newDomains;
486.223 - final String[] createDomains;
486.224 - final String[] newNames;
486.225 - final String[] createNames;
486.226 - final MBeanServer[] ndServers;
486.227 - final MBeanServer[] cdServers;
486.228 - final MBeanServer[] nnServers;
486.229 - final MBeanServer[] cnServers;
486.230 - final Map<String,Set<MBeanServer>> queries;
486.231 - Config(String[][] data) {
486.232 - this(data[0],data[1],data[2],data[3]);
486.233 - }
486.234 - Config(String[] nd, String[] cd, String[] nn, String[] cn) {
486.235 - this.newDomains=nd.clone();
486.236 - this.createDomains=cd.clone();
486.237 - this.newNames=nn.clone();
486.238 - this.createNames=cn.clone();
486.239 - ndServers = new MBeanServer[nd.length];
486.240 - cdServers = new MBeanServer[cd.length];
486.241 - nnServers = new MBeanServer[nn.length];
486.242 - cnServers = new MBeanServer[cn.length];
486.243 - queries = new HashMap<String,Set<MBeanServer>>();
486.244 - init();
486.245 - }
486.246 - private void init() {
486.247 - for (Creator c : Creator.values()) fill(c);
486.248 - addQuery(null,Creator.createMBeanServer.servers(this));
486.249 - addQuery(null,Creator.createNamedMBeanServer.servers(this));
486.250 - addQuery("?*",Creator.createMBeanServer.servers(this));
486.251 - addQuery("?*",Creator.createNamedMBeanServer.servers(this));
486.252 - addQuery("*",Creator.createMBeanServer.servers(this));
486.253 - addQuery("*",Creator.createNamedMBeanServer.servers(this));
486.254 - addQuery(MBeanServerFactory.DEFAULT_MBEANSERVER_NAME,
486.255 - Creator.createMBeanServer.servers(this));
486.256 - }
486.257 - private void addQuery(String pattern, MBeanServer... servers) {
486.258 - final Set<MBeanServer> s = getQuery(pattern);
486.259 - s.addAll(Arrays.asList(servers));
486.260 - }
486.261 - public Set<MBeanServer> getQuery(String pattern) {
486.262 - final Set<MBeanServer> s = queries.get(pattern);
486.263 - if (s != null) return s;
486.264 - queries.put(pattern,new HashSet<MBeanServer>());
486.265 - return queries.get(pattern);
486.266 - }
486.267 - public Set<String> getPatterns() {
486.268 - return queries.keySet();
486.269 - }
486.270 - private void fill(Creator creator) {
486.271 - fill(creator.servers(this),creator.strings(this),creator);
486.272 - }
486.273 - private void fill(MBeanServer[] dest, String[] src, Creator creator) {
486.274 - for(int i=0;i<src.length;i++) dest[i]=creator.create(src[i]);
486.275 - }
486.276 -
486.277 - }
486.278 -
486.279 - static String[] domains(String... str) {
486.280 - return str;
486.281 - }
486.282 - static String[] names(String... str) {
486.283 - return str;
486.284 - }
486.285 - final static Config test1 = new Config(domains("foo1","foo2","foo3"),
486.286 - domains("foobar1","foobar2","foobar3","foobar4"),
486.287 - names("bar1","bar2"),
486.288 - names("barfoo1","barfoo2","barfoo3","batfox1","catfog2","foofoo3"));
486.289 - static {
486.290 - test1.addQuery("b*",Creator.createNamedMBeanServer.servers(test1,
486.291 - "barfoo1","barfoo2","barfoo3","batfox1"));
486.292 - test1.addQuery("*arf*",Creator.createNamedMBeanServer.servers(test1,
486.293 - "barfoo1","barfoo2","barfoo3"));
486.294 - test1.addQuery("*a?f*",Creator.createNamedMBeanServer.servers(test1,
486.295 - "barfoo1","barfoo2","barfoo3","batfox1","catfog2"));
486.296 - test1.addQuery("",new MBeanServer[0]);
486.297 - test1.addQuery("-",new MBeanServer[0]);
486.298 - test1.addQuery("def*",Creator.createMBeanServer.servers(test1));
486.299 - }
486.300 -
486.301 - public static void test(Config config) throws Exception {
486.302 - for (Creator c : Creator.values()) {
486.303 - final MBeanServer[] s = c.servers(config);
486.304 - final String[] ref = c.strings(config);
486.305 - for (int i=0;i<s.length;i++) {
486.306 - final String msg = c.test(s[i], ref[i]);
486.307 - if (msg != null)
486.308 - throw new Exception(String.valueOf(c)+"["+i+"]: "+msg);
486.309 - }
486.310 - }
486.311 - for (String pat : config.getPatterns()) {
486.312 - System.out.print("findMBeanServerByName(\""+pat+"\"): [");
486.313 - final List<MBeanServer> found =
486.314 - MBeanServerFactory.findMBeanServerByName(pat);
486.315 - String sep=" ";
486.316 - for (MBeanServer m : found) {
486.317 - System.out.print(sep+MBeanServerFactory.getMBeanServerName(m));
486.318 - sep=", ";
486.319 - }
486.320 - System.out.println(" ]");
486.321 - final Set<MBeanServer> founds = new HashSet<MBeanServer>();
486.322 - founds.addAll(found);
486.323 - if (!founds.equals(config.getQuery(pat))) {
486.324 - final String msg =
486.325 - "bad result for findMBeanServerByName(\""+
486.326 - pat+"\"): expected "+config.getQuery(pat).size()+", "+
486.327 - "got "+founds.size();
486.328 - throw new Exception(msg);
486.329 - }
486.330 - }
486.331 - }
486.332 -
486.333 - public static void testexception(Creator c, String name,
486.334 - Class<? extends Exception> error) throws Exception {
486.335 - Exception failed = null;
486.336 - MBeanServer server = null;
486.337 - try {
486.338 - server = c.create(name);
486.339 - } catch (Exception x) {
486.340 - failed = x;
486.341 - } finally {
486.342 - if (Creator.REFERENCED.contains(c) && server!=null) {
486.343 - MBeanServerFactory.releaseMBeanServer(server);
486.344 - }
486.345 - }
486.346 - if (failed == null && error != null) {
486.347 - throw new Exception("Expected "+error.getName()+
486.348 - " for "+c+"("+name+")");
486.349 - }
486.350 - if (error != null && !error.isInstance(failed))
486.351 - throw new Exception("Expected "+error.getName()+
486.352 - " for "+c+"("+name+"), caught "+failed);
486.353 - System.out.println(""+c+"("+name+") PASSED: "+
486.354 - (failed==null?"no exception":String.valueOf(failed)));
486.355 - }
486.356 -
486.357 - private static final Map<String,Class<? extends Exception>> failures =
486.358 - new LinkedHashMap<String,Class<? extends Exception>>();
486.359 - private static final Map<String,Class<? extends Exception>> legacy =
486.360 - new LinkedHashMap<String,Class<? extends Exception>>();
486.361 - private static final String[] illegalnames = {
486.362 - "", "-", ":", ";", "?", "*", "wom?bat", "ran:tan.plan",
486.363 - "rin;tin.tin", "tab*mow"
486.364 -
486.365 - };
486.366 - private static final String[] legalnames = {
486.367 - "wombat", "top.tip", "ran.tan.plan", "rin.tin.tin!"
486.368 - };
486.369 - private static final String[] nofailures = {
486.370 - MBeanServerFactory.DEFAULT_MBEANSERVER_NAME, "default", null
486.371 - };
486.372 - static {
486.373 - for (String s:illegalnames)
486.374 - failures.put(s, IllegalArgumentException.class);
486.375 - for (String s:nofailures)
486.376 - failures.put(s, null);
486.377 - legacy.putAll(failures);
486.378 - for (String s:legalnames)
486.379 - legacy.put(s, UnsupportedOperationException.class);
486.380 -
486.381 - }
486.382 -
486.383 - public static void test2(Map<String,Class<? extends Exception>> config)
486.384 - throws Exception {
486.385 - for (Creator c:Creator.NAMED) {
486.386 - for (String s:config.keySet()) testexception(c, s, config.get(s));
486.387 - }
486.388 - }
486.389 -
486.390 - public static class LegacyBuilder extends MBeanServerBuilder {
486.391 -
486.392 - @Override
486.393 - public MBeanServerDelegate newMBeanServerDelegate() {
486.394 - return new MBeanServerDelegate() {
486.395 - @Override
486.396 - public synchronized String getMBeanServerId() {
486.397 - return "gloups";
486.398 - }
486.399 - };
486.400 - }
486.401 -
486.402 - }
486.403 - public static class LegacyBuilder2 extends MBeanServerBuilder {
486.404 -
486.405 - @Override
486.406 - public MBeanServerDelegate newMBeanServerDelegate() {
486.407 - return new MBeanServerDelegate() {
486.408 - @Override
486.409 - public synchronized String getMBeanServerId() {
486.410 - return "c'est la vie...";
486.411 - }
486.412 - @Override
486.413 - public synchronized void setMBeanServerName(String name) {
486.414 - }
486.415 -
486.416 - };
486.417 - }
486.418 -
486.419 - }
486.420 -
486.421 - public static void test3(Map<String,Class<? extends Exception>> config,
486.422 - String builderClassName)
486.423 - throws Exception {
486.424 - final String builder =
486.425 - System.getProperty("javax.management.builder.initial");
486.426 - System.setProperty("javax.management.builder.initial",
486.427 - builderClassName);
486.428 - try {
486.429 - test2(config);
486.430 - } finally {
486.431 - if (builder != null)
486.432 - System.setProperty("javax.management.builder.initial", builder);
486.433 - else
486.434 - System.clearProperty("javax.management.builder.initial");
486.435 - }
486.436 - }
486.437 -
486.438 - public static void main(String[] args) throws Exception {
486.439 - test(test1);
486.440 - test2(failures);
486.441 - test3(legacy,LegacyBuilder.class.getName());
486.442 - test3(legacy,LegacyBuilder2.class.getName());
486.443 - }
486.444 -}
487.1 --- a/test/javax/management/ObjectName/ApplyWildcardTest.java Mon Nov 23 10:04:47 2009 +0000
487.2 +++ b/test/javax/management/ObjectName/ApplyWildcardTest.java Wed Nov 25 11:08:25 2009 -0800
487.3 @@ -1,5 +1,5 @@
487.4 /*
487.5 - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
487.6 + * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
487.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
487.8 *
487.9 * This code is free software; you can redistribute it and/or modify it
487.10 @@ -28,13 +28,10 @@
487.11 * with wildcards in the key properties value part.
487.12 * @author Luis-Miguel Alventosa
487.13 * @run clean ApplyWildcardTest
487.14 - * @compile -XDignore.symbol.file=true ApplyWildcardTest.java
487.15 * @run build ApplyWildcardTest
487.16 * @run main ApplyWildcardTest
487.17 */
487.18
487.19 -import com.sun.jmx.mbeanserver.Repository;
487.20 -import com.sun.jmx.mbeanserver.Util;
487.21 import javax.management.ObjectName;
487.22
487.23 public class ApplyWildcardTest {
487.24 @@ -77,75 +74,6 @@
487.25 { "d:k1=\"a?b\",k2=\"c*d\"", "d:k1=\"axb\",k2=\"cyzd\"" },
487.26 { "d:k1=\"a?b\",k2=\"c*d\",*", "d:k1=\"axb\",k2=\"cyzd\",k3=\"v3\"" },
487.27 { "d:*,k1=\"a?b\",k2=\"c*d\"", "d:k1=\"axb\",k2=\"cyzd\",k3=\"v3\"" },
487.28 -
487.29 - // with namespaces
487.30 -
487.31 - { "*//:*", "d//:k=v" },
487.32 - { "//?:*", "///:k=v" },
487.33 - { "z*x//:*", "zaxcx//:k=v" },
487.34 - { "*//:*", "d/xx/q//:k=v" },
487.35 - { "z*x//:*", "z/a/x/c/x//:k=v" },
487.36 - { "*x?//:*", "dbdbdxk//:k=v" },
487.37 - { "z*x?x//:*", "zaxcx//:k=v" },
487.38 - { "*x?f//:*", "d/xxf/qxbf//:k=v" },
487.39 - { "z*x?c*x//:*", "z/a/x/c/x//:k=v" },
487.40 -
487.41 - { "*//*:*", "d/c/v//x/vgh/:k=v" },
487.42 - { "z*x//z*x:*", "zaxcx//zaxcxcx:k=v" },
487.43 - { "//*//:*", "//d/xx/q//:k=v" },
487.44 - { "z*//*//:*", "z/x/x/z//z/a/x/c/x//:k=v" },
487.45 - { "*x?//blur?g*:*", "dbdbdxk//blurhgblurgh/x/:k=v" },
487.46 - { "z*x??x//??:*", "zaxcxccx///.:k=v" },
487.47 - { "*x?f//?:*", "d/xxf/qxbf///:k=v" },
487.48 - { "z*x?c*x//*//z????//g:*", "z/a/x/c/x//gloubs/././/zargh//g:k=v" },
487.49 - { "z*x?c*x//*//:*", "z/a/x/c/x//gloubs/././/:k=v"},
487.50 - { "*//*//:*", "aza//bzb//:k=v" },
487.51 - { "*//:*", "aza//:k=v" },
487.52 -
487.53 - // with or without namespaces, * can also match nothing
487.54 - { "x*z:*", "xz:k=v"},
487.55 -
487.56 - { "*//:*", "//:k=v" },
487.57 - { "z*x//:*", "zx//:k=v" },
487.58 - { "*x?//:*", "xk//:k=v" },
487.59 - { "z*x?x//:*", "zxcx//:k=v" },
487.60 - { "*x?f//:*", "xbf//:k=v" },
487.61 - { "z*x?c*x//:*", "zx/cx//:k=v" },
487.62 -
487.63 - { "*//*:*", "//:k=v" },
487.64 - { "z*x//z*x:*", "zx//zx:k=v" },
487.65 - { "//*//:*", "////:k=v" },
487.66 - { "z*//*//:*", "z////:k=v" },
487.67 - { "*x?//blur?g*:*", "xk//blurhg:k=v" },
487.68 - { "z*x??x//??:*", "zxccx///.:k=v" },
487.69 - { "*x?f//?:*", "xbf///:k=v" },
487.70 - { "z*x?c*x//*//z????//g:*", "zx/cx////zargh//g:k=v" },
487.71 - { "z*x?c*x//*//:*", "zx/cx////:k=v"},
487.72 - { "*//*//:*", "////:k=v" },
487.73 - { "*//:*", "//:k=v" },
487.74 -
487.75 - // recursive namespace meta-wildcard
487.76 - {"**//D:k=v", "a//D:k=v"},
487.77 - {"**//D:k=v", "a//b//c//D:k=v"},
487.78 - {"a//**//D:k=v", "a//b//c//D:k=v"},
487.79 - {"a//**//d//D:k=v", "a//b//c//d//D:k=v"},
487.80 - {"a//**//d//D:k=v", "a//b//c//d//d//D:k=v"},
487.81 - {"a//**//d//D:k=v", "a//a//b//c//d//d//D:k=v"},
487.82 - {"a//**//d//**//e//D:k=v", "a//a//b//d//c//d//e//D:k=v"},
487.83 -
487.84 - // special cases for names ending with //
487.85 - { "*:*", "d//:k=v" },
487.86 - { "z*x*:*", "zaxcx//:k=v" },
487.87 - { "*:*", "d/xx/q//:k=v" },
487.88 - { "z*x??:*", "z/a/x/c/x//:k=v" },
487.89 - { "*x???:*", "dbdbdxk//:k=v" },
487.90 - { "z*x?c*x*:*", "z/a/x/c/x//:k=v" },
487.91 - { "?/*/?:*", "d/xx/q//:k=v" },
487.92 - { "**//*:*", "a//b//jmx.rmi:k=v"},
487.93 - { "**//*:*", "a//b//jmx.rmi//:k=v"},
487.94 - { "*//*:*", "wombat//:type=Wombat" },
487.95 - { "**//*:*", "jmx.rmi//:k=v"},
487.96 -
487.97 };
487.98
487.99 private static final String negativeTests[][] = {
487.100 @@ -186,33 +114,6 @@
487.101 { "d:k1=\"a?b\",k2=\"c*d\"", "d:k1=\"ab\",k2=\"cd\"" },
487.102 { "d:k1=\"a?b\",k2=\"c*d\",*", "d:k1=\"ab\",k2=\"cd\",k3=\"v3\"" },
487.103 { "d:*,k1=\"a?b\",k2=\"c*d\"", "d:k1=\"ab\",k2=\"cd\",k3=\"v3\"" },
487.104 -
487.105 - // with namespaces
487.106 -
487.107 - { "z*x?x*:*", "zaxcx//blougs:k=v" },
487.108 - { "*x?f??rata:*", "d/xxf/qxbf//rata:k=v" },
487.109 - { "z*x?c*x*b*:*", "z/a/x/c/x//b//:k=v" },
487.110 -
487.111 - { "*:*", "d/c/v//x/vgh/:k=v" },
487.112 - { "z*x??z*x:*", "zaxcx//zaxcxcx:k=v" },
487.113 - { "?/*/?:*", "//d/xx/q//:k=v" },
487.114 - { "z*/?*/?:*", "z/x/x/z//z/a/x/c/x//:k=v" },
487.115 - { "*x?/?blur?g*:*", "dbdbdxk//blurhgblurgh/x/:k=v" },
487.116 - { "z*x??x/???:*", "zaxcxccx///.:k=v" },
487.117 - { "*x?f?/?:*", "d/xxf/qxbf///:k=v" },
487.118 - { "z*x?c*x/?*z????*g:*", "z/a/x/c/x//gloubs/././/zargh//g:k=v" },
487.119 -
487.120 - // recursive namespace meta-wildcard
487.121 - {"**//D:k=v", "D:k=v"},
487.122 - {"b//**//D:k=v", "a//b//c//D:k=v"},
487.123 - {"a//**//D:k=v", "a//D:k=v"},
487.124 - {"a//**//d//D:k=v", "a//b//c//d//e//D:k=v"},
487.125 - {"a//**//d//D:k=v", "a//b//c//D:k=v"},
487.126 - {"a//**//d//D:k=v", "a//b//c//d//d//e//D:k=v"},
487.127 - {"a//**//d//**//e//D:k=v", "a//a//b//c//d//e//D:k=v"},
487.128 - {"a//**//d//**//e//D:k=v", "a//a//b//c//e//D:k=v"},
487.129 - { "**//*:*", "jmx.rmi:k=v"},
487.130 -
487.131 };
487.132
487.133 private static int runPositiveTests() {
487.134 @@ -228,8 +129,6 @@
487.135 if (result == false) {
487.136 error++;
487.137 System.out.println("Test failed!");
487.138 - throw new Error("test failed for "+
487.139 - "\"" + on1 + "\".apply(\"" + on2 + "\")");
487.140 } else {
487.141 System.out.println("Test passed!");
487.142 }
487.143 @@ -269,85 +168,10 @@
487.144 return error;
487.145 }
487.146
487.147 - private static int runRepositoryPositiveTests() {
487.148 - int error = 0;
487.149 - for (int i = 0; i < positiveTests.length; i++) {
487.150 - try {
487.151 - ObjectName on1 = ObjectName.getInstance(positiveTests[i][0]);
487.152 - ObjectName on2 = ObjectName.getInstance(positiveTests[i][1]);
487.153 - if (on1.isPropertyPattern()) {
487.154 - if (!on1.getKeyPropertyListString().equals("")) continue;
487.155 - } else if (!on1.getCanonicalKeyPropertyListString()
487.156 - .equals(on2.getCanonicalKeyPropertyListString())) {
487.157 - continue;
487.158 - }
487.159 - System.out.println("Repository Positive Match Test ---------------");
487.160 - final String dom1 = on1.getDomain();
487.161 - final String dom2 = on2.getDomain();
487.162 - System.out.println("Util.wildpathmatch(\"" + dom2 + "\",\"" + dom1 + "\")");
487.163 - boolean result =
487.164 - Util.wildpathmatch(dom2,dom1);
487.165 - System.out.println("Result = " + result);
487.166 - if (result == false) {
487.167 - error++;
487.168 - System.out.println("Test failed!");
487.169 - } else {
487.170 - System.out.println("Test passed!");
487.171 - }
487.172 - } catch (Exception e) {
487.173 - error++;
487.174 - System.out.println("Got Unexpected Exception = " + e.toString());
487.175 - System.out.println("Test failed!");
487.176 - }
487.177 - System.out.println("----------------------------------------------");
487.178 - }
487.179 - return error;
487.180 - }
487.181 -
487.182 - private static int runRepositoryNegativeTests() {
487.183 - int error = 0;
487.184 - for (int i = 0; i < negativeTests.length; i++) {
487.185 - try {
487.186 - ObjectName on1 = ObjectName.getInstance(negativeTests[i][0]);
487.187 - ObjectName on2 = ObjectName.getInstance(negativeTests[i][1]);
487.188 - if (on1.isPropertyPattern()) {
487.189 - if (!on1.getKeyPropertyListString().equals("")) continue;
487.190 - } else if (!on1.getCanonicalKeyPropertyListString()
487.191 - .equals(on2.getCanonicalKeyPropertyListString())) {
487.192 - continue;
487.193 - }
487.194 - System.out.println("Repository Negative Match Test ---------------");
487.195 - final String dom1 = on1.getDomain();
487.196 - final String dom2 = on2.getDomain();
487.197 - System.out.println("Util.wildpathmatch(\"" + dom2 + "\",\"" + dom1 + "\")");
487.198 - boolean result =
487.199 - Util.wildpathmatch(dom2,dom1);
487.200 - System.out.println("Result = " + result);
487.201 - if (result == true) {
487.202 - error++;
487.203 - System.out.println("Test failed!");
487.204 - } else {
487.205 - System.out.println("Test passed!");
487.206 - }
487.207 - } catch (Exception e) {
487.208 - error++;
487.209 - System.out.println("Got Unexpected Exception = " + e.toString());
487.210 - System.out.println("Test failed!");
487.211 - }
487.212 - System.out.println("----------------------------------------------");
487.213 - }
487.214 - return error;
487.215 - }
487.216 -
487.217 public static void main(String[] args) throws Exception {
487.218
487.219 -
487.220 int error = 0;
487.221
487.222 - if (!(new ObjectName("z*x*:*").apply(new ObjectName("zaxcx//:k=v"))))
487.223 - throw new Exception();
487.224 -
487.225 -
487.226 // Check null values
487.227 //
487.228 System.out.println("----------------------------------------------");
487.229 @@ -429,10 +253,6 @@
487.230
487.231 error += runPositiveTests();
487.232 error += runNegativeTests();
487.233 - System.out.println("----------------------------------------------");
487.234 - error += runRepositoryPositiveTests();
487.235 - System.out.println("----------------------------------------------");
487.236 - error += runRepositoryNegativeTests();
487.237
487.238 if (error > 0) {
487.239 final String msg = "Test FAILED! Got " + error + " error(s)";
488.1 --- a/test/javax/management/ObjectName/ValueOfTest.java Mon Nov 23 10:04:47 2009 +0000
488.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
488.3 @@ -1,175 +0,0 @@
488.4 -/*
488.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
488.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
488.7 - *
488.8 - * This code is free software; you can redistribute it and/or modify it
488.9 - * under the terms of the GNU General Public License version 2 only, as
488.10 - * published by the Free Software Foundation.
488.11 - *
488.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
488.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
488.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
488.15 - * version 2 for more details (a copy is included in the LICENSE file that
488.16 - * accompanied this code).
488.17 - *
488.18 - * You should have received a copy of the GNU General Public License version
488.19 - * 2 along with this work; if not, write to the Free Software Foundation,
488.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
488.21 - *
488.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
488.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
488.24 - * have any questions.
488.25 - */
488.26 -
488.27 -/*
488.28 - * @test
488.29 - * @bug 6734813
488.30 - * @summary Test the ObjectName.valueOf methods
488.31 - * @author Eamonn McManus
488.32 - */
488.33 -
488.34 -import java.lang.reflect.Constructor;
488.35 -import java.lang.reflect.InvocationTargetException;
488.36 -import java.lang.reflect.Method;
488.37 -import java.util.Arrays;
488.38 -import java.util.Hashtable;
488.39 -import javax.management.MalformedObjectNameException;
488.40 -import javax.management.ObjectName;
488.41 -
488.42 -public class ValueOfTest {
488.43 - public static void main(String[] args) throws Exception {
488.44 - // Calls that should work
488.45 - testPositive("d:foo=bar,baz=buh");
488.46 - testPositive("foo", "bar", "baz");
488.47 - Hashtable<String, String> h = new Hashtable<String, String>();
488.48 - h.put("foo", "bar");
488.49 - h.put("baz", "buh");
488.50 - testPositive("domain", h);
488.51 -
488.52 - // Calls that should not work
488.53 - testNegative("d");
488.54 - testNegative("d:");
488.55 - testNegative("d::foo=bar");
488.56 - testNegative("d:", "foo", "bar");
488.57 - testNegative("d", "foo=", "bar");
488.58 - testNegative("d:", h);
488.59 - testNegative("d", new Hashtable<String, String>());
488.60 - }
488.61 -
488.62 - private static void testPositive(Object... args) throws Exception {
488.63 - Method valueOf = valueOfMethod(args);
488.64 - Method getInstance = getInstanceMethod(args);
488.65 - Constructor<?> constructor = constructor(args);
488.66 -
488.67 - Object valueOfValue = valueOf.invoke(null, args);
488.68 - Object getInstanceValue = getInstance.invoke(null, args);
488.69 - Object constructorValue = constructor.newInstance(args);
488.70 -
488.71 - String argString =
488.72 - Arrays.toString(args).replace('[', '(').replace(']', ')');
488.73 -
488.74 - if (!valueOfValue.equals(getInstanceValue)) {
488.75 - throw new Exception(
488.76 - "valueOf" + argString + " differs from getInstance" +
488.77 - argString);
488.78 - }
488.79 -
488.80 - if (!valueOfValue.equals(constructorValue)) {
488.81 - throw new Exception(
488.82 - "valueOf" + argString + " differs from new ObjectName " +
488.83 - argString);
488.84 - }
488.85 -
488.86 - System.out.println("OK: valueOf" + argString);
488.87 - }
488.88 -
488.89 - private static void testNegative(Object... args) throws Exception {
488.90 - Method valueOf = valueOfMethod(args);
488.91 - Method getInstance = getInstanceMethod(args);
488.92 -
488.93 - String argString =
488.94 - Arrays.toString(args).replace('[', '(').replace(']', ')');
488.95 -
488.96 - final Throwable valueOfException;
488.97 - try {
488.98 - valueOf.invoke(null, args);
488.99 - throw new Exception("valueOf" + argString + " did not fail but should");
488.100 - } catch (InvocationTargetException e) {
488.101 - valueOfException = e.getCause();
488.102 - }
488.103 - if (!(valueOfException instanceof IllegalArgumentException)) {
488.104 - throw new Exception(
488.105 - "valueOf" + argString + " threw " +
488.106 - valueOfException.getClass().getName() + " instead of " +
488.107 - "IllegalArgumentException", valueOfException);
488.108 - }
488.109 -
488.110 - final Throwable valueOfCause = valueOfException.getCause();
488.111 - if (!(valueOfCause instanceof MalformedObjectNameException)) {
488.112 - throw new Exception(
488.113 - "valueOf" + argString + " threw exception with wrong " +
488.114 - "type of cause", valueOfCause);
488.115 - }
488.116 -
488.117 - if (!valueOfException.getMessage().equals(valueOfCause.getMessage())) {
488.118 - // The IllegalArgumentException should have the same message as
488.119 - // the MalformedObjectNameException it wraps.
488.120 - // This isn't specified but is desirable.
488.121 - throw new Exception(
488.122 - "valueOf" + argString + ": message in wrapping " +
488.123 - "IllegalArgumentException (" + valueOfException.getMessage() +
488.124 - ") differs from message in wrapped " +
488.125 - "MalformedObjectNameException (" + valueOfCause.getMessage() +
488.126 - ")");
488.127 - }
488.128 -
488.129 - final Throwable getInstanceException;
488.130 - try {
488.131 - getInstance.invoke(null, args);
488.132 - throw new Exception("getInstance" + argString + " did not fail but should");
488.133 - } catch (InvocationTargetException e) {
488.134 - getInstanceException = e.getCause();
488.135 - }
488.136 - if (!(getInstanceException instanceof MalformedObjectNameException)) {
488.137 - throw new Exception(
488.138 - "getInstance" + argString + " threw wrong exception",
488.139 - getInstanceException);
488.140 - }
488.141 -
488.142 - if (!valueOfException.getMessage().equals(getInstanceException.getMessage())) {
488.143 - // Again this is not specified.
488.144 - throw new Exception(
488.145 - "Exception message from valueOf" + argString + " (" +
488.146 - valueOfException.getMessage() + ") differs from message " +
488.147 - "from getInstance" + argString + " (" +
488.148 - getInstanceException.getMessage() + ")");
488.149 - }
488.150 -
488.151 - System.out.println("OK (correct exception): valueOf" + argString);
488.152 - }
488.153 -
488.154 - private static Method valueOfMethod(Object[] args) throws Exception {
488.155 - return method("valueOf", args);
488.156 - }
488.157 -
488.158 - private static Method getInstanceMethod(Object[] args) throws Exception {
488.159 - return method("getInstance", args);
488.160 - }
488.161 -
488.162 - private static Method method(String name, Object[] args) throws Exception {
488.163 - Class<?>[] argTypes = argTypes(args);
488.164 - return ObjectName.class.getMethod(name, argTypes);
488.165 - }
488.166 -
488.167 - private static Constructor<?> constructor(Object[] args) throws Exception {
488.168 - Class<?>[] argTypes = argTypes(args);
488.169 - return ObjectName.class.getConstructor(argTypes);
488.170 - }
488.171 -
488.172 - private static Class<?>[] argTypes(Object[] args) {
488.173 - Class<?>[] argTypes = new Class<?>[args.length];
488.174 - for (int i = 0; i < args.length; i++)
488.175 - argTypes[i] = args[i].getClass();
488.176 - return argTypes;
488.177 - }
488.178 -}
489.1 --- a/test/javax/management/context/ContextForwarderTest.java Mon Nov 23 10:04:47 2009 +0000
489.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
489.3 @@ -1,103 +0,0 @@
489.4 -/*
489.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
489.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
489.7 - *
489.8 - * This code is free software; you can redistribute it and/or modify it
489.9 - * under the terms of the GNU General Public License version 2 only, as
489.10 - * published by the Free Software Foundation.
489.11 - *
489.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
489.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
489.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
489.15 - * version 2 for more details (a copy is included in the LICENSE file that
489.16 - * accompanied this code).
489.17 - *
489.18 - * You should have received a copy of the GNU General Public License version
489.19 - * 2 along with this work; if not, write to the Free Software Foundation,
489.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
489.21 - *
489.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
489.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
489.24 - * have any questions.
489.25 - */
489.26 -
489.27 -/*
489.28 - * @test
489.29 - * @bug 5072267
489.30 - * @summary Test that a context forwarder can be created and then installed.
489.31 - * @author Eamonn McManus
489.32 - */
489.33 -
489.34 -/* The specific thing we're testing for is that the forwarder can be created
489.35 - * with a null "next", and then installed with a real "next". An earlier
489.36 - * defect meant that in this case the simulated jmx.context// namespace had a
489.37 - * null handler that never changed.
489.38 - */
489.39 -
489.40 -import java.util.HashMap;
489.41 -import java.util.Map;
489.42 -import java.util.Set;
489.43 -import java.util.TreeSet;
489.44 -import javax.management.ClientContext;
489.45 -import javax.management.MBeanServer;
489.46 -import javax.management.MBeanServerConnection;
489.47 -import javax.management.MBeanServerFactory;
489.48 -import javax.management.ObjectName;
489.49 -import javax.management.remote.JMXConnector;
489.50 -import javax.management.remote.JMXConnectorFactory;
489.51 -import javax.management.remote.JMXConnectorServer;
489.52 -import javax.management.remote.JMXConnectorServerFactory;
489.53 -import javax.management.remote.JMXServiceURL;
489.54 -import javax.management.remote.MBeanServerForwarder;
489.55 -
489.56 -public class ContextForwarderTest {
489.57 - private static String failure;
489.58 -
489.59 - public static void main(String[] args) throws Exception {
489.60 - MBeanServer mbs = MBeanServerFactory.newMBeanServer();
489.61 - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
489.62 - Map<String, String> env = new HashMap<String, String>();
489.63 - env.put(JMXConnectorServer.CONTEXT_FORWARDER, "false");
489.64 - JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(
489.65 - url, env, mbs);
489.66 - MBeanServerForwarder sysMBSF = cs.getSystemMBeanServerForwarder();
489.67 - MBeanServerForwarder mbsf = ClientContext.newContextForwarder(mbs, sysMBSF);
489.68 - sysMBSF.setMBeanServer(mbsf);
489.69 -
489.70 - int localCount = mbs.getMBeanCount();
489.71 -
489.72 - cs.start();
489.73 - try {
489.74 - JMXConnector cc = JMXConnectorFactory.connect(cs.getAddress());
489.75 - MBeanServerConnection mbsc = cc.getMBeanServerConnection();
489.76 - mbsc = ClientContext.withContext(mbsc, "foo", "bar");
489.77 - int contextCount = mbsc.getMBeanCount();
489.78 - if (localCount + 1 != contextCount) {
489.79 - fail("Local MBean count %d, context MBean count %d",
489.80 - localCount, contextCount);
489.81 - }
489.82 - Set<ObjectName> localNames =
489.83 - new TreeSet<ObjectName>(mbs.queryNames(null, null));
489.84 - ObjectName contextNamespaceObjectName =
489.85 - new ObjectName(ClientContext.NAMESPACE + "//:type=JMXNamespace");
489.86 - if (!localNames.add(contextNamespaceObjectName))
489.87 - fail("Local names already contained context namespace handler");
489.88 - Set<ObjectName> contextNames = mbsc.queryNames(null, null);
489.89 - if (!localNames.equals(contextNames)) {
489.90 - fail("Name set differs locally and in context: " +
489.91 - "local: %s; context: %s", localNames, contextNames);
489.92 - }
489.93 - } finally {
489.94 - cs.stop();
489.95 - }
489.96 - if (failure != null)
489.97 - throw new Exception("TEST FAILED: " + failure);
489.98 - else
489.99 - System.out.println("TEST PASSED");
489.100 - }
489.101 -
489.102 - private static void fail(String msg, Object... params) {
489.103 - failure = String.format(msg, params);
489.104 - System.out.println("FAIL: " + failure);
489.105 - }
489.106 -}
490.1 --- a/test/javax/management/context/ContextTest.java Mon Nov 23 10:04:47 2009 +0000
490.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
490.3 @@ -1,534 +0,0 @@
490.4 -/*
490.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
490.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
490.7 - *
490.8 - * This code is free software; you can redistribute it and/or modify it
490.9 - * under the terms of the GNU General Public License version 2 only, as
490.10 - * published by the Free Software Foundation.
490.11 - *
490.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
490.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
490.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
490.15 - * version 2 for more details (a copy is included in the LICENSE file that
490.16 - * accompanied this code).
490.17 - *
490.18 - * You should have received a copy of the GNU General Public License version
490.19 - * 2 along with this work; if not, write to the Free Software Foundation,
490.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
490.21 - *
490.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
490.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
490.24 - * have any questions.
490.25 - */
490.26 -
490.27 -/*
490.28 - * @test ContextTest
490.29 - * @bug 5072267
490.30 - * @summary Test client contexts.
490.31 - * @author Eamonn McManus
490.32 - * TODO: Try registering with a null name replaced by preRegister (for example
490.33 - * from the MLet class) and see if it now works.
490.34 - */
490.35 -
490.36 -import java.lang.management.ManagementFactory;
490.37 -import java.lang.reflect.InvocationHandler;
490.38 -import java.lang.reflect.InvocationTargetException;
490.39 -import java.lang.reflect.Method;
490.40 -import java.lang.reflect.Proxy;
490.41 -import java.util.Arrays;
490.42 -import java.util.Collections;
490.43 -import java.util.HashMap;
490.44 -import java.util.HashSet;
490.45 -import java.util.LinkedList;
490.46 -import java.util.List;
490.47 -import java.util.Map;
490.48 -import java.util.Queue;
490.49 -import java.util.Set;
490.50 -import java.util.TreeMap;
490.51 -import java.util.concurrent.Callable;
490.52 -import javax.management.Attribute;
490.53 -import javax.management.AttributeList;
490.54 -import javax.management.ClientContext;
490.55 -import javax.management.DynamicMBean;
490.56 -import javax.management.JMX;
490.57 -import javax.management.ListenerNotFoundException;
490.58 -import javax.management.MBeanNotificationInfo;
490.59 -import javax.management.MBeanRegistration;
490.60 -import javax.management.MBeanServer;
490.61 -import javax.management.MBeanServerDelegate;
490.62 -import javax.management.Notification;
490.63 -import javax.management.NotificationBroadcasterSupport;
490.64 -import javax.management.NotificationFilter;
490.65 -import javax.management.NotificationListener;
490.66 -import javax.management.ObjectInstance;
490.67 -import javax.management.ObjectName;
490.68 -import javax.management.StandardMBean;
490.69 -import javax.management.loading.MLet;
490.70 -import javax.management.namespace.JMXNamespace;
490.71 -
490.72 -import javax.management.remote.MBeanServerForwarder;
490.73 -import static java.util.Collections.emptyMap;
490.74 -import static java.util.Collections.singletonMap;
490.75 -
490.76 -public class ContextTest {
490.77 - private static String failure;
490.78 - private static final Map<String, String> emptyContext = emptyMap();
490.79 -
490.80 - public static interface ShowContextMBean {
490.81 - public Map<String, String> getContext();
490.82 - public Map<String, String> getCreationContext();
490.83 - public Set<String> getCalledOps();
490.84 - public String getThing();
490.85 - public void setThing(String x);
490.86 - public int add(int x, int y);
490.87 - }
490.88 -
490.89 - public static class ShowContext
490.90 - extends NotificationBroadcasterSupport
490.91 - implements ShowContextMBean, MBeanRegistration {
490.92 - private final Map<String, String> creationContext;
490.93 - private final Set<String> calledOps = new HashSet<String>();
490.94 -
490.95 - public ShowContext() {
490.96 - creationContext = getContext();
490.97 - }
490.98 -
490.99 - public Map<String, String> getContext() {
490.100 - return ClientContext.getContext();
490.101 - }
490.102 -
490.103 - public Map<String, String> getCreationContext() {
490.104 - return creationContext;
490.105 - }
490.106 -
490.107 - public Set<String> getCalledOps() {
490.108 - return calledOps;
490.109 - }
490.110 -
490.111 - public String getThing() {
490.112 - return "x";
490.113 - }
490.114 -
490.115 - public void setThing(String x) {
490.116 - }
490.117 -
490.118 - public int add(int x, int y) {
490.119 - return x + y;
490.120 - }
490.121 -
490.122 - public ObjectName preRegister(MBeanServer server, ObjectName name) {
490.123 - assertEquals("preRegister context", creationContext, getContext());
490.124 - calledOps.add("preRegister");
490.125 - return name;
490.126 - }
490.127 -
490.128 - public void postRegister(Boolean registrationDone) {
490.129 - assertEquals("postRegister context", creationContext, getContext());
490.130 - calledOps.add("postRegister");
490.131 - }
490.132 -
490.133 - // The condition checked here is not guaranteed universally true,
490.134 - // but is true every time we unregister an instance of this MBean
490.135 - // in this test.
490.136 - public void preDeregister() throws Exception {
490.137 - assertEquals("preDeregister context", creationContext, getContext());
490.138 - }
490.139 -
490.140 - public void postDeregister() {
490.141 - assertEquals("postDeregister context", creationContext, getContext());
490.142 - }
490.143 -
490.144 - // Same remark as for preDeregister
490.145 - @Override
490.146 - public MBeanNotificationInfo[] getNotificationInfo() {
490.147 - calledOps.add("getNotificationInfo");
490.148 - return super.getNotificationInfo();
490.149 - }
490.150 -
490.151 - @Override
490.152 - public void addNotificationListener(
490.153 - NotificationListener listener, NotificationFilter filter, Object handback) {
490.154 - calledOps.add("addNotificationListener");
490.155 - super.addNotificationListener(listener, filter, handback);
490.156 - }
490.157 -
490.158 - @Override
490.159 - public void removeNotificationListener(
490.160 - NotificationListener listener)
490.161 - throws ListenerNotFoundException {
490.162 - calledOps.add("removeNL1");
490.163 - super.removeNotificationListener(listener);
490.164 - }
490.165 -
490.166 - @Override
490.167 - public void removeNotificationListener(
490.168 - NotificationListener listener, NotificationFilter filter, Object handback)
490.169 - throws ListenerNotFoundException {
490.170 - calledOps.add("removeNL3");
490.171 - super.removeNotificationListener(listener, filter, handback);
490.172 - }
490.173 - }
490.174 -
490.175 - private static class LogRecord {
490.176 - final String op;
490.177 - final Object[] params;
490.178 - final Map<String, String> context;
490.179 - LogRecord(String op, Object[] params, Map<String, String> context) {
490.180 - this.op = op;
490.181 - this.params = params;
490.182 - this.context = context;
490.183 - }
490.184 -
490.185 - @Override
490.186 - public String toString() {
490.187 - return op + Arrays.deepToString(params) + " " + context;
490.188 - }
490.189 - }
490.190 -
490.191 - /*
490.192 - * InvocationHandler that forwards all methods to a contained object
490.193 - * but also records each forwarded method. This allows us to check
490.194 - * that the appropriate methods were called with the appropriate
490.195 - * parameters. It's similar to what's typically available in
490.196 - * Mock Object frameworks.
490.197 - */
490.198 - private static class LogIH implements InvocationHandler {
490.199 - private final Object wrapped;
490.200 - Queue<LogRecord> log = new LinkedList<LogRecord>();
490.201 -
490.202 - LogIH(Object wrapped) {
490.203 - this.wrapped = wrapped;
490.204 - }
490.205 -
490.206 - public Object invoke(Object proxy, Method method, Object[] args)
490.207 - throws Throwable {
490.208 - if (method.getDeclaringClass() != Object.class) {
490.209 - LogRecord lr =
490.210 - new LogRecord(
490.211 - method.getName(), args, ClientContext.getContext());
490.212 - log.add(lr);
490.213 - }
490.214 - try {
490.215 - return method.invoke(wrapped, args);
490.216 - } catch (InvocationTargetException e) {
490.217 - throw e.getCause();
490.218 - }
490.219 - }
490.220 - }
490.221 -
490.222 - private static <T> T newSnoop(Class<T> wrappedClass, LogIH logIH) {
490.223 - return wrappedClass.cast(Proxy.newProxyInstance(
490.224 - wrappedClass.getClassLoader(),
490.225 - new Class<?>[] {wrappedClass},
490.226 - logIH));
490.227 - }
490.228 -
490.229 - public static void main(String[] args) throws Exception {
490.230 - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
490.231 - System.out.println(mbs.queryNames(null, null));
490.232 - ObjectName name = new ObjectName("a:b=c");
490.233 - mbs.registerMBean(new ShowContext(), name);
490.234 - final ShowContextMBean show =
490.235 - JMX.newMBeanProxy(mbs, name, ShowContextMBean.class);
490.236 -
490.237 - // Test local setting and getting within the MBeanServer
490.238 -
490.239 - assertEquals("initial context", emptyContext, show.getContext());
490.240 - ClientContext.doWithContext(singletonMap("foo", "bar"), new Callable<Void>() {
490.241 - public Void call() {
490.242 - assertEquals("context in doWithContext",
490.243 - singletonMap("foo", "bar"), show.getContext());
490.244 - return null;
490.245 - }
490.246 - });
490.247 - assertEquals("initial context after doWithContext",
490.248 - emptyContext, show.getContext());
490.249 - String got = ClientContext.doWithContext(
490.250 - singletonMap("foo", "baz"), new Callable<String>() {
490.251 - public String call() {
490.252 - return ClientContext.getContext().get("foo");
490.253 - }
490.254 - });
490.255 - assertEquals("value extracted from context", "baz", got);
490.256 -
490.257 - Map<String, String> combined = ClientContext.doWithContext(
490.258 - singletonMap("foo", "baz"), new Callable<Map<String, String>>() {
490.259 - public Map<String, String> call() throws Exception {
490.260 - return ClientContext.doWithContext(
490.261 - singletonMap("fred", "jim"),
490.262 - new Callable<Map<String, String>>() {
490.263 - public Map<String, String> call() {
490.264 - return ClientContext.getContext();
490.265 - }
490.266 - });
490.267 - }
490.268 - });
490.269 - assertEquals("nested doWithContext context",
490.270 - singletonMap("fred", "jim"), combined);
490.271 -
490.272 - final String ugh = "a!\u00c9//*=:\"% ";
490.273 - ClientContext.doWithContext(singletonMap(ugh, ugh), new Callable<Void>() {
490.274 - public Void call() {
490.275 - assertEquals("context with tricky encoding",
490.276 - singletonMap(ugh, ugh), show.getContext());
490.277 - return null;
490.278 - }
490.279 - });
490.280 - Map<String, String> ughMap = new TreeMap<String, String>();
490.281 - ughMap.put(ugh, ugh);
490.282 - ughMap.put("fred", "jim");
490.283 - // Since this is a TreeMap and "fred" is greater than ugh (which begins
490.284 - // with "a"), we will see the encoding of ugh first in the output string.
490.285 - String encoded = ClientContext.encode(ughMap);
490.286 - String expectedUghCoding = "a%21%C3%89%2F%2F%2A%3D%3A%22%25+";
490.287 - String expectedUghMapCoding =
490.288 - ClientContext.NAMESPACE + "//" + expectedUghCoding + "=" +
490.289 - expectedUghCoding + ";fred=jim";
490.290 - assertEquals("hairy context encoded as string",
490.291 - expectedUghMapCoding, encoded);
490.292 -
490.293 - // Wrap the MBeanServer with a context MBSF so we can test withContext.
490.294 - // Also check the simulated namespace directly.
490.295 -
490.296 - LogIH mbsIH = new LogIH(mbs);
490.297 - MBeanServer snoopMBS = newSnoop(MBeanServer.class, mbsIH);
490.298 - MBeanServerForwarder ctxMBS =
490.299 - ClientContext.newContextForwarder(snoopMBS, null);
490.300 -
490.301 - // The MBSF returned by ClientContext is actually a compound of two
490.302 - // forwarders, but that is supposed to be hidden by changing the
490.303 - // behaviour of get/setMBeanServer. Check that it is indeed so.
490.304 - assertEquals("next MBS of context forwarder",
490.305 - snoopMBS, ctxMBS.getMBeanServer());
490.306 - // If the above assertion fails you may get a confusing message
490.307 - // because the toString() of the two objects is likely to be the same
490.308 - // so it will look as if they should be equal.
490.309 - ctxMBS.setMBeanServer(null);
490.310 - assertEquals("next MBS of context forwarder after setting it null",
490.311 - null, ctxMBS.getMBeanServer());
490.312 - ctxMBS.setMBeanServer(snoopMBS);
490.313 -
490.314 - // The MBSF should look the same as the original MBeanServer except
490.315 - // that it has the JMXNamespace for the simulated namespace.
490.316 -
490.317 - Set<ObjectName> origNames = mbs.queryNames(null, null);
490.318 - Set<ObjectName> mbsfNames = ctxMBS.queryNames(null, null);
490.319 - assertEquals("number of MBeans returned by queryNames within forwarder",
490.320 - origNames.size() + 1, mbsfNames.size());
490.321 - assertEquals("MBeanCount within forwarder",
490.322 - mbsfNames.size(), ctxMBS.getMBeanCount());
490.323 - assertCalled(mbsIH, "queryNames", emptyContext);
490.324 - assertCalled(mbsIH, "getMBeanCount", emptyContext);
490.325 -
490.326 - ObjectName ctxNamespaceName = new ObjectName(
490.327 - ClientContext.NAMESPACE + "//:" + JMXNamespace.TYPE_ASSIGNMENT);
490.328 - origNames.add(ctxNamespaceName);
490.329 - assertEquals("MBeans within forwarder", origNames, mbsfNames);
490.330 - Set<String> domains = new HashSet<String>(Arrays.asList(ctxMBS.getDomains()));
490.331 - assertEquals("domains include context namespace MBean",
490.332 - true, domains.contains(ClientContext.NAMESPACE + "//"));
490.333 - assertCalled(mbsIH, "getDomains", emptyContext);
490.334 -
490.335 - // Now test ClientContext.withContext.
490.336 -
490.337 - MBeanServer ughMBS = ClientContext.withContext(ctxMBS, ugh, ugh);
490.338 -
490.339 - ShowContextMBean ughshow =
490.340 - JMX.newMBeanProxy(ughMBS, name, ShowContextMBean.class);
490.341 - Map<String, String> ughCtx = ughshow.getContext();
490.342 - Map<String, String> ughExpect = singletonMap(ugh, ugh);
490.343 - assertEquals("context seen by MBean accessed within namespace",
490.344 - ughExpect, ughCtx);
490.345 - assertCalled(mbsIH, "getAttribute", ughExpect, name, "Context");
490.346 -
490.347 - MBeanServer cmbs = ClientContext.withContext(
490.348 - ctxMBS, "mickey", "mouse");
490.349 - ShowContextMBean cshow =
490.350 - JMX.newMBeanProxy(cmbs, name, ShowContextMBean.class);
490.351 - assertEquals("context seen by MBean accessed within namespace",
490.352 - singletonMap("mickey", "mouse"), cshow.getContext());
490.353 -
490.354 - MBeanServer ccmbs = ClientContext.withContext(
490.355 - cmbs, "donald", "duck");
490.356 - ShowContextMBean ccshow =
490.357 - JMX.newMBeanProxy(ccmbs, name, ShowContextMBean.class);
490.358 - Map<String, String> disney = new HashMap<String, String>();
490.359 - disney.put("mickey", "mouse");
490.360 - disney.put("donald", "duck");
490.361 - assertEquals("context seen by MBean in nested namespace",
490.362 - disney, ccshow.getContext());
490.363 -
490.364 - // Test that all MBS ops produce reasonable results
490.365 -
490.366 - ObjectName logger = new ObjectName("a:type=Logger");
490.367 - DynamicMBean showMBean =
490.368 - new StandardMBean(new ShowContext(), ShowContextMBean.class);
490.369 - LogIH mbeanLogIH = new LogIH(showMBean);
490.370 - DynamicMBean logMBean = newSnoop(DynamicMBean.class, mbeanLogIH);
490.371 - ObjectInstance loggerOI = ccmbs.registerMBean(logMBean, logger);
490.372 - assertEquals("ObjectName returned by createMBean",
490.373 - logger, loggerOI.getObjectName());
490.374 -
490.375 - // We get an getMBeanInfo call to determine the className in the
490.376 - // ObjectInstance to return from registerMBean.
490.377 - assertCalled(mbeanLogIH, "getMBeanInfo", disney);
490.378 -
490.379 - ccmbs.getAttribute(logger, "Thing");
490.380 - assertCalled(mbeanLogIH, "getAttribute", disney);
490.381 -
490.382 - ccmbs.getAttributes(logger, new String[] {"Thing", "Context"});
490.383 - assertCalled(mbeanLogIH, "getAttributes", disney);
490.384 -
490.385 - ccmbs.setAttribute(logger, new Attribute("Thing", "bar"));
490.386 - assertCalled(mbeanLogIH, "setAttribute", disney);
490.387 -
490.388 - ccmbs.setAttributes(logger, new AttributeList(
490.389 - Arrays.asList(new Attribute("Thing", "baz"))));
490.390 - assertCalled(mbeanLogIH, "setAttributes", disney);
490.391 -
490.392 - ccmbs.getMBeanInfo(logger);
490.393 - assertCalled(mbeanLogIH, "getMBeanInfo", disney);
490.394 -
490.395 - Set<ObjectName> names = ccmbs.queryNames(null, null);
490.396 - Set<ObjectName> expectedNames = new HashSet<ObjectName>(
490.397 - Collections.singleton(MBeanServerDelegate.DELEGATE_NAME));
490.398 - assertEquals("context namespace query includes expected names",
490.399 - true, names.containsAll(expectedNames));
490.400 -
490.401 - Set<ObjectName> nsNames = ccmbs.queryNames(new ObjectName("*//:*"), null);
490.402 - Set<ObjectName> expectedNsNames = new HashSet<ObjectName>(
490.403 - Arrays.asList(
490.404 - new ObjectName(ClientContext.NAMESPACE +
490.405 - ObjectName.NAMESPACE_SEPARATOR + ":" +
490.406 - JMXNamespace.TYPE_ASSIGNMENT)));
490.407 - assertEquals("context namespace query includes namespace MBean",
490.408 - true, nsNames.containsAll(expectedNsNames));
490.409 -
490.410 -
490.411 -
490.412 - Set<ObjectInstance> insts = ccmbs.queryMBeans(
490.413 - MBeanServerDelegate.DELEGATE_NAME, null);
490.414 - assertEquals("size of set from MBeanServerDelegate query", 1, insts.size());
490.415 - assertEquals("ObjectName from MBeanServerDelegate query",
490.416 - MBeanServerDelegate.DELEGATE_NAME,
490.417 - insts.iterator().next().getObjectName());
490.418 -
490.419 - ObjectName createdName = new ObjectName("a:type=Created");
490.420 - ObjectInstance createdOI =
490.421 - ccmbs.createMBean(ShowContext.class.getName(), createdName);
490.422 - assertEquals("class name from createMBean",
490.423 - ShowContext.class.getName(), createdOI.getClassName());
490.424 - assertEquals("ObjectName from createMBean",
490.425 - createdName, createdOI.getObjectName());
490.426 - assertEquals("context within createMBean",
490.427 - disney, ccmbs.getAttribute(createdName, "CreationContext"));
490.428 -
490.429 - NotificationListener nothingListener = new NotificationListener() {
490.430 - public void handleNotification(Notification n, Object h) {}
490.431 - };
490.432 - ccmbs.addNotificationListener(createdName, nothingListener, null, null);
490.433 - ccmbs.removeNotificationListener(createdName, nothingListener, null, null);
490.434 - ccmbs.addNotificationListener(createdName, nothingListener, null, null);
490.435 - ccmbs.removeNotificationListener(createdName, nothingListener);
490.436 - Set<String> expectedOps = new HashSet<String>(Arrays.asList(
490.437 - "preRegister", "postRegister", "addNotificationListener",
490.438 - "removeNL1", "removeNL3", "getNotificationInfo"));
490.439 - assertEquals("operations called on MBean",
490.440 - expectedOps, ccmbs.getAttribute(createdName, "CalledOps"));
490.441 -
490.442 - assertEquals("ClassLoader for MBean",
490.443 - ShowContext.class.getClassLoader(),
490.444 - ccmbs.getClassLoaderFor(createdName));
490.445 -
490.446 - assertEquals("isRegistered", true, ccmbs.isRegistered(createdName));
490.447 - assertEquals("isInstanceOf", true, ccmbs.isInstanceOf(createdName,
490.448 - ShowContext.class.getName()));
490.449 - assertEquals("isInstanceOf", false, ccmbs.isInstanceOf(createdName,
490.450 - DynamicMBean.class.getName()));
490.451 - ccmbs.unregisterMBean(createdName);
490.452 - assertEquals("isRegistered after unregister",
490.453 - false, ccmbs.isRegistered(createdName));
490.454 -
490.455 - MLet mlet = new MLet();
490.456 - ObjectName defaultMLetName = new ObjectName("DefaultDomain:type=MLet");
490.457 -
490.458 - ccmbs.registerMBean(mlet, defaultMLetName);
490.459 -
490.460 - assertEquals("getClassLoader", mlet, ccmbs.getClassLoader(defaultMLetName));
490.461 -
490.462 - assertEquals("number of MBean operations", 0, mbeanLogIH.log.size());
490.463 -
490.464 - // Test that contexts still work when we can't combine two encoded contexts.
490.465 - // Here, we wrap cmbs (mickey=mouse) so that ccmbs2 (donald=duck) cannot
490.466 - // see that it already contains a context and therefore cannot combine
490.467 - // into mickey=mouse;donald=duck. We don't actually use the snoop
490.468 - // capabilities of the returned object -- we just want an opaque
490.469 - // MBeanServer wrapper
490.470 - MBeanServer cmbs2 = newSnoop(MBeanServer.class, new LogIH(cmbs));
490.471 - MBeanServer ccmbs2 = ClientContext.withContext(cmbs2, "donald", "duck");
490.472 - assertEquals("context when combination is impossible",
490.473 - disney, ccmbs2.getAttribute(name, "Context"));
490.474 -
490.475 - // Test failure cases of ClientContext.encode
490.476 - final List<Map<String, String>> badEncodeArgs =
490.477 - Arrays.asList(
490.478 - null,
490.479 - Collections.<String,String>singletonMap(null, "foo"),
490.480 - Collections.<String,String>singletonMap("foo", null));
490.481 - for (Map<String, String> bad : badEncodeArgs) {
490.482 - try {
490.483 - String oops = ClientContext.encode(bad);
490.484 - failed("ClientContext.encode(" + bad + ") should have failed: "
490.485 - + oops);
490.486 - } catch (Exception e) {
490.487 - assertEquals("Exception for ClientContext.encode(" + bad + ")",
490.488 - IllegalArgumentException.class, e.getClass());
490.489 - }
490.490 - }
490.491 -
490.492 - // ADD NEW TESTS HERE ^^^
490.493 -
490.494 - if (failure != null)
490.495 - throw new Exception(failure);
490.496 - }
490.497 -
490.498 - private static void assertEquals(String what, Object x, Object y) {
490.499 - if (!equal(x, y))
490.500 - failed(what + ": expected " + string(x) + "; got " + string(y));
490.501 - }
490.502 -
490.503 - private static boolean equal(Object x, Object y) {
490.504 - if (x == y)
490.505 - return true;
490.506 - if (x == null || y == null)
490.507 - return false;
490.508 - if (x.getClass().isArray())
490.509 - return Arrays.deepEquals(new Object[] {x}, new Object[] {y});
490.510 - return x.equals(y);
490.511 - }
490.512 -
490.513 - private static String string(Object x) {
490.514 - String s = Arrays.deepToString(new Object[] {x});
490.515 - return s.substring(1, s.length() - 1);
490.516 - }
490.517 -
490.518 - private static void assertCalled(
490.519 - LogIH logIH, String op, Map<String, String> expectedContext) {
490.520 - assertCalled(logIH, op, expectedContext, (Object[]) null);
490.521 - }
490.522 -
490.523 - private static void assertCalled(
490.524 - LogIH logIH, String op, Map<String, String> expectedContext,
490.525 - Object... params) {
490.526 - LogRecord lr = logIH.log.remove();
490.527 - assertEquals("called operation", op, lr.op);
490.528 - if (params != null)
490.529 - assertEquals("operation parameters", params, lr.params);
490.530 - assertEquals("operation context", expectedContext, lr.context);
490.531 - }
490.532 -
490.533 - private static void failed(String why) {
490.534 - failure = why;
490.535 - new Throwable("FAILED: " + why).printStackTrace(System.out);
490.536 - }
490.537 -}
491.1 --- a/test/javax/management/context/LocaleAwareBroadcasterTest.java Mon Nov 23 10:04:47 2009 +0000
491.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
491.3 @@ -1,328 +0,0 @@
491.4 -/*
491.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
491.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
491.7 - *
491.8 - * This code is free software; you can redistribute it and/or modify it
491.9 - * under the terms of the GNU General Public License version 2 only, as
491.10 - * published by the Free Software Foundation.
491.11 - *
491.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
491.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
491.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
491.15 - * version 2 for more details (a copy is included in the LICENSE file that
491.16 - * accompanied this code).
491.17 - *
491.18 - * You should have received a copy of the GNU General Public License version
491.19 - * 2 along with this work; if not, write to the Free Software Foundation,
491.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
491.21 - *
491.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
491.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
491.24 - * have any questions.
491.25 - */
491.26 -
491.27 -/*
491.28 - * @test
491.29 - * @bug 5072267
491.30 - * @summary Test that an MBean can handle localized Notification messages.
491.31 - * @author Eamonn McManus
491.32 - */
491.33 -
491.34 -import java.util.Collections;
491.35 -import java.util.ListResourceBundle;
491.36 -import java.util.Locale;
491.37 -import java.util.Map;
491.38 -import java.util.MissingResourceException;
491.39 -import java.util.ResourceBundle;
491.40 -import java.util.concurrent.ArrayBlockingQueue;
491.41 -import java.util.concurrent.BlockingQueue;
491.42 -import java.util.concurrent.Callable;
491.43 -import java.util.concurrent.ConcurrentHashMap;
491.44 -import java.util.concurrent.ConcurrentMap;
491.45 -import java.util.concurrent.TimeUnit;
491.46 -import javax.management.ClientContext;
491.47 -import javax.management.JMX;
491.48 -import javax.management.ListenerNotFoundException;
491.49 -import javax.management.MBeanNotificationInfo;
491.50 -import javax.management.MBeanServer;
491.51 -import javax.management.MBeanServerConnection;
491.52 -import javax.management.MBeanServerFactory;
491.53 -import javax.management.Notification;
491.54 -import javax.management.NotificationBroadcasterSupport;
491.55 -import javax.management.NotificationEmitter;
491.56 -import javax.management.NotificationFilter;
491.57 -import javax.management.NotificationListener;
491.58 -import javax.management.ObjectName;
491.59 -import javax.management.SendNotification;
491.60 -import javax.management.remote.JMXConnector;
491.61 -import javax.management.remote.JMXConnectorFactory;
491.62 -import javax.management.remote.JMXConnectorServer;
491.63 -import javax.management.remote.JMXConnectorServerFactory;
491.64 -import javax.management.remote.JMXServiceURL;
491.65 -
491.66 -public class LocaleAwareBroadcasterTest {
491.67 - static final ObjectName mbeanName = ObjectName.valueOf("d:type=LocaleAware");
491.68 -
491.69 - static final String
491.70 - messageKey = "broken.window",
491.71 - defaultMessage = "broken window",
491.72 - frenchMessage = "fen\u00eatre bris\u00e9e",
491.73 - irishMessage = "fuinneog briste";
491.74 -
491.75 - public static class Bundle extends ListResourceBundle {
491.76 - @Override
491.77 - protected Object[][] getContents() {
491.78 - return new Object[][] {
491.79 - {messageKey, defaultMessage},
491.80 - };
491.81 - }
491.82 - }
491.83 -
491.84 - public static class Bundle_fr extends ListResourceBundle {
491.85 - @Override
491.86 - protected Object[][] getContents() {
491.87 - return new Object[][] {
491.88 - {messageKey, frenchMessage},
491.89 - };
491.90 - }
491.91 - }
491.92 -
491.93 - public static class Bundle_ga extends ListResourceBundle {
491.94 - @Override
491.95 - protected Object[][] getContents() {
491.96 - return new Object[][] {
491.97 - {messageKey, irishMessage},
491.98 - };
491.99 - }
491.100 - }
491.101 -
491.102 - static volatile String failure;
491.103 -
491.104 - public static interface LocaleAwareMBean {
491.105 - public void sendNotification(Notification n);
491.106 - }
491.107 -
491.108 - public static class LocaleAware
491.109 - implements LocaleAwareMBean, NotificationEmitter, SendNotification {
491.110 -
491.111 - private final ConcurrentMap<Locale, NotificationBroadcasterSupport>
491.112 - localeToEmitter = newConcurrentMap();
491.113 -
491.114 - public void sendNotification(Notification n) {
491.115 - for (Map.Entry<Locale, NotificationBroadcasterSupport> entry :
491.116 - localeToEmitter.entrySet()) {
491.117 - Notification localizedNotif =
491.118 - localizeNotification(n, entry.getKey());
491.119 - entry.getValue().sendNotification(localizedNotif);
491.120 - }
491.121 - }
491.122 -
491.123 - public void addNotificationListener(
491.124 - NotificationListener listener,
491.125 - NotificationFilter filter,
491.126 - Object handback)
491.127 - throws IllegalArgumentException {
491.128 - Locale locale = ClientContext.getLocale();
491.129 - NotificationBroadcasterSupport broadcaster;
491.130 - broadcaster = localeToEmitter.get(locale);
491.131 - if (broadcaster == null) {
491.132 - broadcaster = new NotificationBroadcasterSupport();
491.133 - NotificationBroadcasterSupport old =
491.134 - localeToEmitter.putIfAbsent(locale, broadcaster);
491.135 - if (old != null)
491.136 - broadcaster = old;
491.137 - }
491.138 - broadcaster.addNotificationListener(listener, filter, handback);
491.139 - }
491.140 -
491.141 - public void removeNotificationListener(NotificationListener listener)
491.142 - throws ListenerNotFoundException {
491.143 - Locale locale = ClientContext.getLocale();
491.144 - NotificationBroadcasterSupport broadcaster =
491.145 - localeToEmitter.get(locale);
491.146 - if (broadcaster == null)
491.147 - throw new ListenerNotFoundException();
491.148 - broadcaster.removeNotificationListener(listener);
491.149 - }
491.150 -
491.151 - public void removeNotificationListener(
491.152 - NotificationListener listener,
491.153 - NotificationFilter filter,
491.154 - Object handback)
491.155 - throws ListenerNotFoundException {
491.156 - Locale locale = ClientContext.getLocale();
491.157 - NotificationBroadcasterSupport broadcaster =
491.158 - localeToEmitter.get(locale);
491.159 - if (broadcaster == null)
491.160 - throw new ListenerNotFoundException();
491.161 - broadcaster.removeNotificationListener(listener, filter, handback);
491.162 - }
491.163 -
491.164 - public MBeanNotificationInfo[] getNotificationInfo() {
491.165 - return new MBeanNotificationInfo[0];
491.166 - }
491.167 - }
491.168 -
491.169 - // Localize notif using the convention that the message looks like
491.170 - // [resourcebundlename:resourcekey]defaultmessage
491.171 - // for example [foo.bar.Resources:unknown.problem]
491.172 - static Notification localizeNotification(Notification n, Locale locale) {
491.173 - String msg = n.getMessage();
491.174 - if (!msg.startsWith("["))
491.175 - return n;
491.176 - int close = msg.indexOf(']');
491.177 - if (close < 0)
491.178 - throw new IllegalArgumentException("Bad notification message: " + msg);
491.179 - int colon = msg.indexOf(':');
491.180 - if (colon < 0 || colon > close)
491.181 - throw new IllegalArgumentException("Bad notification message: " + msg);
491.182 - String bundleName = msg.substring(1, colon);
491.183 - String key = msg.substring(colon + 1, close);
491.184 - ClassLoader loader = LocaleAwareBroadcasterTest.class.getClassLoader();
491.185 - ResourceBundle bundle =
491.186 - ResourceBundle.getBundle(bundleName, locale, loader);
491.187 - try {
491.188 - msg = bundle.getString(key);
491.189 - } catch (MissingResourceException e) {
491.190 - msg = msg.substring(close + 1);
491.191 - }
491.192 - n = (Notification) n.clone();
491.193 - n.setMessage(msg);
491.194 - return n;
491.195 - }
491.196 -
491.197 - public static void main(String[] args) throws Exception {
491.198 - Locale.setDefault(new Locale("en"));
491.199 - testLocal();
491.200 - testRemote();
491.201 - if (failure == null)
491.202 - System.out.println("TEST PASSED");
491.203 - else
491.204 - throw new Exception("TEST FAILED: " + failure);
491.205 - }
491.206 -
491.207 - static interface AddListenerInLocale {
491.208 - public void addListenerInLocale(
491.209 - MBeanServerConnection mbsc,
491.210 - NotificationListener listener,
491.211 - Locale locale) throws Exception;
491.212 - }
491.213 -
491.214 - private static void testLocal() throws Exception {
491.215 - System.out.println("Test local MBeanServer using doWithContext");
491.216 - MBeanServer mbs = makeMBS();
491.217 - AddListenerInLocale addListener = new AddListenerInLocale() {
491.218 - public void addListenerInLocale(
491.219 - final MBeanServerConnection mbsc,
491.220 - final NotificationListener listener,
491.221 - Locale locale) throws Exception {
491.222 - Map<String, String> localeContext = Collections.singletonMap(
491.223 - ClientContext.LOCALE_KEY, locale.toString());
491.224 - ClientContext.doWithContext(
491.225 - localeContext, new Callable<Void>() {
491.226 - public Void call() throws Exception {
491.227 - mbsc.addNotificationListener(
491.228 - mbeanName, listener, null, null);
491.229 - return null;
491.230 - }
491.231 - });
491.232 - }
491.233 - };
491.234 - test(mbs, addListener);
491.235 - }
491.236 -
491.237 - private static void testRemote() throws Exception {
491.238 - System.out.println("Test remote MBeanServer using withLocale");
491.239 - MBeanServer mbs = makeMBS();
491.240 - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
491.241 - JMXConnectorServer cs =
491.242 - JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
491.243 - cs.start();
491.244 - JMXServiceURL addr = cs.getAddress();
491.245 - JMXConnector cc = JMXConnectorFactory.connect(addr);
491.246 - MBeanServerConnection mbsc = cc.getMBeanServerConnection();
491.247 - AddListenerInLocale addListenerInLocale = new AddListenerInLocale() {
491.248 - public void addListenerInLocale(
491.249 - MBeanServerConnection mbsc,
491.250 - NotificationListener listener,
491.251 - Locale locale) throws Exception {
491.252 - mbsc = ClientContext.withLocale(mbsc, locale);
491.253 - mbsc.addNotificationListener(mbeanName, listener, null, null);
491.254 - }
491.255 - };
491.256 - try {
491.257 - test(mbsc, addListenerInLocale);
491.258 - } finally {
491.259 - try {
491.260 - cc.close();
491.261 - } catch (Exception e) {}
491.262 - cs.stop();
491.263 - }
491.264 - }
491.265 -
491.266 - static class QueueListener implements NotificationListener {
491.267 - final BlockingQueue<Notification> queue =
491.268 - new ArrayBlockingQueue<Notification>(10);
491.269 -
491.270 - public void handleNotification(Notification notification,
491.271 - Object handback) {
491.272 - queue.add(notification);
491.273 - }
491.274 - }
491.275 -
491.276 - private static void test(
491.277 - MBeanServerConnection mbsc, AddListenerInLocale addListener)
491.278 - throws Exception {
491.279 - QueueListener defaultListener = new QueueListener();
491.280 - QueueListener frenchListener = new QueueListener();
491.281 - QueueListener irishListener = new QueueListener();
491.282 - mbsc.addNotificationListener(mbeanName, defaultListener, null, null);
491.283 - addListener.addListenerInLocale(mbsc, frenchListener, new Locale("fr"));
491.284 - addListener.addListenerInLocale(mbsc, irishListener, new Locale("ga"));
491.285 -
491.286 - LocaleAwareMBean proxy =
491.287 - JMX.newMBeanProxy(mbsc, mbeanName, LocaleAwareMBean.class);
491.288 - String notifMsg = "[" + Bundle.class.getName() + ":" + messageKey + "]" +
491.289 - "broken window (default message that should never be seen)";
491.290 - Notification notif = new Notification(
491.291 - "notif.type", mbeanName, 0L, notifMsg);
491.292 - proxy.sendNotification(notif);
491.293 -
491.294 - final Object[][] expected = {
491.295 - {defaultListener, defaultMessage},
491.296 - {frenchListener, frenchMessage},
491.297 - {irishListener, irishMessage},
491.298 - };
491.299 - for (Object[] exp : expected) {
491.300 - QueueListener ql = (QueueListener) exp[0];
491.301 - String msg = (String) exp[1];
491.302 - System.out.println("Checking: " + msg);
491.303 - Notification n = ql.queue.poll(1, TimeUnit.SECONDS);
491.304 - if (n == null)
491.305 - fail("Did not receive expected notif: " + msg);
491.306 - if (!n.getMessage().equals(msg)) {
491.307 - fail("Received notif with wrong message: got " +
491.308 - n.getMessage() + ", expected " + msg);
491.309 - }
491.310 - n = ql.queue.poll(2, TimeUnit.MILLISECONDS);
491.311 - if (n != null)
491.312 - fail("Received unexpected extra notif: " + n);
491.313 - }
491.314 - }
491.315 -
491.316 - private static MBeanServer makeMBS() throws Exception {
491.317 - MBeanServer mbs = MBeanServerFactory.newMBeanServer();
491.318 - LocaleAware aware = new LocaleAware();
491.319 - mbs.registerMBean(aware, mbeanName);
491.320 - return mbs;
491.321 - }
491.322 -
491.323 - static <K, V> ConcurrentMap<K, V> newConcurrentMap() {
491.324 - return new ConcurrentHashMap<K, V>();
491.325 - }
491.326 -
491.327 - static void fail(String why) {
491.328 - System.out.println("FAIL: " + why);
491.329 - failure = why;
491.330 - }
491.331 -}
492.1 --- a/test/javax/management/context/LocaleTest.java Mon Nov 23 10:04:47 2009 +0000
492.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
492.3 @@ -1,140 +0,0 @@
492.4 -/*
492.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
492.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
492.7 - *
492.8 - * This code is free software; you can redistribute it and/or modify it
492.9 - * under the terms of the GNU General Public License version 2 only, as
492.10 - * published by the Free Software Foundation.
492.11 - *
492.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
492.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
492.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
492.15 - * version 2 for more details (a copy is included in the LICENSE file that
492.16 - * accompanied this code).
492.17 - *
492.18 - * You should have received a copy of the GNU General Public License version
492.19 - * 2 along with this work; if not, write to the Free Software Foundation,
492.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
492.21 - *
492.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
492.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
492.24 - * have any questions.
492.25 - */
492.26 -
492.27 -/*
492.28 - * @test LocaleTest.java
492.29 - * @bug 5072267
492.30 - * @summary Test client locales.
492.31 - * @author Eamonn McManus
492.32 - */
492.33 -
492.34 -import java.lang.management.ManagementFactory;
492.35 -import java.util.Collections;
492.36 -import java.util.ListResourceBundle;
492.37 -import java.util.Locale;
492.38 -import java.util.Map;
492.39 -import java.util.ResourceBundle;
492.40 -import java.util.concurrent.Callable;
492.41 -import javax.management.ClientContext;
492.42 -import java.util.Arrays;
492.43 -import javax.management.MBeanServer;
492.44 -import javax.management.ObjectName;
492.45 -
492.46 -public class LocaleTest {
492.47 - private static String failure;
492.48 -
492.49 - public static void main(String[] args) throws Exception {
492.50 -
492.51 - // Test the translation String -> Locale
492.52 -
492.53 - Locale[] locales = Locale.getAvailableLocales();
492.54 - System.out.println("Testing String->Locale for " + locales.length +
492.55 - " locales");
492.56 - for (Locale loc : locales) {
492.57 - Map<String, String> ctx = Collections.singletonMap(
492.58 - ClientContext.LOCALE_KEY, loc.toString());
492.59 - Locale loc2 = ClientContext.doWithContext(
492.60 - ctx, new Callable<Locale>() {
492.61 - public Locale call() {
492.62 - return ClientContext.getLocale();
492.63 - }
492.64 - });
492.65 - assertEquals(loc, loc2);
492.66 - }
492.67 -
492.68 - // Test that a locale-sensitive attribute works
492.69 -
492.70 - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
492.71 - mbs = ClientContext.newContextForwarder(mbs, null);
492.72 - ObjectName name = new ObjectName("a:type=LocaleSensitive");
492.73 - mbs.registerMBean(new LocaleSensitive(), name);
492.74 - Locale.setDefault(Locale.US);
492.75 -
492.76 - assertEquals("spectacular failure",
492.77 - mbs.getAttribute(name, "LastProblemDescription"));
492.78 -
492.79 - MBeanServer frmbs = ClientContext.withContext(
492.80 - mbs, ClientContext.LOCALE_KEY, Locale.FRANCE.toString());
492.81 - assertEquals("\u00e9chec r\u00e9tentissant",
492.82 - frmbs.getAttribute(name, "LastProblemDescription"));
492.83 -
492.84 - if (failure == null)
492.85 - System.out.println("TEST PASSED");
492.86 - else
492.87 - throw new Exception("TEST FAILED: " + failure);
492.88 - }
492.89 -
492.90 - public static interface LocaleSensitiveMBean {
492.91 - public String getLastProblemDescription();
492.92 - }
492.93 -
492.94 - public static class LocaleSensitive implements LocaleSensitiveMBean {
492.95 - public String getLastProblemDescription() {
492.96 - Locale loc = ClientContext.getLocale();
492.97 - ResourceBundle rb = ResourceBundle.getBundle(
492.98 - MyResources.class.getName(), loc);
492.99 - return rb.getString("spectacular");
492.100 - }
492.101 - }
492.102 -
492.103 - public static class MyResources extends ListResourceBundle {
492.104 - protected Object[][] getContents() {
492.105 - return new Object[][] {
492.106 - {"spectacular", "spectacular failure"},
492.107 - };
492.108 - }
492.109 - }
492.110 -
492.111 - public static class MyResources_fr extends ListResourceBundle {
492.112 - protected Object[][] getContents() {
492.113 - return new Object[][] {
492.114 - {"spectacular", "\u00e9chec r\u00e9tentissant"},
492.115 - };
492.116 - }
492.117 - }
492.118 -
492.119 - private static void assertEquals(Object x, Object y) {
492.120 - if (!equal(x, y))
492.121 - failed("expected " + string(x) + "; got " + string(y));
492.122 - }
492.123 -
492.124 - private static boolean equal(Object x, Object y) {
492.125 - if (x == y)
492.126 - return true;
492.127 - if (x == null || y == null)
492.128 - return false;
492.129 - if (x.getClass().isArray())
492.130 - return Arrays.deepEquals(new Object[] {x}, new Object[] {y});
492.131 - return x.equals(y);
492.132 - }
492.133 -
492.134 - private static String string(Object x) {
492.135 - String s = Arrays.deepToString(new Object[] {x});
492.136 - return s.substring(1, s.length() - 1);
492.137 - }
492.138 -
492.139 - private static void failed(String why) {
492.140 - failure = why;
492.141 - new Throwable("FAILED: " + why).printStackTrace(System.out);
492.142 - }
492.143 -}
493.1 --- a/test/javax/management/context/LocalizableTest.java Mon Nov 23 10:04:47 2009 +0000
493.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
493.3 @@ -1,192 +0,0 @@
493.4 -/*
493.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
493.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
493.7 - *
493.8 - * This code is free software; you can redistribute it and/or modify it
493.9 - * under the terms of the GNU General Public License version 2 only, as
493.10 - * published by the Free Software Foundation.
493.11 - *
493.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
493.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
493.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
493.15 - * version 2 for more details (a copy is included in the LICENSE file that
493.16 - * accompanied this code).
493.17 - *
493.18 - * You should have received a copy of the GNU General Public License version
493.19 - * 2 along with this work; if not, write to the Free Software Foundation,
493.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
493.21 - *
493.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
493.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
493.24 - * have any questions.
493.25 - */
493.26 -
493.27 -/*
493.28 - * @test LocalizableTest
493.29 - * @bug 5072267 6635499
493.30 - * @summary Test localizable MBeanInfo using LocalizableMBeanFactory.
493.31 - * @author Eamonn McManus
493.32 - */
493.33 -
493.34 -import java.lang.management.ManagementFactory;
493.35 -import java.util.Locale;
493.36 -import java.util.ResourceBundle;
493.37 -import javax.management.ClientContext;
493.38 -import javax.management.Description;
493.39 -import javax.management.JMX;
493.40 -import javax.management.MBeanAttributeInfo;
493.41 -import javax.management.MBeanConstructorInfo;
493.42 -import javax.management.MBeanInfo;
493.43 -import javax.management.MBeanOperationInfo;
493.44 -import javax.management.MBeanParameterInfo;
493.45 -import javax.management.MBeanServer;
493.46 -import javax.management.ObjectName;
493.47 -
493.48 -import localizable.MBeanDescriptions_fr;
493.49 -import localizable.Whatsit;
493.50 -
493.51 -import static localizable.WhatsitMBean.*;
493.52 -
493.53 -public class LocalizableTest {
493.54 - // If you change the order of the array elements or their number then
493.55 - // you must also change these constants.
493.56 - private static final int
493.57 - MBEAN = 0, ATTR = 1, OPER = 2, PARAM = 3, CONSTR = 4,
493.58 - CONSTR_PARAM = 5;
493.59 - private static final String[] englishDescriptions = {
493.60 - englishMBeanDescription, englishAttrDescription, englishOperDescription,
493.61 - englishParamDescription, englishConstrDescription,
493.62 - englishConstrParamDescription,
493.63 - };
493.64 - private static final String[] defaultDescriptions = englishDescriptions.clone();
493.65 - static {
493.66 - defaultDescriptions[MBEAN] = defaultMBeanDescription;
493.67 - }
493.68 - private static final String[] frenchDescriptions = {
493.69 - frenchMBeanDescription, frenchAttrDescription, frenchOperDescription,
493.70 - frenchParamDescription, frenchConstrDescription,
493.71 - frenchConstrParamDescription,
493.72 - };
493.73 -
493.74 - private static String failure;
493.75 -
493.76 - @Description(unlocalizedMBeanDescription)
493.77 - public static interface UnlocalizedMBean {}
493.78 - public static class Unlocalized implements UnlocalizedMBean {}
493.79 -
493.80 - public static void main(String[] args) throws Exception {
493.81 - ResourceBundle frenchBundle = new MBeanDescriptions_fr();
493.82 - // The purpose of the previous line is to force that class to be compiled
493.83 - // when the test is run so it will be available for reflection.
493.84 - // Yes, we could do this with a @build tag.
493.85 -
493.86 - MBeanServer plainMBS = ManagementFactory.getPlatformMBeanServer();
493.87 - MBeanServer unlocalizedMBS =
493.88 - ClientContext.newContextForwarder(plainMBS, null);
493.89 - MBeanServer localizedMBS =
493.90 - ClientContext.newLocalizeMBeanInfoForwarder(plainMBS);
493.91 - localizedMBS = ClientContext.newContextForwarder(localizedMBS, null);
493.92 - ObjectName name = new ObjectName("a:b=c");
493.93 -
493.94 - Whatsit whatsit = new Whatsit();
493.95 - Object[][] locales = {
493.96 - {null, englishDescriptions},
493.97 - {"en", englishDescriptions},
493.98 - {"fr", frenchDescriptions},
493.99 - };
493.100 -
493.101 - for (Object[] localePair : locales) {
493.102 - String locale = (String) localePair[0];
493.103 - String[] localizedDescriptions = (String[]) localePair[1];
493.104 - System.out.println("===Testing locale " + locale + "===");
493.105 - for (boolean localized : new boolean[] {false, true}) {
493.106 - String[] descriptions = localized ?
493.107 - localizedDescriptions : defaultDescriptions;
493.108 - MBeanServer mbs = localized ? localizedMBS : unlocalizedMBS;
493.109 - System.out.println("Testing MBean " + whatsit + " with " +
493.110 - "localized=" + localized);
493.111 - mbs.registerMBean(whatsit, name);
493.112 - System.out.println(mbs.getMBeanInfo(name));
493.113 - try {
493.114 - test(mbs, name, locale, descriptions);
493.115 - } catch (Exception e) {
493.116 - fail("Caught exception: " + e);
493.117 - } finally {
493.118 - mbs.unregisterMBean(name);
493.119 - }
493.120 - }
493.121 - }
493.122 -
493.123 - System.out.println("===Testing unlocalizable MBean===");
493.124 - Object mbean = new Unlocalized();
493.125 - localizedMBS.registerMBean(mbean, name);
493.126 - try {
493.127 - MBeanInfo mbi = localizedMBS.getMBeanInfo(name);
493.128 - assertEquals("MBean description", unlocalizedMBeanDescription,
493.129 - mbi.getDescription());
493.130 - } finally {
493.131 - localizedMBS.unregisterMBean(name);
493.132 - }
493.133 -
493.134 - System.out.println("===Testing MBeanInfo.localizeDescriptions===");
493.135 - plainMBS.registerMBean(whatsit, name);
493.136 - MBeanInfo mbi = plainMBS.getMBeanInfo(name);
493.137 - Locale french = new Locale("fr");
493.138 - mbi = mbi.localizeDescriptions(french, whatsit.getClass().getClassLoader());
493.139 - checkDescriptions(mbi, frenchDescriptions);
493.140 -
493.141 - if (failure == null)
493.142 - System.out.println("TEST PASSED");
493.143 - else
493.144 - throw new Exception("TEST FAILED: Last failure: " + failure);
493.145 - }
493.146 -
493.147 - private static void test(MBeanServer mbs, ObjectName name, String locale,
493.148 - String[] expectedDescriptions)
493.149 - throws Exception {
493.150 - if (locale != null)
493.151 - mbs = ClientContext.withLocale(mbs, new Locale(locale));
493.152 - MBeanInfo mbi = mbs.getMBeanInfo(name);
493.153 - checkDescriptions(mbi, expectedDescriptions);
493.154 - }
493.155 -
493.156 - private static void checkDescriptions(MBeanInfo mbi,
493.157 - String[] expectedDescriptions) {
493.158 - assertEquals("MBean description",
493.159 - expectedDescriptions[MBEAN], mbi.getDescription());
493.160 - MBeanAttributeInfo mbai = mbi.getAttributes()[0];
493.161 - assertEquals("Attribute description",
493.162 - expectedDescriptions[ATTR], mbai.getDescription());
493.163 - MBeanOperationInfo mboi = mbi.getOperations()[0];
493.164 - assertEquals("Operation description",
493.165 - expectedDescriptions[OPER], mboi.getDescription());
493.166 - MBeanParameterInfo mbpi = mboi.getSignature()[0];
493.167 - assertEquals("Parameter description",
493.168 - expectedDescriptions[PARAM], mbpi.getDescription());
493.169 - MBeanConstructorInfo[] mbcis = mbi.getConstructors();
493.170 - assertEquals("Number of constructors", 2, mbcis.length);
493.171 - for (MBeanConstructorInfo mbci : mbcis) {
493.172 - MBeanParameterInfo[] mbcpis = mbci.getSignature();
493.173 - String constrName = mbcpis.length + "-arg constructor";
493.174 - assertEquals(constrName + " description",
493.175 - expectedDescriptions[CONSTR], mbci.getDescription());
493.176 - if (mbcpis.length > 0) {
493.177 - assertEquals(constrName + " parameter description",
493.178 - expectedDescriptions[CONSTR_PARAM],
493.179 - mbcpis[0].getDescription());
493.180 - }
493.181 - }
493.182 - }
493.183 -
493.184 - private static void assertEquals(String what, Object expect, Object actual) {
493.185 - if (expect.equals(actual))
493.186 - System.out.println("...OK: " + what + " = " + expect);
493.187 - else
493.188 - fail(what + " should be " + expect + ", was " + actual);
493.189 - }
493.190 -
493.191 - private static void fail(String why) {
493.192 - System.out.println("FAIL: " + why);
493.193 - failure = why;
493.194 - }
493.195 -}
494.1 --- a/test/javax/management/context/RemoteContextTest.java Mon Nov 23 10:04:47 2009 +0000
494.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
494.3 @@ -1,496 +0,0 @@
494.4 -/*
494.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
494.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
494.7 - *
494.8 - * This code is free software; you can redistribute it and/or modify it
494.9 - * under the terms of the GNU General Public License version 2 only, as
494.10 - * published by the Free Software Foundation.
494.11 - *
494.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
494.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
494.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
494.15 - * version 2 for more details (a copy is included in the LICENSE file that
494.16 - * accompanied this code).
494.17 - *
494.18 - * You should have received a copy of the GNU General Public License version
494.19 - * 2 along with this work; if not, write to the Free Software Foundation,
494.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
494.21 - *
494.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
494.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
494.24 - * have any questions.
494.25 - */
494.26 -
494.27 -/*
494.28 - * @test RemoteContextTest.java
494.29 - * @bug 5072267
494.30 - * @summary Test client contexts with namespaces.
494.31 - * @author Eamonn McManus, Daniel Fuchs
494.32 - */
494.33 -
494.34 -import java.lang.management.ManagementFactory;
494.35 -import java.lang.reflect.InvocationHandler;
494.36 -import java.lang.reflect.InvocationTargetException;
494.37 -import java.lang.reflect.Method;
494.38 -import java.lang.reflect.Proxy;
494.39 -import java.net.URLEncoder;
494.40 -import java.util.Arrays;
494.41 -import java.util.Collections;
494.42 -import java.util.HashMap;
494.43 -import java.util.HashSet;
494.44 -import java.util.LinkedList;
494.45 -import java.util.Map;
494.46 -import java.util.Queue;
494.47 -import java.util.Set;
494.48 -import java.util.concurrent.Callable;
494.49 -import javax.management.Attribute;
494.50 -import javax.management.AttributeList;
494.51 -import javax.management.ClientContext;
494.52 -import javax.management.DynamicMBean;
494.53 -import javax.management.JMX;
494.54 -import javax.management.ListenerNotFoundException;
494.55 -import javax.management.MBeanNotificationInfo;
494.56 -import javax.management.MBeanRegistration;
494.57 -import javax.management.MBeanServer;
494.58 -import javax.management.MBeanServerConnection;
494.59 -import javax.management.MBeanServerDelegate;
494.60 -import javax.management.Notification;
494.61 -import javax.management.NotificationBroadcasterSupport;
494.62 -import javax.management.NotificationFilter;
494.63 -import javax.management.NotificationListener;
494.64 -import javax.management.ObjectInstance;
494.65 -import javax.management.ObjectName;
494.66 -import javax.management.StandardMBean;
494.67 -import javax.management.loading.MLet;
494.68 -import javax.management.namespace.JMXNamespaces;
494.69 -import javax.management.namespace.JMXRemoteNamespace;
494.70 -import javax.management.namespace.JMXNamespace;
494.71 -
494.72 -import static java.util.Collections.singletonMap;
494.73 -import javax.management.MBeanServerFactory;
494.74 -import javax.management.remote.JMXConnectorServer;
494.75 -import javax.management.remote.JMXConnectorServerFactory;
494.76 -import javax.management.remote.JMXServiceURL;
494.77 -
494.78 -public class RemoteContextTest {
494.79 - private static String failure;
494.80 -
494.81 - public static interface ShowContextMBean {
494.82 - public Map<String, String> getContext();
494.83 - public Map<String, String> getCreationContext();
494.84 - public Set<String> getCalledOps();
494.85 - public String getThing();
494.86 - public void setThing(String x);
494.87 - public int add(int x, int y);
494.88 - }
494.89 -
494.90 - public static class ShowContext
494.91 - extends NotificationBroadcasterSupport
494.92 - implements ShowContextMBean, MBeanRegistration {
494.93 - private final Map<String, String> creationContext;
494.94 - private final Set<String> calledOps = new HashSet<String>();
494.95 -
494.96 - public ShowContext() {
494.97 - creationContext = getContext();
494.98 - }
494.99 -
494.100 - public Map<String, String> getContext() {
494.101 - return ClientContext.getContext();
494.102 - }
494.103 -
494.104 - public Map<String, String> getCreationContext() {
494.105 - return creationContext;
494.106 - }
494.107 -
494.108 - public Set<String> getCalledOps() {
494.109 - return calledOps;
494.110 - }
494.111 -
494.112 - public String getThing() {
494.113 - return "x";
494.114 - }
494.115 -
494.116 - public void setThing(String x) {
494.117 - }
494.118 -
494.119 - public int add(int x, int y) {
494.120 - return x + y;
494.121 - }
494.122 -
494.123 - public ObjectName preRegister(MBeanServer server, ObjectName name) {
494.124 - assertEquals(creationContext, getContext());
494.125 - calledOps.add("preRegister");
494.126 - return name;
494.127 - }
494.128 -
494.129 - public void postRegister(Boolean registrationDone) {
494.130 - assertEquals(creationContext, getContext());
494.131 - calledOps.add("postRegister");
494.132 - }
494.133 -
494.134 - // The condition checked here is not guaranteed universally true,
494.135 - // but is true every time we unregister an instance of this MBean
494.136 - // in this test.
494.137 - public void preDeregister() throws Exception {
494.138 - assertEquals(creationContext, getContext());
494.139 - }
494.140 -
494.141 - public void postDeregister() {
494.142 - assertEquals(creationContext, getContext());
494.143 - }
494.144 -
494.145 - // Same remark as for preDeregister
494.146 - @Override
494.147 - public MBeanNotificationInfo[] getNotificationInfo() {
494.148 - calledOps.add("getNotificationInfo");
494.149 - return super.getNotificationInfo();
494.150 - }
494.151 -
494.152 - @Override
494.153 - public void addNotificationListener(
494.154 - NotificationListener listener, NotificationFilter filter, Object handback) {
494.155 - calledOps.add("addNotificationListener");
494.156 - super.addNotificationListener(listener, filter, handback);
494.157 - }
494.158 -
494.159 - @Override
494.160 - public void removeNotificationListener(
494.161 - NotificationListener listener)
494.162 - throws ListenerNotFoundException {
494.163 - calledOps.add("removeNL1");
494.164 - super.removeNotificationListener(listener);
494.165 - }
494.166 -
494.167 - @Override
494.168 - public void removeNotificationListener(
494.169 - NotificationListener listener, NotificationFilter filter, Object handback)
494.170 - throws ListenerNotFoundException {
494.171 - calledOps.add("removeNL3");
494.172 - super.removeNotificationListener(listener, filter, handback);
494.173 - }
494.174 - }
494.175 -
494.176 - private static class LogRecord {
494.177 - final String op;
494.178 - final Object[] params;
494.179 - final Map<String, String> context;
494.180 - LogRecord(String op, Object[] params, Map<String, String> context) {
494.181 - this.op = op;
494.182 - this.params = params;
494.183 - this.context = context;
494.184 - }
494.185 -
494.186 - @Override
494.187 - public String toString() {
494.188 - return op + Arrays.deepToString(params) + " " + context;
494.189 - }
494.190 - }
494.191 -
494.192 - private static class LogIH implements InvocationHandler {
494.193 - private final Object wrapped;
494.194 - Queue<LogRecord> log = new LinkedList<LogRecord>();
494.195 -
494.196 - LogIH(Object wrapped) {
494.197 - this.wrapped = wrapped;
494.198 - }
494.199 -
494.200 - public Object invoke(Object proxy, Method method, Object[] args)
494.201 - throws Throwable {
494.202 - if (method.getDeclaringClass() != Object.class) {
494.203 - LogRecord lr =
494.204 - new LogRecord(
494.205 - method.getName(), args, ClientContext.getContext());
494.206 - log.add(lr);
494.207 - }
494.208 - try {
494.209 - return method.invoke(wrapped, args);
494.210 - } catch (InvocationTargetException e) {
494.211 - throw e.getCause();
494.212 - }
494.213 - }
494.214 - }
494.215 -
494.216 - private static <T> T newSnoop(Class<T> wrappedClass, LogIH logIH) {
494.217 - return wrappedClass.cast(Proxy.newProxyInstance(
494.218 - wrappedClass.getClassLoader(),
494.219 - new Class<?>[] {wrappedClass},
494.220 - logIH));
494.221 - }
494.222 -
494.223 - public static void main(String[] args) throws Exception {
494.224 - final String subnamespace = "sub";
494.225 - final ObjectName locname = new ObjectName("a:b=c");
494.226 - final ObjectName name = JMXNamespaces.insertPath(subnamespace,locname);
494.227 - final MBeanServer mbs = ClientContext.newContextForwarder(
494.228 - ManagementFactory.getPlatformMBeanServer(), null);
494.229 - final MBeanServer sub = ClientContext.newContextForwarder(
494.230 - MBeanServerFactory.newMBeanServer(), null);
494.231 - final JMXServiceURL anonym = new JMXServiceURL("rmi",null,0);
494.232 - final Map<String, Object> env = Collections.emptyMap();
494.233 - final Map<String, String> emptyContext = Collections.emptyMap();
494.234 - final JMXConnectorServer srv =
494.235 - JMXConnectorServerFactory.newJMXConnectorServer(anonym,env,sub);
494.236 - sub.registerMBean(new ShowContext(), locname);
494.237 -
494.238 - srv.start();
494.239 -
494.240 - try {
494.241 - JMXRemoteNamespace subns = JMXRemoteNamespace.
494.242 - newJMXRemoteNamespace(srv.getAddress(),null);
494.243 - mbs.registerMBean(subns, JMXNamespaces.getNamespaceObjectName("sub"));
494.244 - mbs.invoke(JMXNamespaces.getNamespaceObjectName("sub"),
494.245 - "connect", null,null);
494.246 - final ShowContextMBean show =
494.247 - JMX.newMBeanProxy(mbs, name, ShowContextMBean.class);
494.248 -
494.249 - assertEquals(emptyContext, show.getContext());
494.250 - ClientContext.doWithContext(singletonMap("foo", "bar"), new Callable<Void>() {
494.251 - public Void call() {
494.252 - assertEquals(singletonMap("foo", "bar"), show.getContext());
494.253 - return null;
494.254 - }
494.255 - });
494.256 - assertEquals(emptyContext, show.getContext());
494.257 - String got = ClientContext.doWithContext(
494.258 - singletonMap("foo", "baz"), new Callable<String>() {
494.259 - public String call() {
494.260 - return ClientContext.getContext().get("foo");
494.261 - }
494.262 - });
494.263 - assertEquals("baz", got);
494.264 -
494.265 - Map<String, String> combined = ClientContext.doWithContext(
494.266 - singletonMap("foo", "baz"), new Callable<Map<String, String>>() {
494.267 - public Map<String, String> call() throws Exception {
494.268 - return ClientContext.doWithContext(
494.269 - singletonMap("fred", "jim"),
494.270 - new Callable<Map<String, String>>() {
494.271 - public Map<String, String> call() {
494.272 - return ClientContext.getContext();
494.273 - }
494.274 - });
494.275 - }
494.276 - });
494.277 - assertEquals(singletonMap("fred", "jim"), combined);
494.278 -
494.279 - final String ugh = "a!?//*=:\"% ";
494.280 - ClientContext.doWithContext(singletonMap(ugh, ugh), new Callable<Void>() {
494.281 - public Void call() {
494.282 - assertEquals(Collections.singletonMap(ugh, ugh),
494.283 - ClientContext.getContext());
494.284 - return null;
494.285 - }
494.286 - });
494.287 -
494.288 - // Basic withContext tests
494.289 -
494.290 - LogIH mbsIH = new LogIH(mbs);
494.291 - MBeanServer snoopMBS = newSnoop(MBeanServer.class, mbsIH);
494.292 - MBeanServer ughMBS = ClientContext.withContext(snoopMBS, ugh, ugh);
494.293 - // ughMBS is never referenced but we check that the withContext call
494.294 - // included a call to snoopMBS.isRegistered.
494.295 - String encodedUgh = URLEncoder.encode(ugh, "UTF-8").replace("*", "%2A");
494.296 - ObjectName expectedName = new ObjectName(
494.297 - ClientContext.NAMESPACE + ObjectName.NAMESPACE_SEPARATOR +
494.298 - encodedUgh + "=" + encodedUgh +
494.299 - ObjectName.NAMESPACE_SEPARATOR + ":" +
494.300 - JMXNamespace.TYPE_ASSIGNMENT);
494.301 - assertCalled(mbsIH, "isRegistered", new Object[] {expectedName},
494.302 - emptyContext);
494.303 -
494.304 - // Test withDynamicContext
494.305 -
494.306 - MBeanServerConnection dynamicSnoop =
494.307 - ClientContext.withDynamicContext(snoopMBS);
494.308 - assertCalled(mbsIH, "isRegistered",
494.309 - new Object[] {
494.310 - JMXNamespaces.getNamespaceObjectName(ClientContext.NAMESPACE)
494.311 - },
494.312 - emptyContext);
494.313 - final ShowContextMBean dynamicShow =
494.314 - JMX.newMBeanProxy(dynamicSnoop, name, ShowContextMBean.class);
494.315 - assertEquals(Collections.emptyMap(), dynamicShow.getContext());
494.316 - assertCalled(mbsIH, "getAttribute", new Object[] {name, "Context"},
494.317 - emptyContext);
494.318 -
494.319 - Map<String, String> expectedDynamic =
494.320 - Collections.singletonMap("gladstone", "gander");
494.321 - Map<String, String> dynamic = ClientContext.doWithContext(
494.322 - expectedDynamic,
494.323 - new Callable<Map<String, String>>() {
494.324 - public Map<String, String> call() throws Exception {
494.325 - return dynamicShow.getContext();
494.326 - }
494.327 - });
494.328 - assertEquals(expectedDynamic, dynamic);
494.329 - ObjectName expectedDynamicName = new ObjectName(
494.330 - ClientContext.encode(expectedDynamic) +
494.331 - ObjectName.NAMESPACE_SEPARATOR + name);
494.332 - assertCalled(mbsIH, "getAttribute",
494.333 - new Object[] {expectedDynamicName, "Context"}, dynamic);
494.334 -
494.335 - MBeanServer cmbs = ClientContext.withContext(
494.336 - mbs, "mickey", "mouse");
494.337 - ShowContextMBean cshow =
494.338 - JMX.newMBeanProxy(cmbs, name, ShowContextMBean.class);
494.339 - assertEquals(Collections.singletonMap("mickey", "mouse"), cshow.getContext());
494.340 -
494.341 - MBeanServer ccmbs = ClientContext.withContext(
494.342 - cmbs, "donald", "duck");
494.343 - ShowContextMBean ccshow =
494.344 - JMX.newMBeanProxy(ccmbs, name, ShowContextMBean.class);
494.345 - Map<String, String> disney = new HashMap<String, String>();
494.346 - disney.put("mickey", "mouse");
494.347 - disney.put("donald", "duck");
494.348 - assertEquals(disney, ccshow.getContext());
494.349 -
494.350 - // Test that all MBS ops produce reasonable results
494.351 -
494.352 - ObjectName logger = new ObjectName("a:type=Logger");
494.353 - DynamicMBean showMBean =
494.354 - new StandardMBean(new ShowContext(), ShowContextMBean.class);
494.355 - LogIH mbeanLogIH = new LogIH(showMBean);
494.356 - DynamicMBean logMBean = newSnoop(DynamicMBean.class, mbeanLogIH);
494.357 - ObjectInstance loggerOI = ccmbs.registerMBean(logMBean, logger);
494.358 - assertEquals(logger, loggerOI.getObjectName());
494.359 -
494.360 - // We get a getMBeanInfo call to determine the className in the
494.361 - // ObjectInstance to return from registerMBean.
494.362 - assertCalled(mbeanLogIH, "getMBeanInfo", disney);
494.363 -
494.364 - ccmbs.getAttribute(logger, "Thing");
494.365 - assertCalled(mbeanLogIH, "getAttribute", disney);
494.366 -
494.367 - ccmbs.getAttributes(logger, new String[] {"Thing", "Context"});
494.368 - assertCalled(mbeanLogIH, "getAttributes", disney);
494.369 -
494.370 - ccmbs.setAttribute(logger, new Attribute("Thing", "bar"));
494.371 - assertCalled(mbeanLogIH, "setAttribute", disney);
494.372 -
494.373 - ccmbs.setAttributes(logger, new AttributeList(
494.374 - Arrays.asList(new Attribute("Thing", "baz"))));
494.375 - assertCalled(mbeanLogIH, "setAttributes", disney);
494.376 -
494.377 - ccmbs.getMBeanInfo(logger);
494.378 - assertCalled(mbeanLogIH, "getMBeanInfo", disney);
494.379 -
494.380 - Set<ObjectName> names = ccmbs.queryNames(null, null);
494.381 - Set<ObjectName> expectedNames = new HashSet<ObjectName>(
494.382 - Collections.singleton(MBeanServerDelegate.DELEGATE_NAME));
494.383 - expectedNames.removeAll(names);
494.384 - assertEquals(0, expectedNames.size());
494.385 -
494.386 - Set<ObjectName> nsNames =
494.387 - ccmbs.queryNames(new ObjectName("**?*?//:*"), null);
494.388 - Set<ObjectName> expectedNsNames = new HashSet<ObjectName>(
494.389 - Arrays.asList(
494.390 - new ObjectName(ClientContext.NAMESPACE +
494.391 - ObjectName.NAMESPACE_SEPARATOR + ":" +
494.392 - JMXNamespace.TYPE_ASSIGNMENT)));
494.393 - expectedNsNames.removeAll(nsNames);
494.394 - assertEquals(0, expectedNsNames.size());
494.395 -
494.396 - Set<ObjectInstance> insts = ccmbs.queryMBeans(
494.397 - MBeanServerDelegate.DELEGATE_NAME, null);
494.398 - assertEquals(1, insts.size());
494.399 - assertEquals(MBeanServerDelegate.DELEGATE_NAME,
494.400 - insts.iterator().next().getObjectName());
494.401 -
494.402 - ObjectName createdName = new ObjectName("a:type=Created");
494.403 - ObjectInstance createdOI =
494.404 - ccmbs.createMBean(ShowContext.class.getName(), createdName);
494.405 - assertEquals(ShowContext.class.getName(), createdOI.getClassName());
494.406 - assertEquals(createdName, createdOI.getObjectName());
494.407 - assertEquals(disney, ccmbs.getAttribute(createdName, "CreationContext"));
494.408 -
494.409 - NotificationListener nothingListener = new NotificationListener() {
494.410 - public void handleNotification(Notification n, Object h) {}
494.411 - };
494.412 - ccmbs.addNotificationListener(createdName, nothingListener, null, null);
494.413 - ccmbs.removeNotificationListener(createdName, nothingListener, null, null);
494.414 - ccmbs.addNotificationListener(createdName, nothingListener, null, null);
494.415 - ccmbs.removeNotificationListener(createdName, nothingListener);
494.416 - Set<String> expectedOps = new HashSet<String>(Arrays.asList(
494.417 - "preRegister", "postRegister", "addNotificationListener",
494.418 - "removeNL1", "removeNL3", "getNotificationInfo"));
494.419 - assertEquals(expectedOps, ccmbs.getAttribute(createdName, "CalledOps"));
494.420 -
494.421 - assertEquals(ShowContext.class.getClassLoader(),
494.422 - ccmbs.getClassLoaderFor(createdName));
494.423 -
494.424 - assertEquals(true, ccmbs.isRegistered(createdName));
494.425 - assertEquals(true, ccmbs.isInstanceOf(createdName,
494.426 - ShowContext.class.getName()));
494.427 - assertEquals(false, ccmbs.isInstanceOf(createdName,
494.428 - DynamicMBean.class.getName()));
494.429 - ccmbs.unregisterMBean(createdName);
494.430 - assertEquals(false, ccmbs.isRegistered(createdName));
494.431 -
494.432 - MLet mlet = new MLet();
494.433 - ObjectName defaultMLetName = new ObjectName("DefaultDomain:type=MLet");
494.434 -
494.435 - ccmbs.registerMBean(mlet, defaultMLetName);
494.436 -
494.437 - assertEquals(mlet, ccmbs.getClassLoader(defaultMLetName));
494.438 -
494.439 - assertEquals(0, mbeanLogIH.log.size());
494.440 -
494.441 - // Test that contexts still work when we can't combine two encoded contexts.
494.442 - // Here, we wrap cmbs (mickey=mouse) so that ccmbs2 (donald=duck) cannot
494.443 - // see that it already contains a context and therefore cannot combine
494.444 - // into mickey=mouse;donald=duck. We don't actually use the snoop
494.445 - // capabilities of the returned object -- we just want an opaque
494.446 - // MBeanServer wrapper
494.447 - MBeanServer cmbs2 = newSnoop(MBeanServer.class, new LogIH(cmbs));
494.448 - MBeanServer ccmbs2 = ClientContext.withContext(cmbs2, "donald", "duck");
494.449 - assertEquals(disney, ccmbs2.getAttribute(name, "Context"));
494.450 -
494.451 - // ADD NEW TESTS HERE ^^^
494.452 -
494.453 - if (failure != null)
494.454 - throw new Exception(failure);
494.455 - } finally {
494.456 - srv.stop();
494.457 - }
494.458 - }
494.459 -
494.460 - private static void assertEquals(Object x, Object y) {
494.461 - if (!equal(x, y))
494.462 - failed("expected " + string(x) + "; got " + string(y));
494.463 - }
494.464 -
494.465 - private static boolean equal(Object x, Object y) {
494.466 - if (x == y)
494.467 - return true;
494.468 - if (x == null || y == null)
494.469 - return false;
494.470 - if (x.getClass().isArray())
494.471 - return Arrays.deepEquals(new Object[] {x}, new Object[] {y});
494.472 - return x.equals(y);
494.473 - }
494.474 -
494.475 - private static String string(Object x) {
494.476 - String s = Arrays.deepToString(new Object[] {x});
494.477 - return s.substring(1, s.length() - 1);
494.478 - }
494.479 -
494.480 - private static void assertCalled(
494.481 - LogIH logIH, String op, Map<String, String> expectedContext) {
494.482 - assertCalled(logIH, op, null, expectedContext);
494.483 - }
494.484 -
494.485 - private static void assertCalled(
494.486 - LogIH logIH, String op, Object[] params,
494.487 - Map<String, String> expectedContext) {
494.488 - LogRecord lr = logIH.log.remove();
494.489 - assertEquals(op, lr.op);
494.490 - if (params != null)
494.491 - assertEquals(params, lr.params);
494.492 - assertEquals(expectedContext, lr.context);
494.493 - }
494.494 -
494.495 - private static void failed(String why) {
494.496 - failure = why;
494.497 - new Throwable("FAILED: " + why).printStackTrace(System.out);
494.498 - }
494.499 -}
495.1 --- a/test/javax/management/context/localizable/MBeanDescriptions.properties Mon Nov 23 10:04:47 2009 +0000
495.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
495.3 @@ -1,9 +0,0 @@
495.4 -# This is the default description ResourceBundle for MBeans in this package.
495.5 -# Resources here override the descriptions specified with @Description
495.6 -# but only when localization is happening and when there is not a more
495.7 -# specific resource for the description (for example from MBeanDescriptions_fr).
495.8 -
495.9 -WhatsitMBean.mbean = A whatsit
495.10 -# This must be the same as WhatsitMBean.englishMBeanDescription for the
495.11 -# purposes of this test.
495.12 -
496.1 --- a/test/javax/management/context/localizable/MBeanDescriptions_fr.java Mon Nov 23 10:04:47 2009 +0000
496.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
496.3 @@ -1,42 +0,0 @@
496.4 -/*
496.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
496.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
496.7 - *
496.8 - * This code is free software; you can redistribute it and/or modify it
496.9 - * under the terms of the GNU General Public License version 2 only, as
496.10 - * published by the Free Software Foundation.
496.11 - *
496.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
496.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
496.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
496.15 - * version 2 for more details (a copy is included in the LICENSE file that
496.16 - * accompanied this code).
496.17 - *
496.18 - * You should have received a copy of the GNU General Public License version
496.19 - * 2 along with this work; if not, write to the Free Software Foundation,
496.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
496.21 - *
496.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
496.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
496.24 - * have any questions.
496.25 - */
496.26 -
496.27 -package localizable;
496.28 -
496.29 -import java.util.ListResourceBundle;
496.30 -import static localizable.WhatsitMBean.*;
496.31 -
496.32 -public class MBeanDescriptions_fr extends ListResourceBundle {
496.33 - @Override
496.34 - protected Object[][] getContents() {
496.35 - String constrProp = "WhatsitMBean.constructor." + Whatsit.class.getName();
496.36 - return new Object[][] {
496.37 - {"WhatsitMBean.mbean", frenchMBeanDescription},
496.38 - {"WhatsitMBean.attribute.Whatsit", frenchAttrDescription},
496.39 - {"WhatsitMBean.operation.frob", frenchOperDescription},
496.40 - {"WhatsitMBean.operation.frob.p1", frenchParamDescription},
496.41 - {constrProp, frenchConstrDescription},
496.42 - {constrProp + ".p1", frenchConstrParamDescription},
496.43 - };
496.44 - }
496.45 -}
497.1 --- a/test/javax/management/context/localizable/Whatsit.java Mon Nov 23 10:04:47 2009 +0000
497.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
497.3 @@ -1,59 +0,0 @@
497.4 -/*
497.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
497.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
497.7 - *
497.8 - * This code is free software; you can redistribute it and/or modify it
497.9 - * under the terms of the GNU General Public License version 2 only, as
497.10 - * published by the Free Software Foundation.
497.11 - *
497.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
497.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
497.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
497.15 - * version 2 for more details (a copy is included in the LICENSE file that
497.16 - * accompanied this code).
497.17 - *
497.18 - * You should have received a copy of the GNU General Public License version
497.19 - * 2 along with this work; if not, write to the Free Software Foundation,
497.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
497.21 - *
497.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
497.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
497.24 - * have any questions.
497.25 - */
497.26 -
497.27 -package localizable;
497.28 -
497.29 -import javax.management.Description;
497.30 -
497.31 -public class Whatsit implements WhatsitMBean {
497.32 - /**
497.33 - * Attribute : NewAttribute0
497.34 - */
497.35 - private String newAttribute0;
497.36 - @Description(englishConstrDescription)
497.37 - public Whatsit() {}
497.38 -
497.39 - @Description(englishConstrDescription)
497.40 - public Whatsit(@Description(englishConstrParamDescription) int type) {}
497.41 -
497.42 - public String getWhatsit() {
497.43 - return "whatsit";
497.44 - }
497.45 -
497.46 - public void frob(String whatsit) {
497.47 - }
497.48 -
497.49 - /**
497.50 - * Get Tiddly
497.51 - */
497.52 - public String getNewAttribute0() {
497.53 - return newAttribute0;
497.54 - }
497.55 -
497.56 - /**
497.57 - * Set Tiddly
497.58 - */
497.59 - public void setNewAttribute0(String value) {
497.60 - newAttribute0 = value;
497.61 - }
497.62 -}
498.1 --- a/test/javax/management/context/localizable/WhatsitMBean.java Mon Nov 23 10:04:47 2009 +0000
498.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
498.3 @@ -1,53 +0,0 @@
498.4 -/*
498.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
498.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
498.7 - *
498.8 - * This code is free software; you can redistribute it and/or modify it
498.9 - * under the terms of the GNU General Public License version 2 only, as
498.10 - * published by the Free Software Foundation.
498.11 - *
498.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
498.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
498.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
498.15 - * version 2 for more details (a copy is included in the LICENSE file that
498.16 - * accompanied this code).
498.17 - *
498.18 - * You should have received a copy of the GNU General Public License version
498.19 - * 2 along with this work; if not, write to the Free Software Foundation,
498.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
498.21 - *
498.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
498.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
498.24 - * have any questions.
498.25 - */
498.26 -
498.27 -package localizable;
498.28 -
498.29 -import javax.management.Description;
498.30 -
498.31 -@Description(WhatsitMBean.defaultMBeanDescription)
498.32 -public interface WhatsitMBean {
498.33 - public static final String
498.34 - defaultMBeanDescription = "Default whatsit MBean description",
498.35 - englishMBeanDescription = "A whatsit",
498.36 - // Previous description appears in MBeanDescriptions.properties
498.37 - // so it overrides the @Description when that file is used.
498.38 - frenchMBeanDescription = "Un bidule",
498.39 - englishAttrDescription = "The whatsit",
498.40 - frenchAttrDescription = "Le bidule",
498.41 - englishOperDescription = "Frob the whatsit",
498.42 - frenchOperDescription = "Frober le bidule",
498.43 - englishParamDescription = "The whatsit to frob",
498.44 - frenchParamDescription = "Le bidule \u00e0 frober",
498.45 - englishConstrDescription = "Make a whatsit",
498.46 - frenchConstrDescription = "Fabriquer un bidule",
498.47 - englishConstrParamDescription = "Type of whatsit to make",
498.48 - frenchConstrParamDescription = "Type de bidule \u00e0 fabriquer",
498.49 - unlocalizedMBeanDescription = "Unlocalized MBean";
498.50 -
498.51 - @Description(englishAttrDescription)
498.52 - public String getWhatsit();
498.53 -
498.54 - @Description(englishOperDescription)
498.55 - public void frob(@Description(englishParamDescription) String whatsit);
498.56 -}
499.1 --- a/test/javax/management/descriptor/DescriptorConstructorTest.java Mon Nov 23 10:04:47 2009 +0000
499.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
499.3 @@ -1,46 +0,0 @@
499.4 -/*
499.5 - * Copyright 2004-2005 Sun Microsystems, Inc. All Rights Reserved.
499.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
499.7 - *
499.8 - * This code is free software; you can redistribute it and/or modify it
499.9 - * under the terms of the GNU General Public License version 2 only, as
499.10 - * published by the Free Software Foundation.
499.11 - *
499.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
499.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
499.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
499.15 - * version 2 for more details (a copy is included in the LICENSE file that
499.16 - * accompanied this code).
499.17 - *
499.18 - * You should have received a copy of the GNU General Public License version
499.19 - * 2 along with this work; if not, write to the Free Software Foundation,
499.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
499.21 - *
499.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
499.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
499.24 - * have any questions.
499.25 - */
499.26 -
499.27 -/*
499.28 - * @test
499.29 - * @bug 6501362
499.30 - * @summary DescriptorSupport(String) could recognize "name=value" as well as XML format
499.31 - * @author Jean-Francois Denise
499.32 - * @run clean DescriptorConstructorTest
499.33 - * @run build DescriptorConstructorTest
499.34 - * @run main DescriptorConstructorTest
499.35 - */
499.36 -
499.37 -import javax.management.modelmbean.DescriptorSupport;
499.38 -
499.39 -public class DescriptorConstructorTest {
499.40 - public static void main(String[] args) throws Exception {
499.41 - DescriptorSupport d1 = new DescriptorSupport("MyName1=MyValue1");
499.42 - if(!d1.getFieldValue("MyName1").equals("MyValue1"))
499.43 - throw new Exception("Invalid parsing");
499.44 - DescriptorSupport d2 = new DescriptorSupport("<Descriptor>" +
499.45 - "<field name=\"MyName2\" value=\"MyValue2\"></field></Descriptor>");
499.46 - if(!d2.getFieldValue("MyName2").equals("MyValue2"))
499.47 - throw new Exception("Invalid parsing");
499.48 - }
499.49 -}
500.1 --- a/test/javax/management/eventService/AddRemoveListenerTest.java Mon Nov 23 10:04:47 2009 +0000
500.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
500.3 @@ -1,371 +0,0 @@
500.4 -/*
500.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
500.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
500.7 - *
500.8 - * This code is free software; you can redistribute it and/or modify it
500.9 - * under the terms of the GNU General Public License version 2 only, as
500.10 - * published by the Free Software Foundation.
500.11 - *
500.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
500.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
500.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
500.15 - * version 2 for more details (a copy is included in the LICENSE file that
500.16 - * accompanied this code).
500.17 - *
500.18 - * You should have received a copy of the GNU General Public License version
500.19 - * 2 along with this work; if not, write to the Free Software Foundation,
500.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
500.21 - *
500.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
500.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
500.24 - * have any questions.
500.25 - */
500.26 -
500.27 -/*
500.28 - * @test AddRemoveListenerTest.java
500.29 - * @bug 5108776
500.30 - * @summary Basic test for EventClient to see internal thread management.
500.31 - * @author Shanliang JIANG
500.32 - * @run clean AddRemoveListenerTest
500.33 - * @run build AddRemoveListenerTest
500.34 - * @run main AddRemoveListenerTest
500.35 - */
500.36 -
500.37 -import java.io.IOException;
500.38 -import javax.management.MBeanServer;
500.39 -import javax.management.MBeanServerFactory;
500.40 -import javax.management.Notification;
500.41 -import javax.management.NotificationBroadcasterSupport;
500.42 -import javax.management.NotificationFilter;
500.43 -import javax.management.NotificationListener;
500.44 -import javax.management.ObjectName;
500.45 -import javax.management.event.EventClient;
500.46 -import javax.management.event.EventClientDelegate;
500.47 -import javax.management.event.EventClientDelegateMBean;
500.48 -import javax.management.event.FetchingEventRelay;
500.49 -import javax.management.event.RMIPushEventRelay;
500.50 -import javax.management.remote.JMXConnector;
500.51 -import javax.management.remote.JMXConnectorFactory;
500.52 -import javax.management.remote.JMXConnectorServer;
500.53 -import javax.management.remote.JMXConnectorServerFactory;
500.54 -import javax.management.remote.JMXServiceURL;
500.55 -
500.56 -
500.57 -// This thread creates a single MBean that emits a number of parallel
500.58 -// sequences of notifications. Each sequence is distinguished by an id
500.59 -// and each id corresponds to a thread that is filtering the notifications
500.60 -// so it only sees its own ones. The notifications for a given id have
500.61 -// contiguous sequence numbers and each thread checks that the notifications
500.62 -// it receives do indeed have these numbers. If notifications are lost or
500.63 -// if the different sequences interfere with each other then the test will
500.64 -// fail. As an added tweak, a "noise" thread periodically causes notifications
500.65 -// to be emitted that do not correspond to any sequence and do not have any id.
500.66 -public class AddRemoveListenerTest {
500.67 -
500.68 - private static MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer();
500.69 - private static ObjectName emitter;
500.70 - private static NotificationSender emitterImpl;
500.71 - private static JMXServiceURL url;
500.72 - private static JMXConnectorServer server;
500.73 -
500.74 - private static int toSend = 100;
500.75 - private static final long bigWaiting = 10000;
500.76 - private static int counter = 0;
500.77 - private static int jobs = 10;
500.78 - private static int endedJobs = 0;
500.79 -
500.80 - private static volatile String failure;
500.81 -
500.82 - public static void main(String[] args) throws Exception {
500.83 - System.out.println(">>> Test on multiple adding/removing listeners.");
500.84 -
500.85 - // for 1.5
500.86 - if (System.getProperty("java.version").startsWith("1.5") &&
500.87 - !mbeanServer.isRegistered(EventClientDelegateMBean.OBJECT_NAME)) {
500.88 - System.out.print("Working on "+System.getProperty("java.version")+
500.89 - " register "+EventClientDelegateMBean.OBJECT_NAME);
500.90 -
500.91 - mbeanServer.registerMBean(EventClientDelegate.
500.92 - getEventClientDelegate(mbeanServer),
500.93 - EventClientDelegateMBean.OBJECT_NAME);
500.94 - }
500.95 -
500.96 - emitter = new ObjectName("Default:name=NotificationSender");
500.97 - emitterImpl = new NotificationSender();
500.98 - mbeanServer.registerMBean(emitterImpl, emitter);
500.99 -
500.100 - String[] types = new String[]{"PushEventRelay", "FetchingEventRelay"};
500.101 - String[] protos = new String[]{"rmi", "iiop", "jmxmp"};
500.102 - for (String prot : protos) {
500.103 - url = new JMXServiceURL(prot, null, 0);
500.104 -
500.105 - try {
500.106 - server =
500.107 - JMXConnectorServerFactory.newJMXConnectorServer(url,
500.108 - null, mbeanServer);
500.109 - server.start();
500.110 - } catch (Exception e) {
500.111 - System.out.println(">>> Skip "+prot+", not supported.");
500.112 - continue;
500.113 - }
500.114 -
500.115 - url = server.getAddress();
500.116 -
500.117 - // noise
500.118 - Thread noise = new Thread(new Runnable() {
500.119 - public void run() {
500.120 - while (true) {
500.121 - emitterImpl.sendNotif(1, null);
500.122 - try {
500.123 - Thread.sleep(10);
500.124 - } catch (Exception e) {
500.125 - // OK
500.126 - }
500.127 - }
500.128 - }
500.129 - });
500.130 - noise.setDaemon(true);
500.131 - noise.start();
500.132 -
500.133 - try {
500.134 - for (String type: types) {
500.135 - System.out.println("\n\n>>> Testing "+type+" on "+url+" ...");
500.136 - JMXConnector conn = newConn();
500.137 - try {
500.138 - testType(type, conn);
500.139 - } finally {
500.140 - conn.close();
500.141 - System.out.println(">>> Testing "+type+" on "+url+" ... done");
500.142 - }
500.143 - }
500.144 - } finally {
500.145 - server.stop();
500.146 - }
500.147 - }
500.148 - }
500.149 -
500.150 - private static void testType(String type, JMXConnector conn) throws Exception {
500.151 - Thread[] threads = new Thread[jobs];
500.152 - for (int i=0; i<jobs; i++) {
500.153 - threads[i] = new Thread(new Job(type, conn));
500.154 - threads[i].setDaemon(true);
500.155 - threads[i].start();
500.156 - }
500.157 -
500.158 - // to wait
500.159 - long toWait = bigWaiting*jobs;
500.160 - long stopTime = System.currentTimeMillis() + toWait;
500.161 -
500.162 - synchronized(AddRemoveListenerTest.class) {
500.163 - while (endedJobs < jobs && toWait > 0 && failure == null) {
500.164 - AddRemoveListenerTest.class.wait(toWait);
500.165 - toWait = stopTime - System.currentTimeMillis();
500.166 - }
500.167 - }
500.168 -
500.169 - if (endedJobs != jobs && failure == null) {
500.170 - throw new RuntimeException("Need to set bigger waiting timeout?");
500.171 - }
500.172 -
500.173 - endedJobs = 0;
500.174 - }
500.175 -
500.176 - public static class Job implements Runnable {
500.177 - public Job(String type, JMXConnector conn) {
500.178 - this.type = type;
500.179 - this.conn = conn;
500.180 - }
500.181 - public void run() {
500.182 - try {
500.183 - test(type, conn);
500.184 -
500.185 - synchronized(AddRemoveListenerTest.class) {
500.186 - endedJobs++;
500.187 - if (endedJobs>=jobs) {
500.188 - AddRemoveListenerTest.class.notify();
500.189 - }
500.190 - }
500.191 - } catch (RuntimeException re) {
500.192 - throw re;
500.193 - } catch (Exception e) {
500.194 - throw new RuntimeException(e);
500.195 - }
500.196 - }
500.197 -
500.198 - private final String type;
500.199 - private final JMXConnector conn;
500.200 - }
500.201 -
500.202 - private static void test(String type, JMXConnector conn) throws Exception {
500.203 - EventClient ec = newEventClient(type, conn);
500.204 - try {
500.205 - test(type, conn, ec);
500.206 - } finally {
500.207 - ec.close();
500.208 - }
500.209 - }
500.210 -
500.211 - private static void test(String type, JMXConnector conn, EventClient ec)
500.212 - throws Exception {
500.213 - String id = getId();
500.214 -
500.215 - Listener listener = new Listener(id);
500.216 - Filter filter = new Filter(id);
500.217 -
500.218 - System.out.println(">>> ("+id+") To receive notifications "+toSend);
500.219 - ec.addNotificationListener(emitter,
500.220 - listener, filter, null);
500.221 -
500.222 - emitterImpl.sendNotif(toSend, id);
500.223 - listener.waitNotifs(bigWaiting, toSend);
500.224 - if (listener.received != toSend) {
500.225 - throw new RuntimeException(">>> ("+id+") Expected to receive: "
500.226 - +toSend+", but got: "+listener.received);
500.227 - }
500.228 -
500.229 - listener.clear();
500.230 - ec.removeNotificationListener(emitter, listener, filter, null);
500.231 -
500.232 - System.out.println(">>> ("+id+") Repeat adding and removing ...");
500.233 - for (int j=0; j<10; j++) {
500.234 - ec.addNotificationListener(emitter, dummyListener, null, id);
500.235 - Thread.yield(); // allow to start listening
500.236 - ec.removeNotificationListener(emitter, dummyListener, null, id);
500.237 - }
500.238 -
500.239 - System.out.println(">>> ("+id+") To receive again notifications "+toSend);
500.240 - ec.addNotificationListener(emitter,
500.241 - listener, filter, null);
500.242 -
500.243 - emitterImpl.sendNotif(toSend, id);
500.244 - listener.waitNotifs(bigWaiting, toSend);
500.245 - Thread.yield(); //any duplicated?
500.246 - if (listener.received != toSend) {
500.247 - throw new RuntimeException("("+id+") Expected to receive: "
500.248 - +toSend+", but got: "+listener.received);
500.249 - }
500.250 - }
500.251 -
500.252 -//--------------------------
500.253 -// private classes
500.254 -//--------------------------
500.255 -
500.256 - private static class Listener implements NotificationListener {
500.257 - public Listener(String id) {
500.258 - this.id = id;
500.259 - }
500.260 - public void handleNotification(Notification notif, Object handback) {
500.261 - if (!id.equals(notif.getUserData())) {
500.262 - System.out.println("("+id+") Filter error, my id is: "+id+
500.263 - ", but got "+notif.getUserData());
500.264 - System.exit(1);
500.265 - }
500.266 -
500.267 - synchronized (this) {
500.268 - received++;
500.269 -
500.270 - if(++sequenceNB != notif.getSequenceNumber()) {
500.271 - fail("(" + id + ") Wrong sequence number, expected: "
500.272 - +sequenceNB+", but got: "+notif.getSequenceNumber());
500.273 - }
500.274 - if (received >= toSend || failure != null) {
500.275 - this.notify();
500.276 - }
500.277 - }
500.278 - }
500.279 -
500.280 - public void waitNotifs(long timeout, int nb) throws Exception {
500.281 - long toWait = timeout;
500.282 - long stopTime = System.currentTimeMillis() + timeout;
500.283 - synchronized(this) {
500.284 - while (received < nb && toWait > 0 && failure == null) {
500.285 - this.wait(toWait);
500.286 - toWait = stopTime - System.currentTimeMillis();
500.287 - }
500.288 - }
500.289 - }
500.290 -
500.291 - public void clear() {
500.292 - synchronized(this) {
500.293 - received = 0;
500.294 - sequenceNB = -1;
500.295 - }
500.296 - }
500.297 -
500.298 - private String id;
500.299 - private int received = 0;
500.300 -
500.301 - private long sequenceNB = -1;
500.302 - }
500.303 -
500.304 - private static class Filter implements NotificationFilter {
500.305 - public Filter(String id) {
500.306 - this.id = id;
500.307 - }
500.308 -
500.309 - public boolean isNotificationEnabled(Notification n) {
500.310 - return id.equals(n.getUserData());
500.311 - }
500.312 - private String id;
500.313 - }
500.314 -
500.315 - private static NotificationListener dummyListener = new NotificationListener() {
500.316 - public void handleNotification(Notification notif, Object handback) {
500.317 - }
500.318 - };
500.319 -
500.320 - public static class NotificationSender extends NotificationBroadcasterSupport
500.321 - implements NotificationSenderMBean {
500.322 -
500.323 - /**
500.324 - * Send Notification objects.
500.325 - *
500.326 - * @param nb The number of notifications to send
500.327 - */
500.328 - public void sendNotif(int nb, String userData) {
500.329 - long sequenceNumber = 0;
500.330 - for (int i = 0; i<nb; i++) {
500.331 - Notification notif = new Notification(myType, this, sequenceNumber++);
500.332 - notif.setUserData(userData);
500.333 - sendNotification(notif);
500.334 - }
500.335 - }
500.336 -
500.337 -
500.338 - private final String myType = "notification.my_notification";
500.339 - }
500.340 -
500.341 - public interface NotificationSenderMBean {
500.342 - public void sendNotif(int nb, String userData);
500.343 - }
500.344 -
500.345 - private static JMXConnector newConn() throws IOException {
500.346 - return JMXConnectorFactory.connect(url);
500.347 - }
500.348 -
500.349 - private static EventClient newEventClient(String type, JMXConnector conn)
500.350 - throws Exception {
500.351 - EventClientDelegateMBean proxy =
500.352 - EventClientDelegate.getProxy(conn.getMBeanServerConnection());
500.353 - if (type.equals("PushEventRelay")) {
500.354 - return new EventClient(proxy,
500.355 - new RMIPushEventRelay(proxy), null, null, 60000);
500.356 - } else if (type.equals("FetchingEventRelay")) {
500.357 - return new EventClient(proxy,
500.358 - new FetchingEventRelay(proxy), null, null, 60000);
500.359 - } else {
500.360 - throw new RuntimeException("Wrong event client type: "+type);
500.361 - }
500.362 - }
500.363 -
500.364 - private static String getId() {
500.365 - synchronized(AddRemoveListenerTest.class) {
500.366 - return String.valueOf(counter++);
500.367 - }
500.368 - }
500.369 -
500.370 - private static void fail(String msg) {
500.371 - System.out.println("FAIL: " + msg);
500.372 - failure = msg;
500.373 - }
500.374 -}
501.1 --- a/test/javax/management/eventService/CustomForwarderTest.java Mon Nov 23 10:04:47 2009 +0000
501.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
501.3 @@ -1,395 +0,0 @@
501.4 -/*
501.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
501.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
501.7 - *
501.8 - * This code is free software; you can redistribute it and/or modify it
501.9 - * under the terms of the GNU General Public License version 2 only, as
501.10 - * published by the Free Software Foundation.
501.11 - *
501.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
501.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
501.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
501.15 - * version 2 for more details (a copy is included in the LICENSE file that
501.16 - * accompanied this code).
501.17 - *
501.18 - * You should have received a copy of the GNU General Public License version
501.19 - * 2 along with this work; if not, write to the Free Software Foundation,
501.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
501.21 - *
501.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
501.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
501.24 - * have any questions.
501.25 - */
501.26 -
501.27 -/*
501.28 - * @test CustomForwarderTest
501.29 - * @bug 5108776 6759619
501.30 - * @summary Test that a custom EventForwarder can be added
501.31 - * @author Eamonn McManus
501.32 - */
501.33 -
501.34 -import java.io.ByteArrayInputStream;
501.35 -import java.io.ByteArrayOutputStream;
501.36 -import java.io.IOException;
501.37 -import java.io.ObjectInputStream;
501.38 -import java.io.ObjectOutputStream;
501.39 -import java.lang.management.ManagementFactory;
501.40 -import java.net.DatagramPacket;
501.41 -import java.net.DatagramSocket;
501.42 -import java.net.SocketAddress;
501.43 -import java.util.Map;
501.44 -import java.util.concurrent.ArrayBlockingQueue;
501.45 -import java.util.concurrent.BlockingQueue;
501.46 -import java.util.concurrent.Semaphore;
501.47 -import java.util.concurrent.TimeUnit;
501.48 -import java.util.concurrent.atomic.AtomicBoolean;
501.49 -import java.util.concurrent.atomic.AtomicInteger;
501.50 -import java.util.concurrent.atomic.AtomicLong;
501.51 -import javax.management.MBeanNotificationInfo;
501.52 -import javax.management.MBeanServer;
501.53 -import javax.management.MBeanServerInvocationHandler;
501.54 -import javax.management.Notification;
501.55 -import javax.management.NotificationBroadcasterSupport;
501.56 -import javax.management.NotificationFilter;
501.57 -import javax.management.NotificationListener;
501.58 -import javax.management.ObjectName;
501.59 -import javax.management.event.EventClient;
501.60 -import javax.management.event.EventClientDelegate;
501.61 -import javax.management.event.EventClientDelegateMBean;
501.62 -import javax.management.event.EventForwarder;
501.63 -import javax.management.event.EventReceiver;
501.64 -import javax.management.event.EventRelay;
501.65 -import javax.management.remote.MBeanServerForwarder;
501.66 -import javax.management.remote.NotificationResult;
501.67 -import javax.management.remote.TargetedNotification;
501.68 -
501.69 -public class CustomForwarderTest {
501.70 - public static class UdpEventRelay implements EventRelay {
501.71 - private final EventClientDelegateMBean delegate;
501.72 - private final DatagramSocket socket;
501.73 - private final AtomicBoolean closed = new AtomicBoolean();
501.74 - private final String clientId;
501.75 - private EventReceiver receiver;
501.76 -
501.77 - public UdpEventRelay(EventClientDelegateMBean delegate)
501.78 - throws IOException {
501.79 - this.delegate = delegate;
501.80 - this.socket = new DatagramSocket();
501.81 - try {
501.82 - clientId = delegate.addClient(
501.83 - UdpEventForwarder.class.getName(),
501.84 - new Object[] {socket.getLocalSocketAddress()},
501.85 - new String[] {SocketAddress.class.getName()});
501.86 - } catch (IOException e) {
501.87 - throw e;
501.88 - } catch (RuntimeException e) {
501.89 - throw e;
501.90 - } catch (Exception e) {
501.91 - final IOException ioe =
501.92 - new IOException("Exception creating EventForwarder");
501.93 - ioe.initCause(e);
501.94 - throw ioe;
501.95 - }
501.96 - Thread t = new Thread(new Receiver());
501.97 - t.setDaemon(true);
501.98 - t.start();
501.99 - }
501.100 -
501.101 - public String getClientId() throws IOException {
501.102 - return clientId;
501.103 - }
501.104 -
501.105 - public void setEventReceiver(EventReceiver eventReceiver) {
501.106 - this.receiver = eventReceiver;
501.107 - }
501.108 -
501.109 - public void stop() throws IOException {
501.110 - closed.set(true);
501.111 - socket.close();
501.112 - }
501.113 -
501.114 - void simulateNonFatal() {
501.115 - receiver.nonFatal(new Exception("NonFatal"));
501.116 - }
501.117 -
501.118 - void simulateFailed() {
501.119 - receiver.failed(new Error("Failed"));
501.120 - }
501.121 -
501.122 - private class Receiver implements Runnable {
501.123 - public void run() {
501.124 - byte[] buf = new byte[1024];
501.125 - DatagramPacket packet = new DatagramPacket(buf, buf.length);
501.126 - while (true) {
501.127 - try {
501.128 - socket.receive(packet);
501.129 - } catch (IOException e) {
501.130 - if (closed.get()) {
501.131 - System.out.println("Receiver got exception: " + e);
501.132 - System.out.println("Normal because it has been closed");
501.133 - return;
501.134 - } else {
501.135 - System.err.println("UNEXPECTED EXCEPTION IN RECEIVER:");
501.136 - e.printStackTrace();
501.137 - System.exit(1);
501.138 - }
501.139 - }
501.140 - try {
501.141 - ByteArrayInputStream bin = new ByteArrayInputStream(buf);
501.142 - ObjectInputStream oin = new ObjectInputStream(bin);
501.143 - NotificationResult nr = (NotificationResult)
501.144 - oin.readObject();
501.145 - receiver.receive(nr);
501.146 - } catch (Exception e) {
501.147 - System.err.println("UNEXPECTED EXCEPTION IN RECEIVER:");
501.148 - e.printStackTrace();
501.149 - System.exit(1);
501.150 - }
501.151 - }
501.152 - }
501.153 - }
501.154 - }
501.155 -
501.156 - public static class UdpEventForwarder implements EventForwarder {
501.157 - private final DatagramSocket socket;
501.158 - private final AtomicLong seqNo = new AtomicLong(0);
501.159 - private static volatile boolean drop;
501.160 -
501.161 - public UdpEventForwarder(SocketAddress addr) throws IOException {
501.162 - this.socket = new DatagramSocket();
501.163 - socket.connect(addr);
501.164 - }
501.165 -
501.166 - public static void setDrop(boolean drop) {
501.167 - UdpEventForwarder.drop = drop;
501.168 - }
501.169 -
501.170 - public void forward(Notification n, Integer listenerId) throws IOException {
501.171 - long nextSeqNo = seqNo.incrementAndGet();
501.172 - long thisSeqNo = nextSeqNo - 1;
501.173 - TargetedNotification tn = new TargetedNotification(n, listenerId);
501.174 - NotificationResult nr = new NotificationResult(
501.175 - thisSeqNo, nextSeqNo, new TargetedNotification[] {tn});
501.176 - ByteArrayOutputStream bout = new ByteArrayOutputStream();
501.177 - ObjectOutputStream oout = new ObjectOutputStream(bout);
501.178 - oout.writeObject(nr);
501.179 - oout.close();
501.180 - byte[] bytes = bout.toByteArray();
501.181 - DatagramPacket packet = new DatagramPacket(bytes, bytes.length);
501.182 - if (!drop)
501.183 - socket.send(packet);
501.184 - }
501.185 -
501.186 - public void close() throws IOException {
501.187 - socket.close();
501.188 - }
501.189 -
501.190 - public void setClientId(String clientId) throws IOException {
501.191 - // Nothing to do.
501.192 - }
501.193 - }
501.194 -
501.195 - public static interface EmptyMBean {}
501.196 -
501.197 - public static class Empty
501.198 - extends NotificationBroadcasterSupport implements EmptyMBean {
501.199 - public void send(Notification n) {
501.200 - super.sendNotification(n);
501.201 - }
501.202 - }
501.203 -
501.204 - public static void main(String[] args) throws Exception {
501.205 - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
501.206 - MBeanServerForwarder mbsf = EventClientDelegate.newForwarder(mbs, null);
501.207 - mbs = mbsf;
501.208 -
501.209 - // for 1.5
501.210 - if (System.getProperty("java.version").startsWith("1.5") &&
501.211 - !mbs.isRegistered(EventClientDelegateMBean.OBJECT_NAME)) {
501.212 - System.out.print("Working on "+System.getProperty("java.version")+
501.213 - " register "+EventClientDelegateMBean.OBJECT_NAME);
501.214 -
501.215 - mbs.registerMBean(EventClientDelegate.
501.216 - getEventClientDelegate(mbs),
501.217 - EventClientDelegateMBean.OBJECT_NAME);
501.218 - }
501.219 -
501.220 - ObjectName name = new ObjectName("a:b=c");
501.221 - Empty mbean = new Empty();
501.222 - mbs.registerMBean(mbean, name);
501.223 -
501.224 - EventClientDelegateMBean delegate = (EventClientDelegateMBean)
501.225 - MBeanServerInvocationHandler.newProxyInstance(
501.226 - mbs,
501.227 - EventClientDelegateMBean.OBJECT_NAME,
501.228 - EventClientDelegateMBean.class,
501.229 - false);
501.230 - UdpEventRelay relay = new UdpEventRelay(delegate);
501.231 - EventClient client = new EventClient(delegate, relay, null, null, 0L);
501.232 -
501.233 - final Semaphore lostCountSema = new Semaphore(0);
501.234 - final BlockingQueue<Notification> nonFatalNotifs =
501.235 - new ArrayBlockingQueue<Notification>(1);
501.236 - final BlockingQueue<Notification> failedNotifs =
501.237 - new ArrayBlockingQueue<Notification>(1);
501.238 - NotificationListener lostListener = new NotificationListener() {
501.239 - public void handleNotification(Notification notification, Object handback) {
501.240 - if (notification.getType().equals(EventClient.NOTIFS_LOST)) {
501.241 - System.out.println("Got lost-notifs notif: count=" +
501.242 - notification.getUserData());
501.243 - lostCountSema.release(((Long) notification.getUserData()).intValue());
501.244 - } else if (notification.getType().equals(EventClient.NONFATAL)) {
501.245 - System.out.println("Got nonFatal notif");
501.246 - nonFatalNotifs.add(notification);
501.247 - } else if (notification.getType().equals(EventClient.FAILED)) {
501.248 - System.out.println("Got failed notif");
501.249 - failedNotifs.add(notification);
501.250 - } else
501.251 - System.out.println("Mysterious EventClient notif: " + notification);
501.252 - }
501.253 - };
501.254 - client.addEventClientListener(lostListener, null, null);
501.255 -
501.256 - final BlockingQueue<Notification> notifQueue =
501.257 - new ArrayBlockingQueue<Notification>(10);
501.258 - NotificationListener countListener = new NotificationListener() {
501.259 - public void handleNotification(Notification notification, Object handback) {
501.260 - System.out.println("Received: " + notification);
501.261 - notifQueue.add(notification);
501.262 - if (!"tiddly".equals(handback)) {
501.263 - System.err.println("TEST FAILED: bad handback: " + handback);
501.264 - System.exit(1);
501.265 - }
501.266 - }
501.267 - };
501.268 -
501.269 - final AtomicInteger filterCount = new AtomicInteger(0);
501.270 - NotificationFilter countFilter = new NotificationFilter() {
501.271 - private static final long serialVersionUID = 1234L;
501.272 -
501.273 - public boolean isNotificationEnabled(Notification notification) {
501.274 - System.out.println("Filter called for: " + notification);
501.275 - filterCount.incrementAndGet();
501.276 - return true;
501.277 - }
501.278 - };
501.279 -
501.280 - client.addNotificationListener(name, countListener, countFilter, "tiddly");
501.281 -
501.282 - assertEquals("Initial notif count", 0, notifQueue.size());
501.283 - assertEquals("Initial filter count", 0, filterCount.get());
501.284 -
501.285 - Notification n = nextNotif(name);
501.286 - mbean.send(n);
501.287 -
501.288 - System.out.println("Waiting for notification to arrive...");
501.289 -
501.290 - Notification n1 = notifQueue.poll(10, TimeUnit.SECONDS);
501.291 -
501.292 - assertEquals("Received notif", n, n1);
501.293 - assertEquals("Notif queue size after receive", 0, notifQueue.size());
501.294 - assertEquals("Filter count after notif", 1, filterCount.get());
501.295 - assertEquals("Lost notif count", 0, lostCountSema.availablePermits());
501.296 -
501.297 - System.out.println("Dropping notifs");
501.298 -
501.299 - UdpEventForwarder.setDrop(true);
501.300 - for (int i = 0; i < 3; i++)
501.301 - mbean.send(nextNotif(name));
501.302 - UdpEventForwarder.setDrop(false);
501.303 -
501.304 - Thread.sleep(2);
501.305 - assertEquals("Notif queue size after drops", 0, notifQueue.size());
501.306 -
501.307 - System.out.println("Turning off dropping and sending a notif");
501.308 - n = nextNotif(name);
501.309 - mbean.send(n);
501.310 -
501.311 - System.out.println("Waiting for dropped notifications to be detected...");
501.312 - boolean acquired = lostCountSema.tryAcquire(3, 5, TimeUnit.SECONDS);
501.313 - assertEquals("Correct count of lost notifs", true, acquired);
501.314 -
501.315 - n1 = notifQueue.poll(10, TimeUnit.SECONDS);
501.316 - assertEquals("Received non-dropped notif", n, n1);
501.317 -
501.318 - assertEquals("Notif queue size", 0, notifQueue.size());
501.319 - assertEquals("Filter count after drops", 5, filterCount.get());
501.320 -
501.321 - Thread.sleep(10);
501.322 - assertEquals("Further lost-notifs", 0, lostCountSema.availablePermits());
501.323 -
501.324 - System.out.println("Testing error notifs");
501.325 - relay.simulateNonFatal();
501.326 - n = nonFatalNotifs.poll(10, TimeUnit.SECONDS);
501.327 - assertEquals("Exception message for non-fatal exception", "NonFatal",
501.328 - ((Throwable) n.getSource()).getMessage());
501.329 - relay.simulateFailed();
501.330 - n = failedNotifs.poll(10, TimeUnit.SECONDS);
501.331 - assertEquals("Exception message for failed exception", "Failed",
501.332 - ((Throwable) n.getSource()).getMessage());
501.333 -
501.334 - // 6759619
501.335 - System.out.println("Test EventClient.getEventClientNotificationInfo");
501.336 - MBeanNotificationInfo[] mbnis = client.getEventClientNotificationInfo();
501.337 - final String[] expectedTypes = {
501.338 - EventClient.NOTIFS_LOST, EventClient.NONFATAL, EventClient.FAILED
501.339 - };
501.340 - check:
501.341 - for (String type : expectedTypes) {
501.342 - for (MBeanNotificationInfo mbni : mbnis) {
501.343 - for (String t : mbni.getNotifTypes()) {
501.344 - if (type.equals(t)) {
501.345 - System.out.println("...found " + type);
501.346 - continue check;
501.347 - }
501.348 - }
501.349 - }
501.350 - throw new Exception("TEST FAILED: Did not find notif type " + type);
501.351 - }
501.352 -
501.353 - client.close();
501.354 -
501.355 - System.out.println("TEST PASSED");
501.356 - }
501.357 -
501.358 - private static AtomicLong nextSeqNo = new AtomicLong(0);
501.359 - private static Notification nextNotif(ObjectName name) {
501.360 - long n = nextSeqNo.incrementAndGet();
501.361 - return new Notification("type", name, n, "" + n);
501.362 - }
501.363 -
501.364 - private static void assertEquals(String what, Object expected, Object got) {
501.365 - if (equals(expected, got))
501.366 - System.out.println(what + " = " + expected + ", as expected");
501.367 - else {
501.368 - Map<Thread, StackTraceElement[]> traces = Thread.getAllStackTraces();
501.369 - for (Thread t : traces.keySet()) {
501.370 - System.out.println(t.getName());
501.371 - for (StackTraceElement elmt : traces.get(t)) {
501.372 - System.out.println(" " + elmt);
501.373 - }
501.374 - }
501.375 - throw new RuntimeException(
501.376 - "TEST FAILED: " + what + " is " + got + "; should be " +
501.377 - expected);
501.378 - }
501.379 - }
501.380 -
501.381 - private static boolean equals(Object expected, Object got) {
501.382 - if (!(expected instanceof Notification))
501.383 - return expected.equals(got);
501.384 - if (expected.getClass() != got.getClass())
501.385 - return false;
501.386 - // Notification doesn't override Object.equals so two distinct
501.387 - // notifs are never equal even if they have the same contents.
501.388 - // Although the test doesn't serialize the notifs, if at some
501.389 - // stage it did then it would fail because the deserialized notif
501.390 - // was not equal to the original one. Therefore we compare enough
501.391 - // notif fields to detect when notifs really are different.
501.392 - Notification en = (Notification) expected;
501.393 - Notification gn = (Notification) got;
501.394 - return (en.getType().equals(gn.getType()) &&
501.395 - en.getSource().equals(gn.getSource()) &&
501.396 - en.getSequenceNumber() == gn.getSequenceNumber());
501.397 - }
501.398 -}
502.1 --- a/test/javax/management/eventService/EventClientExecutorTest.java Mon Nov 23 10:04:47 2009 +0000
502.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
502.3 @@ -1,190 +0,0 @@
502.4 -/*
502.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
502.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
502.7 - *
502.8 - * This code is free software; you can redistribute it and/or modify it
502.9 - * under the terms of the GNU General Public License version 2 only, as
502.10 - * published by the Free Software Foundation.
502.11 - *
502.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
502.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
502.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
502.15 - * version 2 for more details (a copy is included in the LICENSE file that
502.16 - * accompanied this code).
502.17 - *
502.18 - * You should have received a copy of the GNU General Public License version
502.19 - * 2 along with this work; if not, write to the Free Software Foundation,
502.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
502.21 - *
502.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
502.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
502.24 - * have any questions.
502.25 - */
502.26 -
502.27 -/*
502.28 - * @test
502.29 - * @bug 5108776
502.30 - * @summary Test that the various Executor parameters in an EventClient do
502.31 - * what they are supposed to.
502.32 - * @author Eamonn McManus
502.33 - */
502.34 -
502.35 -import java.lang.reflect.InvocationHandler;
502.36 -import java.lang.reflect.InvocationTargetException;
502.37 -import java.lang.reflect.Method;
502.38 -import java.lang.reflect.Proxy;
502.39 -import java.util.HashSet;
502.40 -import java.util.Set;
502.41 -import java.util.concurrent.Executor;
502.42 -import java.util.concurrent.Executors;
502.43 -import java.util.concurrent.ScheduledExecutorService;
502.44 -import java.util.concurrent.ThreadFactory;
502.45 -import javax.management.MBeanServer;
502.46 -import javax.management.MBeanServerFactory;
502.47 -import javax.management.Notification;
502.48 -import javax.management.NotificationBroadcasterSupport;
502.49 -import javax.management.NotificationListener;
502.50 -import javax.management.ObjectName;
502.51 -import javax.management.event.EventClient;
502.52 -import javax.management.event.EventClientDelegate;
502.53 -import javax.management.event.EventClientDelegateMBean;
502.54 -import javax.management.event.FetchingEventRelay;
502.55 -import javax.management.remote.MBeanServerForwarder;
502.56 -
502.57 -public class EventClientExecutorTest {
502.58 - private static volatile String failure;
502.59 - private static final Set testedPrefixes = new HashSet();
502.60 -
502.61 - public static void main(String[] args) throws Exception {
502.62 - Executor fetchExecutor = Executors.newSingleThreadExecutor(
502.63 - new NamedThreadFactory("FETCH"));
502.64 - Executor listenerExecutor = Executors.newSingleThreadExecutor(
502.65 - new NamedThreadFactory("LISTENER"));
502.66 - ScheduledExecutorService leaseScheduler =
502.67 - Executors.newSingleThreadScheduledExecutor(
502.68 - new NamedThreadFactory("LEASE"));
502.69 -
502.70 - MBeanServer mbs = MBeanServerFactory.newMBeanServer();
502.71 - MBeanServerForwarder mbsf = EventClientDelegate.newForwarder(mbs, null);
502.72 - mbs = mbsf;
502.73 -
502.74 - EventClientDelegateMBean ecd = EventClientDelegate.getProxy(mbs);
502.75 - ecd = (EventClientDelegateMBean) Proxy.newProxyInstance(
502.76 - EventClientDelegateMBean.class.getClassLoader(),
502.77 - new Class<?>[] {EventClientDelegateMBean.class},
502.78 - new DelegateCheckIH(ecd));
502.79 -
502.80 - ObjectName mbeanName = new ObjectName("d:type=Notifier");
502.81 - Notifier notifier = new Notifier();
502.82 - mbs.registerMBean(notifier, mbeanName);
502.83 -
502.84 - FetchingEventRelay eventRelay = new FetchingEventRelay(
502.85 - ecd, fetchExecutor);
502.86 - EventClient ec = new EventClient(
502.87 - ecd, eventRelay, listenerExecutor, leaseScheduler, 1000L);
502.88 - NotificationListener checkListener = new NotificationListener() {
502.89 - public void handleNotification(Notification notification,
502.90 - Object handback) {
502.91 - assertThreadName("listener dispatch", "LISTENER");
502.92 - }
502.93 - };
502.94 - ec.addNotificationListener(mbeanName, checkListener, null, null);
502.95 -
502.96 - mbs.invoke(mbeanName, "send", null, null);
502.97 -
502.98 - // Now wait until we have seen all three thread types.
502.99 - long deadline = System.currentTimeMillis() + 5000;
502.100 - synchronized (testedPrefixes) {
502.101 - while (testedPrefixes.size() < 3 && failure == null) {
502.102 - long remain = deadline - System.currentTimeMillis();
502.103 - if (remain <= 0) {
502.104 - fail("Timed out waiting for all three thread types to show, " +
502.105 - "saw only " + testedPrefixes);
502.106 - break;
502.107 - }
502.108 - try {
502.109 - testedPrefixes.wait(remain);
502.110 - } catch (InterruptedException e) {
502.111 - fail("Unexpected InterruptedException");
502.112 - break;
502.113 - }
502.114 - }
502.115 - }
502.116 -
502.117 - // We deliberately don't close the EventClient to check that it has
502.118 - // not created any non-daemon threads.
502.119 -
502.120 - if (failure != null)
502.121 - throw new Exception("TEST FAILED: " + failure);
502.122 - else
502.123 - System.out.println("TEST PASSED");
502.124 - }
502.125 -
502.126 - public static interface NotifierMBean {
502.127 - public void send();
502.128 - }
502.129 -
502.130 - public static class Notifier extends NotificationBroadcasterSupport
502.131 - implements NotifierMBean {
502.132 - public void send() {
502.133 - Notification n = new Notification("a.b.c", this, 0L);
502.134 - sendNotification(n);
502.135 - }
502.136 - }
502.137 -
502.138 - static void fail(String why) {
502.139 - System.out.println("FAIL: " + why);
502.140 - failure = why;
502.141 - }
502.142 -
502.143 - static void assertThreadName(String what, String prefix) {
502.144 - String name = Thread.currentThread().getName();
502.145 - if (!name.startsWith(prefix)) {
502.146 - fail("Wrong thread for " + what + ": " + name);
502.147 - return;
502.148 - }
502.149 -
502.150 - synchronized (testedPrefixes) {
502.151 - if (testedPrefixes.add(prefix))
502.152 - testedPrefixes.notify();
502.153 - }
502.154 - }
502.155 -
502.156 - private static class DelegateCheckIH implements InvocationHandler {
502.157 - private final EventClientDelegateMBean ecd;
502.158 -
502.159 - public DelegateCheckIH(EventClientDelegateMBean ecd) {
502.160 - this.ecd = ecd;
502.161 - }
502.162 -
502.163 - public Object invoke(Object proxy, Method method, Object[] args)
502.164 - throws Throwable {
502.165 - String methodName = method.getName();
502.166 - if (methodName.equals("fetchNotifications"))
502.167 - assertThreadName("fetchNotifications", "FETCH");
502.168 - else if (methodName.equals("lease"))
502.169 - assertThreadName("lease renewal", "LEASE");
502.170 - try {
502.171 - return method.invoke(ecd, args);
502.172 - } catch (InvocationTargetException e) {
502.173 - throw e.getCause();
502.174 - }
502.175 - }
502.176 - }
502.177 -
502.178 - private static class NamedThreadFactory implements ThreadFactory {
502.179 - private final String namePrefix;
502.180 - private int count;
502.181 -
502.182 - NamedThreadFactory(String namePrefix) {
502.183 - this.namePrefix = namePrefix;
502.184 - }
502.185 -
502.186 - public synchronized Thread newThread(Runnable r) {
502.187 - Thread t = new Thread(r);
502.188 - t.setName(namePrefix + " " + ++count);
502.189 - t.setDaemon(true);
502.190 - return t;
502.191 - }
502.192 - }
502.193 -}
503.1 --- a/test/javax/management/eventService/EventClientThreadTest.java Mon Nov 23 10:04:47 2009 +0000
503.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
503.3 @@ -1,176 +0,0 @@
503.4 -/*
503.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
503.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
503.7 - *
503.8 - * This code is free software; you can redistribute it and/or modify it
503.9 - * under the terms of the GNU General Public License version 2 only, as
503.10 - * published by the Free Software Foundation.
503.11 - *
503.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
503.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
503.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
503.15 - * version 2 for more details (a copy is included in the LICENSE file that
503.16 - * accompanied this code).
503.17 - *
503.18 - * You should have received a copy of the GNU General Public License version
503.19 - * 2 along with this work; if not, write to the Free Software Foundation,
503.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
503.21 - *
503.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
503.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
503.24 - * have any questions.
503.25 - */
503.26 -
503.27 -/*
503.28 - * @test
503.29 - * @bug 6747411
503.30 - * @summary Check that EventClient instances don't leak threads.
503.31 - * @author Eamonn McManus
503.32 - */
503.33 -
503.34 -import java.lang.management.ManagementFactory;
503.35 -import java.lang.management.ThreadInfo;
503.36 -import java.lang.management.ThreadMXBean;
503.37 -import java.util.concurrent.ArrayBlockingQueue;
503.38 -import java.util.concurrent.BlockingQueue;
503.39 -import java.util.concurrent.TimeUnit;
503.40 -import java.util.Set;
503.41 -import java.util.TreeSet;
503.42 -import javax.management.MBeanServer;
503.43 -import javax.management.MBeanServerConnection;
503.44 -import javax.management.MBeanServerDelegate;
503.45 -import javax.management.MBeanServerNotification;
503.46 -import javax.management.Notification;
503.47 -import javax.management.NotificationFilter;
503.48 -import javax.management.NotificationListener;
503.49 -import javax.management.ObjectName;
503.50 -import javax.management.event.EventClient;
503.51 -import javax.management.remote.JMXConnector;
503.52 -import javax.management.remote.JMXConnectorFactory;
503.53 -import javax.management.remote.JMXConnectorServer;
503.54 -import javax.management.remote.JMXConnectorServerFactory;
503.55 -import javax.management.remote.JMXServiceURL;
503.56 -
503.57 -public class EventClientThreadTest {
503.58 - private static final int MAX_TIME_SECONDS = 20;
503.59 -
503.60 - private static final BlockingQueue<Notification> queue =
503.61 - new ArrayBlockingQueue(100);
503.62 -
503.63 - private static final NotificationListener queueListener =
503.64 - new NotificationListener() {
503.65 - public void handleNotification(Notification notification,
503.66 - Object handback) {
503.67 - queue.add(notification);
503.68 - }
503.69 - };
503.70 -
503.71 - private static final NotificationFilter dummyFilter =
503.72 - new NotificationFilter() {
503.73 - public boolean isNotificationEnabled(Notification notification) {
503.74 - return true;
503.75 - }
503.76 - };
503.77 -
503.78 - public static void main(String[] args) throws Exception {
503.79 - long start = System.currentTimeMillis();
503.80 - long deadline = start + MAX_TIME_SECONDS * 1000;
503.81 -
503.82 - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
503.83 - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
503.84 - JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(
503.85 - url, null, mbs);
503.86 - cs.start();
503.87 - JMXServiceURL addr = cs.getAddress();
503.88 - JMXConnector cc = JMXConnectorFactory.connect(addr);
503.89 - MBeanServerConnection mbsc = cc.getMBeanServerConnection();
503.90 -
503.91 - ThreadMXBean threads = ManagementFactory.getThreadMXBean();
503.92 -
503.93 - System.out.println("Opening and closing some EventClients...");
503.94 - // If we create a connection, then create and destroy EventClients
503.95 - // over it, then close it, there should be no "JMX *" threads left.
503.96 - for (int i = 0; i < 5; i++)
503.97 - test(mbsc);
503.98 -
503.99 - cc.close();
503.100 -
503.101 - showTime("opening and closing initial EventClients", start);
503.102 -
503.103 - Set<String> jmxThreads = threadsMatching("JMX .*");
503.104 - while (!jmxThreads.isEmpty() && System.currentTimeMillis() < deadline) {
503.105 - Set<String> jmxThreadsNow = threadsMatching("JMX .*");
503.106 - Set<String> gone = new TreeSet<String>(jmxThreads);
503.107 - gone.removeAll(jmxThreadsNow);
503.108 - for (String s : gone)
503.109 - showTime("expiry of \"" + s + "\"", start);
503.110 - jmxThreads = jmxThreadsNow;
503.111 - Thread.sleep(10);
503.112 - }
503.113 - if (System.currentTimeMillis() >= deadline) {
503.114 - showThreads(threads);
503.115 - throw new Exception("Timed out waiting for JMX threads to expire");
503.116 - }
503.117 -
503.118 - showTime("waiting for JMX threads to expire", start);
503.119 -
503.120 - System.out.println("TEST PASSED");
503.121 - }
503.122 -
503.123 - static void showThreads(ThreadMXBean threads) throws Exception {
503.124 - long[] ids = threads.getAllThreadIds();
503.125 - for (long id : ids) {
503.126 - ThreadInfo ti = threads.getThreadInfo(id);
503.127 - String name = (ti == null) ? "(defunct)" : ti.getThreadName();
503.128 - System.out.printf("%4d %s\n", id, name);
503.129 - }
503.130 - }
503.131 -
503.132 - static void showTime(String what, long start) {
503.133 - long elapsed = System.currentTimeMillis() - start;
503.134 - System.out.printf("Time after %s: %.3f s\n", what, elapsed / 1000.0);
503.135 - }
503.136 -
503.137 - static Set<String> threadsMatching(String pattern) {
503.138 - Set<String> matching = new TreeSet<String>();
503.139 - ThreadMXBean threads = ManagementFactory.getThreadMXBean();
503.140 - long[] ids = threads.getAllThreadIds();
503.141 - for (long id : ids) {
503.142 - ThreadInfo ti = threads.getThreadInfo(id);
503.143 - String name = (ti == null) ? "(defunct)" : ti.getThreadName();
503.144 - if (name.matches(pattern))
503.145 - matching.add(name);
503.146 - }
503.147 - return matching;
503.148 - }
503.149 -
503.150 - static void test(MBeanServerConnection mbsc) throws Exception {
503.151 - final ObjectName delegateName = MBeanServerDelegate.DELEGATE_NAME;
503.152 - final ObjectName testName = new ObjectName("test:type=Test");
503.153 - EventClient ec = new EventClient(mbsc);
503.154 - ec.addNotificationListener(delegateName, queueListener, null, null);
503.155 - mbsc.createMBean(MBeanServerDelegate.class.getName(), testName);
503.156 - mbsc.unregisterMBean(testName);
503.157 - final String[] expectedTypes = {
503.158 - MBeanServerNotification.REGISTRATION_NOTIFICATION,
503.159 - MBeanServerNotification.UNREGISTRATION_NOTIFICATION,
503.160 - };
503.161 - for (String s : expectedTypes) {
503.162 - Notification n = queue.poll(3, TimeUnit.SECONDS);
503.163 - if (n == null)
503.164 - throw new Exception("Timed out waiting for notif: " + s);
503.165 - if (!(n instanceof MBeanServerNotification))
503.166 - throw new Exception("Got notif of wrong class: " + n.getClass());
503.167 - if (!n.getType().equals(s)) {
503.168 - throw new Exception("Got notif of wrong type: " + n.getType() +
503.169 - " (expecting " + s + ")");
503.170 - }
503.171 - }
503.172 - ec.removeNotificationListener(delegateName, queueListener);
503.173 -
503.174 - ec.addNotificationListener(delegateName, queueListener, dummyFilter, "foo");
503.175 - ec.removeNotificationListener(delegateName, queueListener, dummyFilter, "foo");
503.176 -
503.177 - ec.close();
503.178 - }
503.179 -}
503.180 \ No newline at end of file
504.1 --- a/test/javax/management/eventService/EventDelegateSecurityTest.java Mon Nov 23 10:04:47 2009 +0000
504.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
504.3 @@ -1,289 +0,0 @@
504.4 -/*
504.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
504.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
504.7 - *
504.8 - * This code is free software; you can redistribute it and/or modify it
504.9 - * under the terms of the GNU General Public License version 2 only, as
504.10 - * published by the Free Software Foundation.
504.11 - *
504.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
504.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
504.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
504.15 - * version 2 for more details (a copy is included in the LICENSE file that
504.16 - * accompanied this code).
504.17 - *
504.18 - * You should have received a copy of the GNU General Public License version
504.19 - * 2 along with this work; if not, write to the Free Software Foundation,
504.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
504.21 - *
504.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
504.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
504.24 - * have any questions.
504.25 - */
504.26 -
504.27 -/*
504.28 - * @test
504.29 - * @bug 5108776
504.30 - * @summary Test that the EventClientDelegate MBean does not require extra
504.31 - * permissions compared with plain addNotificationListener.
504.32 - * @author Eamonn McManus
504.33 - * @run main/othervm -Dxjava.security.debug=policy,access,failure EventDelegateSecurityTest
504.34 - */
504.35 -
504.36 -import java.io.File;
504.37 -import java.io.IOException;
504.38 -import java.io.PrintWriter;
504.39 -import java.lang.management.ManagementFactory;
504.40 -import java.lang.reflect.InvocationHandler;
504.41 -import java.lang.reflect.InvocationTargetException;
504.42 -import java.lang.reflect.Method;
504.43 -import java.lang.reflect.Proxy;
504.44 -import java.security.AccessControlContext;
504.45 -import java.security.AccessController;
504.46 -import java.security.AllPermission;
504.47 -import java.security.PrivilegedExceptionAction;
504.48 -import java.util.Arrays;
504.49 -import java.util.HashMap;
504.50 -import java.util.HashSet;
504.51 -import java.util.Map;
504.52 -import java.util.Set;
504.53 -import java.util.concurrent.BlockingQueue;
504.54 -import java.util.concurrent.SynchronousQueue;
504.55 -import java.util.concurrent.TimeUnit;
504.56 -import javax.management.MBeanPermission;
504.57 -import javax.management.MBeanServer;
504.58 -import javax.management.MBeanServerConnection;
504.59 -import javax.management.Notification;
504.60 -import javax.management.NotificationBroadcasterSupport;
504.61 -import javax.management.NotificationListener;
504.62 -import javax.management.ObjectName;
504.63 -import javax.management.event.EventClient;
504.64 -import javax.management.remote.JMXAuthenticator;
504.65 -import javax.management.remote.JMXConnector;
504.66 -import javax.management.remote.JMXConnectorFactory;
504.67 -import javax.management.remote.JMXConnectorServer;
504.68 -import javax.management.remote.JMXConnectorServerFactory;
504.69 -import javax.management.remote.JMXPrincipal;
504.70 -import javax.management.remote.JMXServiceURL;
504.71 -import javax.management.remote.MBeanServerForwarder;
504.72 -import javax.security.auth.Subject;
504.73 -
504.74 -public class EventDelegateSecurityTest {
504.75 - private static final BlockingQueue<Notification> notifQ =
504.76 - new SynchronousQueue<Notification>();
504.77 -
504.78 - private static volatile long seqNo;
504.79 - private static volatile long expectSeqNo;
504.80 -
504.81 - private static class QueueListener implements NotificationListener {
504.82 - public void handleNotification(Notification notification,
504.83 - Object handback) {
504.84 - try {
504.85 - notifQ.put(notification);
504.86 - } catch (InterruptedException e) {
504.87 - throw new AssertionError(e);
504.88 - }
504.89 - }
504.90 - }
504.91 - private static final NotificationListener queueListener = new QueueListener();
504.92 -
504.93 - public static interface SenderMBean {
504.94 - public void send();
504.95 - }
504.96 -
504.97 - public static class Sender
504.98 - extends NotificationBroadcasterSupport implements SenderMBean {
504.99 - public void send() {
504.100 - Notification n = new Notification("x", this, seqNo++);
504.101 - sendNotification(n);
504.102 - }
504.103 - }
504.104 -
504.105 - private static class LimitInvocationHandler implements InvocationHandler {
504.106 - private MBeanServer nextMBS;
504.107 - private final Set<String> allowedMethods = new HashSet<String>();
504.108 -
504.109 - void allow(String... names) {
504.110 - synchronized (allowedMethods) {
504.111 - allowedMethods.addAll(Arrays.asList(names));
504.112 - }
504.113 - }
504.114 -
504.115 - public Object invoke(Object proxy, Method m, Object[] args)
504.116 - throws Throwable {
504.117 - System.out.println(
504.118 - "filter: " + m.getName() +
504.119 - ((args == null) ? "[]" : Arrays.deepToString(args)));
504.120 - String name = m.getName();
504.121 -
504.122 - if (name.equals("getMBeanServer"))
504.123 - return nextMBS;
504.124 -
504.125 - if (name.equals("setMBeanServer")) {
504.126 - nextMBS = (MBeanServer) args[0];
504.127 - return null;
504.128 - }
504.129 -
504.130 - if (m.getDeclaringClass() == Object.class ||
504.131 - allowedMethods.contains(name)) {
504.132 - try {
504.133 - return m.invoke(nextMBS, args);
504.134 - } catch (InvocationTargetException e) {
504.135 - throw e.getCause();
504.136 - }
504.137 - } else {
504.138 - System.out.println("...refused");
504.139 - throw new SecurityException(
504.140 - "Method refused: " + m.getDeclaringClass().getName() +
504.141 - "." + m.getName() +
504.142 - ((args == null) ? "[]" : Arrays.deepToString(args)));
504.143 - }
504.144 - }
504.145 -
504.146 - }
504.147 -
504.148 - private static interface MakeConnectorServer {
504.149 - public JMXConnectorServer make(JMXServiceURL url) throws IOException;
504.150 - }
504.151 -
504.152 -
504.153 - public static void main(String[] args) throws Exception {
504.154 - JMXPrincipal rootPrincipal = new JMXPrincipal("root");
504.155 - Subject rootSubject = new Subject();
504.156 - rootSubject.getPrincipals().add(rootPrincipal);
504.157 - Subject.doAsPrivileged(rootSubject, new PrivilegedExceptionAction<Void>() {
504.158 - public Void run() throws Exception {
504.159 - mainAsRoot();
504.160 - return null;
504.161 - }
504.162 - }, null);
504.163 - }
504.164 -
504.165 - private static void mainAsRoot() throws Exception {
504.166 - AccessControlContext acc = AccessController.getContext();
504.167 - Subject subject = Subject.getSubject(acc);
504.168 - System.out.println("Subject: " + subject);
504.169 - final MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
504.170 - ObjectName name = new ObjectName("a:b=c");
504.171 - mbs.registerMBean(new Sender(), name);
504.172 -
504.173 - System.out.println("Test with no installed security");
504.174 - test(mbs, name, new MakeConnectorServer() {
504.175 - public JMXConnectorServer make(JMXServiceURL url) throws IOException {
504.176 - return
504.177 - JMXConnectorServerFactory.newJMXConnectorServer(url, null, null);
504.178 - }
504.179 - });
504.180 -
504.181 - System.out.println("Test with filtering MBeanServerForwarder");
504.182 - LimitInvocationHandler limitIH = new LimitInvocationHandler();
504.183 - // We allow getClassLoaderRepository because the ConnectorServer
504.184 - // calls it so any real checking MBeanServerForwarder must accept it.
504.185 - limitIH.allow(
504.186 - "addNotificationListener", "removeNotificationListener",
504.187 - "getClassLoaderRepository"
504.188 - );
504.189 - final MBeanServerForwarder limitMBSF = (MBeanServerForwarder)
504.190 - Proxy.newProxyInstance(
504.191 - MBeanServerForwarder.class.getClassLoader(),
504.192 - new Class<?>[] {MBeanServerForwarder.class},
504.193 - limitIH);
504.194 - // We go to considerable lengths to ensure that the ConnectorServer has
504.195 - // no MBeanServer when the EventClientDelegate forwarder is activated,
504.196 - // so that the calls it makes when it is later linked to an MBeanServer
504.197 - // go through the limitMBSF.
504.198 - test(mbs, name, new MakeConnectorServer() {
504.199 - public JMXConnectorServer make(JMXServiceURL url) throws IOException {
504.200 - JMXConnectorServer cs =
504.201 - JMXConnectorServerFactory.newJMXConnectorServer(url, null, null);
504.202 - limitMBSF.setMBeanServer(mbs);
504.203 - cs.setMBeanServerForwarder(limitMBSF);
504.204 - return cs;
504.205 - }
504.206 - });
504.207 -
504.208 - final File policyFile =
504.209 - File.createTempFile("EventDelegateSecurityTest", ".policy");
504.210 - PrintWriter pw = new PrintWriter(policyFile);
504.211 - String JMXPrincipal = JMXPrincipal.class.getName();
504.212 - String AllPermission = AllPermission.class.getName();
504.213 - String MBeanPermission = MBeanPermission.class.getName();
504.214 - pw.println("grant principal " + JMXPrincipal + " \"root\" {");
504.215 - pw.println(" permission " + AllPermission + ";");
504.216 - pw.println("};");
504.217 - pw.println("grant principal " + JMXPrincipal + " \"user\" {");
504.218 - pw.println(" permission " + MBeanPermission + " \"*\", " +
504.219 - " \"addNotificationListener\";");
504.220 - pw.println(" permission " + MBeanPermission + " \"*\", " +
504.221 - " \"removeNotificationListener\";");
504.222 - pw.println("};");
504.223 - pw.close();
504.224 - Runtime.getRuntime().addShutdownHook(new Thread() {
504.225 - @Override
504.226 - public void run() {
504.227 - policyFile.delete();
504.228 - }
504.229 - });
504.230 - System.setProperty("java.security.policy", policyFile.getAbsolutePath());
504.231 - System.setSecurityManager(new SecurityManager());
504.232 - test(mbs, name, new MakeConnectorServer() {
504.233 - public JMXConnectorServer make(JMXServiceURL url) throws IOException {
504.234 - Map<String, Object> env = new HashMap<String, Object>();
504.235 - env.put(JMXConnectorServer.AUTHENTICATOR, new JMXAuthenticator() {
504.236 - public Subject authenticate(Object credentials) {
504.237 - Subject s = new Subject();
504.238 - s.getPrincipals().add(new JMXPrincipal("user"));
504.239 - return s;
504.240 - }
504.241 - });
504.242 - return
504.243 - JMXConnectorServerFactory.newJMXConnectorServer(url, env, null);
504.244 - }
504.245 - });
504.246 - }
504.247 -
504.248 - private static void test(MBeanServer mbs, ObjectName name) throws Exception {
504.249 - test(mbs, name, null);
504.250 - }
504.251 -
504.252 - private static void test(
504.253 - MBeanServer mbs, ObjectName name, MakeConnectorServer make)
504.254 - throws Exception {
504.255 - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///");
504.256 - JMXConnectorServer cs = make.make(url);
504.257 - ObjectName csName = new ObjectName("a:type=ConnectorServer");
504.258 - mbs.registerMBean(cs, csName);
504.259 - cs.start();
504.260 - try {
504.261 - JMXServiceURL addr = cs.getAddress();
504.262 - JMXConnector cc = JMXConnectorFactory.connect(addr);
504.263 - MBeanServerConnection mbsc = cc.getMBeanServerConnection();
504.264 - test(mbs, mbsc, name);
504.265 - cc.close();
504.266 - mbs.unregisterMBean(csName);
504.267 - } finally {
504.268 - cs.stop();
504.269 - }
504.270 - }
504.271 -
504.272 - private static void test(
504.273 - MBeanServer mbs, MBeanServerConnection mbsc, ObjectName name)
504.274 - throws Exception {
504.275 - EventClient ec = new EventClient(mbsc);
504.276 - ec.addNotificationListener(name, queueListener, null, null);
504.277 - mbs.invoke(name, "send", null, null);
504.278 -
504.279 - Notification n = notifQ.poll(5, TimeUnit.SECONDS);
504.280 - if (n == null)
504.281 - throw new Exception("FAILED: notif not delivered");
504.282 - if (n.getSequenceNumber() != expectSeqNo) {
504.283 - throw new Exception(
504.284 - "FAILED: notif seqno " + n.getSequenceNumber() +
504.285 - " should be " + expectSeqNo);
504.286 - }
504.287 - expectSeqNo++;
504.288 -
504.289 - ec.removeNotificationListener(name, queueListener);
504.290 - ec.close();
504.291 - }
504.292 -}
505.1 --- a/test/javax/management/eventService/EventManagerTest.java Mon Nov 23 10:04:47 2009 +0000
505.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
505.3 @@ -1,221 +0,0 @@
505.4 -/*
505.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
505.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
505.7 - *
505.8 - * This code is free software; you can redistribute it and/or modify it
505.9 - * under the terms of the GNU General Public License version 2 only, as
505.10 - * published by the Free Software Foundation.
505.11 - *
505.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
505.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
505.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
505.15 - * version 2 for more details (a copy is included in the LICENSE file that
505.16 - * accompanied this code).
505.17 - *
505.18 - * You should have received a copy of the GNU General Public License version
505.19 - * 2 along with this work; if not, write to the Free Software Foundation,
505.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
505.21 - *
505.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
505.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
505.24 - * have any questions.
505.25 - */
505.26 -
505.27 -/*
505.28 - * @test EventManagerTest.java 1.8 08/01/22
505.29 - * @bug 5108776
505.30 - * @summary Basic test for EventManager.
505.31 - * @author Shanliang JIANG
505.32 - * @run clean EventManagerTest
505.33 - * @run build EventManagerTest
505.34 - * @run main EventManagerTest
505.35 - */
505.36 -
505.37 -import javax.management.MBeanNotificationInfo;
505.38 -import javax.management.MBeanServer;
505.39 -import javax.management.MBeanServerConnection;
505.40 -import javax.management.MBeanServerFactory;
505.41 -import javax.management.Notification;
505.42 -import javax.management.NotificationBroadcasterSupport;
505.43 -import javax.management.NotificationListener;
505.44 -import javax.management.ObjectName;
505.45 -import javax.management.event.*;
505.46 -import javax.management.remote.JMXConnector;
505.47 -import javax.management.remote.JMXConnectorFactory;
505.48 -import javax.management.remote.JMXConnectorServer;
505.49 -import javax.management.remote.JMXConnectorServerFactory;
505.50 -import javax.management.remote.JMXServiceURL;
505.51 -
505.52 -/**
505.53 - *
505.54 - */
505.55 -public class EventManagerTest {
505.56 - private static MBeanServer mbeanServer;
505.57 - private static ObjectName emitter;
505.58 - private static JMXServiceURL url;
505.59 - private static JMXConnectorServer server;
505.60 - private static JMXConnector conn;
505.61 - private static MBeanServerConnection client;
505.62 -
505.63 - /**
505.64 - * @param args the command line arguments
505.65 - */
505.66 - public static void main(String[] args) throws Exception {
505.67 - System.out.println(">>> EventManagerTest-main basic tests ...");
505.68 - mbeanServer = MBeanServerFactory.createMBeanServer();
505.69 -
505.70 - // for 1.5
505.71 - if (System.getProperty("java.version").startsWith("1.5") &&
505.72 - !mbeanServer.isRegistered(EventClientDelegateMBean.OBJECT_NAME)) {
505.73 - System.out.print("Working on "+System.getProperty("java.version")+
505.74 - " register "+EventClientDelegateMBean.OBJECT_NAME);
505.75 -
505.76 - mbeanServer.registerMBean(EventClientDelegate.
505.77 - getEventClientDelegate(mbeanServer),
505.78 - EventClientDelegateMBean.OBJECT_NAME);
505.79 - }
505.80 -
505.81 - emitter = new ObjectName("Default:name=NotificationEmitter");
505.82 -
505.83 - url = new JMXServiceURL("rmi", null, 0) ;
505.84 - server =
505.85 - JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbeanServer);
505.86 - server.start();
505.87 -
505.88 - url = server.getAddress();
505.89 - conn = JMXConnectorFactory.connect(url, null);
505.90 - client = conn.getMBeanServerConnection();
505.91 -
505.92 - mbeanServer.registerMBean(new NotificationEmitter(), emitter);
505.93 -
505.94 - boolean succeed;
505.95 -
505.96 - System.out.println(">>> EventManagerTest-main: using the fetching EventRelay...");
505.97 - succeed = test(new EventClient(client));
505.98 -
505.99 - System.out.println(">>> EventManagerTest-main: using the pushing EventRelay...");
505.100 - EventClientDelegateMBean ecd = EventClientDelegate.getProxy(client);
505.101 - succeed &= test(new EventClient(ecd,
505.102 - new RMIPushEventRelay(ecd),
505.103 - null, null,
505.104 - EventClient.DEFAULT_REQUESTED_LEASE_TIME));
505.105 -
505.106 - conn.close();
505.107 - server.stop();
505.108 -
505.109 - if (succeed) {
505.110 - System.out.println(">>> EventManagerTest-main: PASSE!");
505.111 - } else {
505.112 - System.out.println("\n>>> EventManagerTest-main: FAILED!");
505.113 - System.exit(1);
505.114 - }
505.115 - }
505.116 -
505.117 - public static boolean test(EventClient efClient) throws Exception {
505.118 - // add listener from the client side
505.119 - Listener listener = new Listener();
505.120 - efClient.subscribe(emitter, listener, null, null);
505.121 -
505.122 - // ask to send notifs
505.123 - Object[] params = new Object[] {new Integer(sendNB)};
505.124 - String[] signatures = new String[] {"java.lang.Integer"};
505.125 - client.invoke(emitter, "sendNotifications", params, signatures);
505.126 -
505.127 - // waiting
505.128 - long toWait = 6000;
505.129 - long stopTime = System.currentTimeMillis() + toWait;
505.130 -
505.131 - synchronized(listener) {
505.132 - while(listener.received < sendNB && toWait > 0) {
505.133 - listener.wait(toWait);
505.134 - toWait = stopTime - System.currentTimeMillis();
505.135 - }
505.136 - }
505.137 -
505.138 - // clean
505.139 - System.out.println(">>> EventManagerTest-test: cleaning...");
505.140 - efClient.unsubscribe(emitter, listener);
505.141 - efClient.close();
505.142 -
505.143 - if (listener.received != sendNB) {
505.144 - System.out.println(">>> EventManagerTest-test: FAILED! Expected to receive "+sendNB+", but got "+listener.received);
505.145 -
505.146 - return false;
505.147 - } else if (listener.seqErr > 0) {
505.148 - System.out.println(">>> EventManagerTest-test: FAILED! The receiving sequence is not correct.");
505.149 -
505.150 - return false;
505.151 - } else {
505.152 - System.out.println(">>> EventManagerTest-test: got all expected "+listener.received);
505.153 - return true;
505.154 - }
505.155 - }
505.156 -
505.157 - private static class Listener implements NotificationListener {
505.158 - public int received = 0;
505.159 - public int seqErr = 0;
505.160 -
505.161 - private long lastSeq = -1;
505.162 -
505.163 - public void handleNotification(Notification notif, Object handback) {
505.164 - if (!myType.equals(notif.getType())) {
505.165 - System.out.println(">>> EventManagerTest-Listener: got unexpected notif: "+notif);
505.166 - System.exit(1);
505.167 - }
505.168 -
505.169 - if (lastSeq == -1) {
505.170 - lastSeq = notif.getSequenceNumber();
505.171 - } else if (notif.getSequenceNumber() - lastSeq++ != 1) {
505.172 - seqErr++;
505.173 - }
505.174 -
505.175 - //System.out.println(">>> EventManagerTest-Listener: got notif "+notif.getSequenceNumber());
505.176 -
505.177 - synchronized(this) {
505.178 - if (++received >= sendNB) {
505.179 - this.notify();
505.180 - }
505.181 - }
505.182 - }
505.183 - }
505.184 -
505.185 - public static class NotificationEmitter extends NotificationBroadcasterSupport
505.186 - implements NotificationEmitterMBean {
505.187 -
505.188 - public MBeanNotificationInfo[] getNotificationInfo() {
505.189 - final String[] ntfTypes = {myType};
505.190 -
505.191 - final MBeanNotificationInfo[] ntfInfoArray = {
505.192 - new MBeanNotificationInfo(ntfTypes,
505.193 - "javax.management.Notification",
505.194 - "Notifications sent by the NotificationEmitter")};
505.195 -
505.196 - return ntfInfoArray;
505.197 - }
505.198 -
505.199 - /**
505.200 - * Send Notification objects.
505.201 - *
505.202 - * @param nb The number of notifications to send
505.203 - */
505.204 - public void sendNotifications(Integer nb) {
505.205 - Notification notif;
505.206 - for (int i=1; i<=nb.intValue(); i++) {
505.207 - notif = new Notification(myType, this, count++);
505.208 - notif.setUserData("jsl");
505.209 - //System.out.println(">>> EventManagerService-NotificationEmitter-sendNotifications: "+i);
505.210 -
505.211 - sendNotification(notif);
505.212 - }
505.213 - }
505.214 - }
505.215 -
505.216 - public interface NotificationEmitterMBean {
505.217 - public void sendNotifications(Integer nb);
505.218 - }
505.219 -
505.220 - private static int sendNB = 120;
505.221 - private static long count = 0;
505.222 -
505.223 - private static final String myType = "notification.my_notification";
505.224 -}
506.1 --- a/test/javax/management/eventService/FetchingTest.java Mon Nov 23 10:04:47 2009 +0000
506.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
506.3 @@ -1,276 +0,0 @@
506.4 -/*
506.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
506.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
506.7 - *
506.8 - * This code is free software; you can redistribute it and/or modify it
506.9 - * under the terms of the GNU General Public License version 2 only, as
506.10 - * published by the Free Software Foundation.
506.11 - *
506.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
506.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
506.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
506.15 - * version 2 for more details (a copy is included in the LICENSE file that
506.16 - * accompanied this code).
506.17 - *
506.18 - * You should have received a copy of the GNU General Public License version
506.19 - * 2 along with this work; if not, write to the Free Software Foundation,
506.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
506.21 - *
506.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
506.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
506.24 - * have any questions.
506.25 - */
506.26 -
506.27 -/*
506.28 - * @test
506.29 - * @bug 5108776
506.30 - * @summary Basic test for EventClient.
506.31 - * @author Shanliang JIANG
506.32 - * @run clean FetchingTest MyFetchingEventForwarder
506.33 - * @run build FetchingTest MyFetchingEventForwarder
506.34 - * @run main FetchingTest MyFetchingEventForwarder
506.35 - */
506.36 -
506.37 -import javax.management.MBeanServer;
506.38 -import javax.management.MBeanServerConnection;
506.39 -import javax.management.MBeanServerFactory;
506.40 -import javax.management.Notification;
506.41 -import javax.management.NotificationBroadcasterSupport;
506.42 -import javax.management.NotificationListener;
506.43 -import javax.management.ObjectName;
506.44 -import javax.management.event.EventClient;
506.45 -import javax.management.event.EventClientDelegate;
506.46 -import javax.management.event.EventClientDelegateMBean;
506.47 -import javax.management.event.FetchingEventRelay;
506.48 -import javax.management.event.RMIPushEventForwarder;
506.49 -import javax.management.event.RMIPushServer;
506.50 -import javax.management.remote.JMXConnector;
506.51 -import javax.management.remote.JMXConnectorFactory;
506.52 -import javax.management.remote.JMXConnectorServer;
506.53 -import javax.management.remote.JMXConnectorServerFactory;
506.54 -import javax.management.remote.JMXServiceURL;
506.55 -
506.56 -public class FetchingTest {
506.57 - private static MBeanServer mbeanServer;
506.58 - private static ObjectName emitter;
506.59 - private static JMXServiceURL url;
506.60 - private static JMXConnectorServer server;
506.61 - private static JMXConnector conn;
506.62 - private static MBeanServerConnection client;
506.63 - private static long WAITING_TIME = 6000;
506.64 -
506.65 - /**
506.66 - * @param args the command line arguments
506.67 - */
506.68 - public static void main(String[] args) throws Exception {
506.69 -
506.70 - System.out.println(">>> FetchingTest-main basic tests ...");
506.71 - mbeanServer = MBeanServerFactory.createMBeanServer();
506.72 -
506.73 - // for 1.5
506.74 - if (System.getProperty("java.version").startsWith("1.5") &&
506.75 - !mbeanServer.isRegistered(EventClientDelegateMBean.OBJECT_NAME)) {
506.76 - System.out.print("Working on "+System.getProperty("java.version")+
506.77 - " register "+EventClientDelegateMBean.OBJECT_NAME);
506.78 -
506.79 - mbeanServer.registerMBean(EventClientDelegate.
506.80 - getEventClientDelegate(mbeanServer),
506.81 - EventClientDelegateMBean.OBJECT_NAME);
506.82 - }
506.83 -
506.84 - emitter = new ObjectName("Default:name=NotificationEmitter");
506.85 - mbeanServer.registerMBean(new NotificationEmitter(), emitter);
506.86 - boolean succeed = true;
506.87 -
506.88 - final String[] protos = new String[] {"rmi", "iiop", "jmxmp"};
506.89 - for (String proto : protos) {
506.90 - System.out.println(">>> FetchingTest-main: testing on "+proto);
506.91 -
506.92 - try {
506.93 - url = new JMXServiceURL(proto, null, 0) ;
506.94 - server = JMXConnectorServerFactory.
506.95 - newJMXConnectorServer(url, null, mbeanServer);
506.96 - server.start();
506.97 - } catch (Exception e) {
506.98 - // OK
506.99 - System.out.println(">>> FetchingTest-main: skip the proto "+proto);
506.100 - continue;
506.101 - }
506.102 -
506.103 - url = server.getAddress();
506.104 - conn = JMXConnectorFactory.connect(url, null);
506.105 - client = conn.getMBeanServerConnection();
506.106 -
506.107 - succeed &= test();
506.108 -
506.109 - conn.close();
506.110 - server.stop();
506.111 -
506.112 - System.out.println(
506.113 - ">>> FetchingTest-main: testing on "+proto+" done.");
506.114 - }
506.115 -
506.116 - if (succeed) {
506.117 - System.out.println(">>> FetchingTest-main: PASSED!");
506.118 - } else {
506.119 - System.out.println("\n>>> FetchingTest-main: FAILED!");
506.120 - System.exit(1);
506.121 - }
506.122 - }
506.123 -
506.124 - public static boolean test() throws Exception {
506.125 - System.out.println(">>> FetchingTest-test: " +
506.126 - "using the default fetching forwarder ...");
506.127 - EventClient eventClient =
506.128 - new EventClient(client);
506.129 -
506.130 - Listener listener = new Listener();
506.131 - eventClient.addNotificationListener(emitter, listener, null, null);
506.132 -
506.133 - // ask to send notifs
506.134 - Object[] params = new Object[] {new Integer(sendNB)};
506.135 - String[] signatures = new String[] {"java.lang.Integer"};
506.136 - conn.getMBeanServerConnection().invoke(emitter,
506.137 - "sendNotifications", params, signatures);
506.138 -
506.139 - if (listener.waitNotif(WAITING_TIME) != sendNB) {
506.140 - System.out.println(
506.141 - ">>> FetchingTest-test: FAILED! Expected to receive "+
506.142 - sendNB+", but got "+listener.received);
506.143 -
506.144 - return false;
506.145 - }
506.146 -
506.147 - System.out.println(
506.148 - ">>> ListenerTest-test: got all expected "+listener.received);
506.149 - //eventClient.removeNotificationListener(emitter, listener);
506.150 - eventClient.close();
506.151 -
506.152 - System.out.println(">>> FetchingTest-test: " +
506.153 - "using a user specific List ...");
506.154 -
506.155 - FetchingEventRelay fer = new FetchingEventRelay(
506.156 - EventClientDelegate.getProxy(client),
506.157 - 1000, 1000L, 1000, null,
506.158 - MyFetchingEventForwarder.class.getName(),
506.159 - null, null);
506.160 -
506.161 - eventClient = new EventClient(
506.162 - EventClientDelegate.getProxy(client), fer, null, null, 10000);
506.163 -
506.164 - eventClient.addNotificationListener(emitter, listener, null, null);
506.165 - listener.received = 0;
506.166 -
506.167 - conn.getMBeanServerConnection().invoke(emitter,
506.168 - "sendNotifications", params, signatures);
506.169 -
506.170 - if (listener.waitNotif(WAITING_TIME) != sendNB) {
506.171 - System.out.println(
506.172 - ">>> FetchingTest-test: FAILED! Expected to receive "+
506.173 - sendNB+", but got "+listener.received);
506.174 -
506.175 - return false;
506.176 - }
506.177 -
506.178 - System.out.println(
506.179 - ">>> FetchingTest-test: got all expected "+listener.received);
506.180 -
506.181 - if (!MyFetchingEventForwarder.shared.isUsed()) {
506.182 - System.out.println(
506.183 - ">>> FetchingTest-test: FAILED! The user specific list" +
506.184 - "is not used!");
506.185 -
506.186 - return false;
506.187 - }
506.188 -
506.189 - System.out.println(">>> Negative test to add an EventClient" +
506.190 - " with a non EventForwarder object.");
506.191 - try {
506.192 - MyFetchingEventForwarder.shared.setAgain();
506.193 -
506.194 - System.out.println(
506.195 - ">>> FetchingTest-test: FAILED! No expected exception" +
506.196 - "when setting the list after the forwarder started.");
506.197 -
506.198 - return false;
506.199 - } catch (IllegalStateException ise) {
506.200 - // OK
506.201 - System.out.println(
506.202 - ">>> FetchingTest-test: Got expected exception: " + ise);
506.203 - }
506.204 -
506.205 - eventClient.close();
506.206 -
506.207 - try {
506.208 - fer = new FetchingEventRelay(
506.209 - EventClientDelegate.getProxy(client),
506.210 - 1000, 1000L, 1000, null,
506.211 - Object.class.getName(),
506.212 - null, null);
506.213 -
506.214 - eventClient = new EventClient(
506.215 - EventClientDelegate.getProxy(client), fer, null, null, 10000);
506.216 -
506.217 - System.out.println(
506.218 - ">>> FetchingTest-test: FAILED! No expected exception" +
506.219 - "when creating an illegal EventForwarder");
506.220 - } catch (IllegalArgumentException iae) {
506.221 - // OK
506.222 - // iae.printStackTrace();
506.223 - }
506.224 -
506.225 - return true;
506.226 - }
506.227 -
506.228 - private static class Listener implements NotificationListener {
506.229 - public void handleNotification(Notification notif, Object handback) {
506.230 - synchronized(this) {
506.231 - if (++received >= sendNB) {
506.232 - this.notify();
506.233 - }
506.234 - }
506.235 -
506.236 - //System.out.println(">>> FetchingTest-Listener: received = "+received);
506.237 - }
506.238 -
506.239 - public int waitNotif(long timeout) throws Exception {
506.240 - synchronized(this) {
506.241 - long stopTime = System.currentTimeMillis() + timeout;
506.242 - long toWait = timeout;
506.243 - while (toWait > 0 && received < sendNB) {
506.244 - this.wait(toWait);
506.245 - toWait = stopTime - System.currentTimeMillis();
506.246 - }
506.247 - }
506.248 -
506.249 - return received;
506.250 - }
506.251 -
506.252 - public static int received = 0;
506.253 - }
506.254 -
506.255 - public static class NotificationEmitter extends NotificationBroadcasterSupport
506.256 - implements NotificationEmitterMBean {
506.257 -
506.258 - public void sendNotifications(Integer nb) {
506.259 - System.out.println(
506.260 - ">>> FetchingTest-NotificationEmitter-sendNotifications: "+nb);
506.261 - Notification notif;
506.262 - for (int i=1; i<=nb.intValue(); i++) {
506.263 - notif = new Notification(myType, this, count++);
506.264 - sendNotification(notif);
506.265 - }
506.266 - }
506.267 - }
506.268 -
506.269 - public interface NotificationEmitterMBean {
506.270 - public void sendNotifications(Integer nb);
506.271 - }
506.272 -
506.273 -
506.274 -
506.275 - private static int sendNB = 20;
506.276 - private static int count = 0;
506.277 -
506.278 - private static final String myType = "notification.my_notification";
506.279 -}
507.1 --- a/test/javax/management/eventService/LeaseManagerDeadlockTest.java Mon Nov 23 10:04:47 2009 +0000
507.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
507.3 @@ -1,98 +0,0 @@
507.4 -/*
507.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
507.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
507.7 - *
507.8 - * This code is free software; you can redistribute it and/or modify it
507.9 - * under the terms of the GNU General Public License version 2 only, as
507.10 - * published by the Free Software Foundation.
507.11 - *
507.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
507.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
507.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
507.15 - * version 2 for more details (a copy is included in the LICENSE file that
507.16 - * accompanied this code).
507.17 - *
507.18 - * You should have received a copy of the GNU General Public License version
507.19 - * 2 along with this work; if not, write to the Free Software Foundation,
507.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
507.21 - *
507.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
507.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
507.24 - * have any questions.
507.25 - */
507.26 -
507.27 -/*
507.28 - * @test
507.29 - * @bug 6717789
507.30 - * @summary Check that a lock is not held when a LeaseManager expires.
507.31 - * @author Eamonn McManus
507.32 - * @compile -XDignore.symbol.file=true LeaseManagerDeadlockTest.java
507.33 - * @run main LeaseManagerDeadlockTest
507.34 - */
507.35 -
507.36 -import com.sun.jmx.event.LeaseManager;
507.37 -import java.lang.management.ManagementFactory;
507.38 -import java.lang.management.ThreadMXBean;
507.39 -import java.util.Arrays;
507.40 -import java.util.concurrent.Semaphore;
507.41 -import java.util.concurrent.TimeUnit;
507.42 -
507.43 -public class LeaseManagerDeadlockTest {
507.44 - public static String failure;
507.45 - public static LeaseManager leaseManager;
507.46 - public static Semaphore callbackThreadCompleted = new Semaphore(0);
507.47 - public static Object lock = new Object();
507.48 -
507.49 - public static Runnable triggerDeadlock = new Runnable() {
507.50 - public void run() {
507.51 - Runnable pingLeaseManager = new Runnable() {
507.52 - public void run() {
507.53 - System.out.println("Ping thread starts");
507.54 - synchronized (lock) {
507.55 - leaseManager.lease(1);
507.56 - }
507.57 - System.out.println("Ping thread completes");
507.58 - }
507.59 - };
507.60 - Thread t = new Thread(pingLeaseManager);
507.61 - t.start();
507.62 - try {
507.63 - Thread.sleep(10); // enough time for ping thread to grab lock
507.64 - synchronized (lock) {
507.65 - t.join();
507.66 - }
507.67 - } catch (InterruptedException e) {
507.68 - fail(e.toString());
507.69 - }
507.70 - System.out.println("Callback thread completes");
507.71 - callbackThreadCompleted.release();
507.72 - }
507.73 - };
507.74 -
507.75 - public static void main(String[] args) throws Exception {
507.76 - // Also test that we can shorten the lease from its initial value.
507.77 - leaseManager = new LeaseManager(triggerDeadlock, 1000000);
507.78 - leaseManager.lease(1L);
507.79 -
507.80 - boolean callbackRan =
507.81 - callbackThreadCompleted.tryAcquire(3, TimeUnit.SECONDS);
507.82 -
507.83 - if (!callbackRan) {
507.84 - fail("Callback did not complete - probable deadlock");
507.85 - ThreadMXBean threads = ManagementFactory.getThreadMXBean();
507.86 - System.out.println(Arrays.toString(threads.findDeadlockedThreads()));
507.87 - System.out.println("PRESS RETURN");
507.88 - System.in.read();
507.89 - }
507.90 -
507.91 - if (failure == null)
507.92 - System.out.println("TEST PASSED");
507.93 - else
507.94 - throw new Exception("TEST FAILED: " + failure);
507.95 - }
507.96 -
507.97 - public static void fail(String why) {
507.98 - System.out.println("TEST FAILS: " + why);
507.99 - failure = why;
507.100 - }
507.101 -}
508.1 --- a/test/javax/management/eventService/LeaseTest.java Mon Nov 23 10:04:47 2009 +0000
508.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
508.3 @@ -1,361 +0,0 @@
508.4 -/*
508.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
508.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
508.7 - *
508.8 - * This code is free software; you can redistribute it and/or modify it
508.9 - * under the terms of the GNU General Public License version 2 only, as
508.10 - * published by the Free Software Foundation.
508.11 - *
508.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
508.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
508.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
508.15 - * version 2 for more details (a copy is included in the LICENSE file that
508.16 - * accompanied this code).
508.17 - *
508.18 - * You should have received a copy of the GNU General Public License version
508.19 - * 2 along with this work; if not, write to the Free Software Foundation,
508.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
508.21 - *
508.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
508.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
508.24 - * have any questions.
508.25 - */
508.26 -
508.27 -/*
508.28 - * @test LeaseTest.java 1.6 08/01/22
508.29 - * @bug 5108776
508.30 - * @summary Basic test for Event service leasing.
508.31 - * @author Shanliang JIANG
508.32 - * @run clean LeaseTest
508.33 - * @run build LeaseTest
508.34 - * @run main LeaseTest
508.35 - */
508.36 -
508.37 -
508.38 -import java.io.IOException;
508.39 -import java.util.ArrayList;
508.40 -import java.util.List;
508.41 -import javax.management.ListenerNotFoundException;
508.42 -import javax.management.MBeanNotificationInfo;
508.43 -import javax.management.MBeanServer;
508.44 -import javax.management.MBeanServerFactory;
508.45 -import javax.management.Notification;
508.46 -import javax.management.NotificationBroadcasterSupport;
508.47 -import javax.management.NotificationFilter;
508.48 -import javax.management.NotificationListener;
508.49 -import javax.management.ObjectName;
508.50 -import javax.management.event.EventClient;
508.51 -import javax.management.event.EventClientDelegate;
508.52 -import javax.management.event.EventClientDelegateMBean;
508.53 -import javax.management.event.EventClientNotFoundException;
508.54 -import javax.management.event.FetchingEventRelay;
508.55 -import javax.management.remote.JMXConnector;
508.56 -import javax.management.remote.JMXConnectorFactory;
508.57 -import javax.management.remote.JMXConnectorServer;
508.58 -import javax.management.remote.JMXConnectorServerFactory;
508.59 -import javax.management.remote.JMXServiceURL;
508.60 -
508.61 -public class LeaseTest {
508.62 -
508.63 - private static MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer();
508.64 - private static List<Notification> notifList = new ArrayList<Notification>();
508.65 - private static ObjectName emitter;
508.66 - private static NotificationEmitter emitterImpl;
508.67 - private static JMXServiceURL url;
508.68 - private static JMXConnectorServer server;
508.69 - private static JMXConnector conn;
508.70 - private static Listener listener = new Listener();
508.71 -
508.72 - private static long leaseTime = 100;
508.73 - private static final int multiple = 5;
508.74 - private static final long bigWaiting = 6000;
508.75 -
508.76 - public static void main(String[] args) throws Exception {
508.77 - System.out.println(">>> Test the event service lease");
508.78 -
508.79 - // for 1.5
508.80 - if (System.getProperty("java.version").startsWith("1.5") &&
508.81 - !mbeanServer.isRegistered(EventClientDelegateMBean.OBJECT_NAME)) {
508.82 - System.out.print("Working on "+System.getProperty("java.version")+
508.83 - " register "+EventClientDelegateMBean.OBJECT_NAME);
508.84 -
508.85 - mbeanServer.registerMBean(EventClientDelegate.
508.86 - getEventClientDelegate(mbeanServer),
508.87 - EventClientDelegateMBean.OBJECT_NAME);
508.88 - }
508.89 -
508.90 - System.setProperty("com.sun.event.lease.time",
508.91 - String.valueOf(leaseTime));
508.92 - emitter = new ObjectName("Default:name=NotificationEmitter");
508.93 - emitterImpl = new NotificationEmitter();
508.94 - mbeanServer.registerMBean(emitterImpl, emitter);
508.95 -
508.96 - String[] types = new String[]{"PushingEventRelay", "FetchingEventRelay"};
508.97 - String[] protos = new String[]{"rmi", "iiop", "jmxmp"};
508.98 - for (String prot : protos) {
508.99 - url = new JMXServiceURL(prot, null, 0);
508.100 -
508.101 - try {
508.102 - server =
508.103 - JMXConnectorServerFactory.newJMXConnectorServer(url,
508.104 - null, mbeanServer);
508.105 - server.start();
508.106 - } catch (Exception e) {
508.107 - System.out.println(">>> Skip "+prot+", not support.");
508.108 - continue;
508.109 - }
508.110 -
508.111 - url = server.getAddress();
508.112 -
508.113 - try {
508.114 - for (String type: types) {
508.115 - test(type);
508.116 - }
508.117 - } finally {
508.118 - server.stop();
508.119 - }
508.120 - }
508.121 - }
508.122 -
508.123 - private static void test(String type) throws Exception {
508.124 - System.out.println("\n\n>>> Testing "+type+" on "+url+" ...");
508.125 - newConn();
508.126 - EventClient ec = newEventClient(type);
508.127 -
508.128 - ec.addNotificationListener(emitter,
508.129 - listener, null, null);
508.130 -
508.131 - System.out.println(">>> Send a notification and should receive it.");
508.132 - emitterImpl.sendNotif(++counter);
508.133 -
508.134 - if (!waitNotif(bigWaiting, counter)) {
508.135 - throw new RuntimeException(">>> Failed to receive notif.");
508.136 - }
508.137 -
508.138 - System.out.println(">>> Sleep 3 times of requested lease time.");
508.139 - Thread.sleep(leaseTime*3);
508.140 - System.out.println(">>> Send again a notification and should receive it.");
508.141 - emitterImpl.sendNotif(++counter);
508.142 -
508.143 - if (!waitNotif(bigWaiting, counter)) {
508.144 - throw new RuntimeException(">>> Failed to receive notif.");
508.145 - }
508.146 -
508.147 - System.out.println(">>> Close the client connection: "+
508.148 - conn.getConnectionId());
508.149 - conn.close();
508.150 -
508.151 - System.out.println(">>> Waiting lease timeout to do clean.");
508.152 -
508.153 - if (!emitterImpl.waitingClean(leaseTime*multiple)) {
508.154 - throw new RuntimeException(
508.155 - ">>> The event lease failed to do clean: "+
508.156 - emitterImpl.listenerSize);
508.157 - } else {
508.158 - System.out.println(">>> The listener has been removed.");
508.159 - }
508.160 -
508.161 - // Check that the client id has indeed been removed, by trying to
508.162 - // remove it again, which should fail.
508.163 - newConn();
508.164 - try {
508.165 - EventClientDelegateMBean proxy =
508.166 - EventClientDelegate.getProxy(conn.getMBeanServerConnection());
508.167 - proxy.removeClient(ec.getEventRelay().getClientId());
508.168 -
508.169 - throw new RuntimeException(
508.170 - ">>> The client id is not removed.");
508.171 - } catch (EventClientNotFoundException ecnfe) {
508.172 - // OK
508.173 - System.out.println(">>> The client id has been removed.");
508.174 - }
508.175 - conn.close();
508.176 -
508.177 - System.out.println(">>> Reconnect to the server.");
508.178 - newConn();
508.179 -
508.180 - System.out.println(">>> Create a new EventClient and add the listeners" +
508.181 - " in the failed EventClient into new EventClient");
508.182 - EventClient newEC = newEventClient(type);
508.183 - newEC.addListeners(ec.getListeners());
508.184 - // We expect ec.close() to get IOException because we closed the
508.185 - // underlying connection.
508.186 - try {
508.187 - ec.close();
508.188 - throw new RuntimeException(">>> EventClient.close did not throw " +
508.189 - "expected IOException");
508.190 - } catch (IOException e) {
508.191 - System.out.println(">>> EventClient.close threw expected exception: " + e);
508.192 - }
508.193 -
508.194 - emitterImpl.sendNotif(++counter);
508.195 -
508.196 - if (!waitNotif(bigWaiting, counter)) {
508.197 - throw new RuntimeException(">>> The event client failed to add " +
508.198 - "all old registered listeners after re-connection.");
508.199 - } else {
508.200 - System.out.println(">>> Successfully received notification from" +
508.201 - " new EventClient.");
508.202 - }
508.203 -
508.204 - System.out.println(">>> Clean the failed EventClient.");
508.205 - ec.close();
508.206 - if (ec.getListeners().size() != 0) {
508.207 - throw new RuntimeException(">>> The event client fails to do clean.");
508.208 - }
508.209 -
508.210 - System.out.println(">>> Clean the new EventClient.");
508.211 - newEC.close();
508.212 - if (newEC.getListeners().size() != 0) {
508.213 - throw new RuntimeException(">>> The event client fails to do clean.");
508.214 - }
508.215 -
508.216 - conn.close();
508.217 - System.out.println(">>> Testing "+type+" on "+url+" ... done");
508.218 - }
508.219 -
508.220 - private static boolean waitNotif(long time, int sequenceNumber)
508.221 - throws Exception {
508.222 - synchronized(notifList) {
508.223 - if (search(sequenceNumber)) {
508.224 - return true;
508.225 - }
508.226 -
508.227 - long stopTime = System.currentTimeMillis() + time;
508.228 - long toWait = time;
508.229 - while (toWait > 0) {
508.230 - notifList.wait(toWait);
508.231 -
508.232 - if (search(sequenceNumber)) {
508.233 - return true;
508.234 - }
508.235 -
508.236 - toWait = stopTime - System.currentTimeMillis();
508.237 - }
508.238 -
508.239 - return false;
508.240 - }
508.241 - }
508.242 -
508.243 - private static boolean search(int sequenceNumber) {
508.244 - while(notifList.size() > 0) {
508.245 - Notification n = notifList.remove(0);
508.246 - if (n.getSequenceNumber() == sequenceNumber) {
508.247 - return true;
508.248 - }
508.249 - }
508.250 -
508.251 - return false;
508.252 - }
508.253 -
508.254 -//--------------------------
508.255 -// private classes
508.256 -//--------------------------
508.257 -
508.258 - private static class Listener implements NotificationListener {
508.259 - public void handleNotification(Notification notif, Object handback) {
508.260 - synchronized (notifList) {
508.261 - notifList.add(notif);
508.262 - notifList.notify();
508.263 - }
508.264 - }
508.265 - }
508.266 -
508.267 - public static class NotificationEmitter extends NotificationBroadcasterSupport
508.268 - implements NotificationEmitterMBean {
508.269 -
508.270 - public MBeanNotificationInfo[] getNotificationInfo() {
508.271 - final String[] ntfTypes = {myType};
508.272 -
508.273 - final MBeanNotificationInfo[] ntfInfoArray = {
508.274 - new MBeanNotificationInfo(ntfTypes,
508.275 - "javax.management.Notification",
508.276 - "Notifications sent by the NotificationEmitter")};
508.277 -
508.278 - return ntfInfoArray;
508.279 - }
508.280 -
508.281 - /**
508.282 - * Send Notification objects.
508.283 - *
508.284 - * @param nb The number of notifications to send
508.285 - */
508.286 - public void sendNotif(int sequenceNumber) {
508.287 - Notification notif = new Notification(myType, this, sequenceNumber);
508.288 - sendNotification(notif);
508.289 - }
508.290 -
508.291 - public void addNotificationListener(NotificationListener listener,
508.292 - NotificationFilter filter, Object handback) {
508.293 - super.addNotificationListener(listener, filter, handback);
508.294 -
508.295 - listenerSize++;
508.296 - }
508.297 -
508.298 - public void removeNotificationListener(NotificationListener listener)
508.299 - throws ListenerNotFoundException {
508.300 - super.removeNotificationListener(listener);
508.301 - listenerSize--;
508.302 -
508.303 - synchronized(this) {
508.304 - if (listenerSize == 0) {
508.305 - this.notifyAll();
508.306 - }
508.307 - }
508.308 - }
508.309 -
508.310 - public void removeNotificationListener(NotificationListener listener,
508.311 - NotificationFilter filter, Object handback)
508.312 - throws ListenerNotFoundException {
508.313 - super.removeNotificationListener(listener, filter, handback);
508.314 - listenerSize--;
508.315 -
508.316 - synchronized(this) {
508.317 - if (listenerSize == 0) {
508.318 - this.notifyAll();
508.319 - }
508.320 - }
508.321 - }
508.322 -
508.323 - public boolean waitingClean(long timeout) throws Exception {
508.324 - synchronized(this) {
508.325 - long stopTime = System.currentTimeMillis() + timeout;
508.326 - long toWait = timeout;
508.327 - while (listenerSize != 0 && toWait > 0) {
508.328 - this.wait(toWait);
508.329 - toWait = stopTime - System.currentTimeMillis();
508.330 - }
508.331 - }
508.332 -
508.333 - return listenerSize == 0;
508.334 - }
508.335 -
508.336 - public int listenerSize = 0;
508.337 -
508.338 - private final String myType = "notification.my_notification";
508.339 - }
508.340 -
508.341 - public interface NotificationEmitterMBean {
508.342 - public void sendNotif(int sequenceNumber);
508.343 - }
508.344 -
508.345 - private static void newConn() throws IOException {
508.346 - conn = JMXConnectorFactory.connect(url);
508.347 - }
508.348 -
508.349 - private static EventClient newEventClient(String type) throws Exception {
508.350 - EventClientDelegateMBean proxy =
508.351 - EventClientDelegate.getProxy(conn.getMBeanServerConnection());
508.352 - if (type.equals("PushingEventRelay")) {
508.353 - return new EventClient(proxy,
508.354 - new FetchingEventRelay(proxy), null, null, leaseTime);
508.355 - } else if (type.equals("FetchingEventRelay")) {
508.356 - return new EventClient(proxy,
508.357 - new FetchingEventRelay(proxy), null, null, leaseTime);
508.358 - } else {
508.359 - throw new RuntimeException("Wrong event client type: "+type);
508.360 - }
508.361 - }
508.362 -
508.363 - private static int counter = 0;
508.364 -}
509.1 --- a/test/javax/management/eventService/ListenerTest.java Mon Nov 23 10:04:47 2009 +0000
509.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
509.3 @@ -1,224 +0,0 @@
509.4 -/*
509.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
509.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
509.7 - *
509.8 - * This code is free software; you can redistribute it and/or modify it
509.9 - * under the terms of the GNU General Public License version 2 only, as
509.10 - * published by the Free Software Foundation.
509.11 - *
509.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
509.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
509.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
509.15 - * version 2 for more details (a copy is included in the LICENSE file that
509.16 - * accompanied this code).
509.17 - *
509.18 - * You should have received a copy of the GNU General Public License version
509.19 - * 2 along with this work; if not, write to the Free Software Foundation,
509.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
509.21 - *
509.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
509.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
509.24 - * have any questions.
509.25 - */
509.26 -
509.27 -/*
509.28 - * @test ListenerTest.java 1.7 08/01/22
509.29 - * @bug 5108776
509.30 - * @summary Basic test for EventClient.
509.31 - * @author Shanliang JIANG
509.32 - * @run clean ListenerTest
509.33 - * @run build ListenerTest
509.34 - * @run main ListenerTest
509.35 - */
509.36 -
509.37 -import javax.management.MBeanNotificationInfo;
509.38 -import javax.management.MBeanServer;
509.39 -import javax.management.MBeanServerConnection;
509.40 -import javax.management.MBeanServerFactory;
509.41 -import javax.management.Notification;
509.42 -import javax.management.NotificationBroadcasterSupport;
509.43 -import javax.management.NotificationListener;
509.44 -import javax.management.ObjectName;
509.45 -import javax.management.event.*;
509.46 -import javax.management.remote.JMXConnector;
509.47 -import javax.management.remote.JMXConnectorFactory;
509.48 -import javax.management.remote.JMXConnectorServer;
509.49 -import javax.management.remote.JMXConnectorServerFactory;
509.50 -import javax.management.remote.JMXServiceURL;
509.51 -
509.52 -/**
509.53 - *
509.54 - */
509.55 -public class ListenerTest {
509.56 - private static MBeanServer mbeanServer;
509.57 - private static ObjectName emitter;
509.58 - private static JMXServiceURL url;
509.59 - private static JMXConnectorServer server;
509.60 - private static JMXConnector conn;
509.61 - private static MBeanServerConnection client;
509.62 -
509.63 - /**
509.64 - * @param args the command line arguments
509.65 - */
509.66 - public static void main(String[] args) throws Exception {
509.67 -
509.68 - System.out.println(">>> ListenerTest-main basic tests ...");
509.69 - mbeanServer = MBeanServerFactory.createMBeanServer();
509.70 -
509.71 - // for 1.5
509.72 - if (System.getProperty("java.version").startsWith("1.5") &&
509.73 - !mbeanServer.isRegistered(EventClientDelegateMBean.OBJECT_NAME)) {
509.74 - System.out.print("Working on "+System.getProperty("java.version")+
509.75 - " register "+EventClientDelegateMBean.OBJECT_NAME);
509.76 -
509.77 - mbeanServer.registerMBean(EventClientDelegate.
509.78 - getEventClientDelegate(mbeanServer),
509.79 - EventClientDelegateMBean.OBJECT_NAME);
509.80 - }
509.81 -
509.82 - emitter = new ObjectName("Default:name=NotificationEmitter");
509.83 -
509.84 - url = new JMXServiceURL("rmi", null, 0) ;
509.85 - server =
509.86 - JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbeanServer);
509.87 - server.start();
509.88 -
509.89 - url = server.getAddress();
509.90 - conn = JMXConnectorFactory.connect(url, null);
509.91 - client = conn.getMBeanServerConnection();
509.92 -
509.93 - mbeanServer.registerMBean(new NotificationEmitter(), emitter);
509.94 -
509.95 - boolean succeed;
509.96 -
509.97 - System.out.println(">>> ListenerTest-main: using the fetching EventRelay...");
509.98 - succeed = test(new EventClient(client));
509.99 -
509.100 - System.out.println(">>> ListenerTest-main: using the pushing EventRelay...");
509.101 - EventClientDelegateMBean ecd = EventClientDelegate.getProxy(client);
509.102 - succeed &= test(new EventClient(ecd,
509.103 - new RMIPushEventRelay(ecd),
509.104 - null, null,
509.105 - EventClient.DEFAULT_REQUESTED_LEASE_TIME));
509.106 -
509.107 - conn.close();
509.108 - server.stop();
509.109 -
509.110 - if (succeed) {
509.111 - System.out.println(">>> ListenerTest-main: PASSED!");
509.112 - } else {
509.113 - System.out.println("\n>>> ListenerTest-main: FAILED!");
509.114 - System.exit(1);
509.115 - }
509.116 - }
509.117 -
509.118 - public static boolean test(EventClient efClient) throws Exception {
509.119 - // add listener from the client side
509.120 - Listener listener = new Listener();
509.121 - efClient.addNotificationListener(emitter, listener, null, null);
509.122 -
509.123 - // ask to send notifs
509.124 - Object[] params = new Object[] {new Integer(sendNB)};
509.125 - String[] signatures = new String[] {"java.lang.Integer"};
509.126 - client.invoke(emitter, "sendNotifications", params, signatures);
509.127 -
509.128 - // waiting
509.129 - long toWait = 6000;
509.130 - long stopTime = System.currentTimeMillis() + toWait;
509.131 -
509.132 - synchronized(listener) {
509.133 - while(listener.received < sendNB && toWait > 0) {
509.134 - listener.wait(toWait);
509.135 - toWait = stopTime - System.currentTimeMillis();
509.136 - }
509.137 - }
509.138 -
509.139 - // clean
509.140 - efClient.removeNotificationListener(emitter, listener, null, null);
509.141 - efClient.close();
509.142 -
509.143 - if (listener.received != sendNB) {
509.144 - System.out.println(">>> ListenerTest-test: FAILED! Expected to receive "+sendNB+", but got "+listener.received);
509.145 -
509.146 - return false;
509.147 - } else if (listener.seqErr > 0) {
509.148 - System.out.println(">>> ListenerTest-test: FAILED! The receiving sequence is not correct.");
509.149 -
509.150 - return false;
509.151 - } else {
509.152 - System.out.println(">>> ListenerTest-test: got all expected "+listener.received);
509.153 - return true;
509.154 - }
509.155 - }
509.156 -
509.157 - private static class Listener implements NotificationListener {
509.158 - public int received = 0;
509.159 - public int seqErr = 0;
509.160 -
509.161 - private long lastSeq = -1;
509.162 -
509.163 - public void handleNotification(Notification notif, Object handback) {
509.164 - if (!myType.equals(notif.getType())) {
509.165 - System.out.println(">>> EventManagerTest-Listener: got unexpected notif: "+notif);
509.166 - System.exit(1);
509.167 - }
509.168 -
509.169 - if (lastSeq == -1) {
509.170 - lastSeq = notif.getSequenceNumber();
509.171 - } else if (notif.getSequenceNumber() - lastSeq++ != 1) {
509.172 - seqErr++;
509.173 - }
509.174 -
509.175 - System.out.println(">>> ListenerTest-Listener: got notif "+notif.getSequenceNumber());
509.176 -
509.177 - synchronized(this) {
509.178 - if (++received >= sendNB) {
509.179 - this.notify();
509.180 - }
509.181 - }
509.182 -
509.183 - System.out.println(">>> ListenerTest-Listener: received = "+received);
509.184 - }
509.185 - }
509.186 -
509.187 - public static class NotificationEmitter extends NotificationBroadcasterSupport
509.188 - implements NotificationEmitterMBean {
509.189 -
509.190 - public MBeanNotificationInfo[] getNotificationInfo() {
509.191 - final String[] ntfTypes = {myType};
509.192 -
509.193 - final MBeanNotificationInfo[] ntfInfoArray = {
509.194 - new MBeanNotificationInfo(ntfTypes,
509.195 - "javax.management.Notification",
509.196 - "Notifications sent by the NotificationEmitter")};
509.197 -
509.198 - return ntfInfoArray;
509.199 - }
509.200 -
509.201 - /**
509.202 - * Send Notification objects.
509.203 - *
509.204 - * @param nb The number of notifications to send
509.205 - */
509.206 - public void sendNotifications(Integer nb) {
509.207 - Notification notif;
509.208 - for (int i=1; i<=nb.intValue(); i++) {
509.209 - notif = new Notification(myType, this, count++);
509.210 - //System.out.println(">>> ListenerTest-NotificationEmitter-sendNotifications: "+i);
509.211 -
509.212 - sendNotification(notif);
509.213 - }
509.214 - }
509.215 -
509.216 -
509.217 - }
509.218 -
509.219 - public interface NotificationEmitterMBean {
509.220 - public void sendNotifications(Integer nb);
509.221 - }
509.222 -
509.223 - private static int sendNB = 20;
509.224 - private static int count = 0;
509.225 -
509.226 - private static final String myType = "notification.my_notification";
509.227 -}
510.1 --- a/test/javax/management/eventService/MyFetchingEventForwarder.java Mon Nov 23 10:04:47 2009 +0000
510.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
510.3 @@ -1,53 +0,0 @@
510.4 -/*
510.5 - * MyList.java
510.6 - *
510.7 - * Created on Oct 23, 2007, 2:45:57 PM
510.8 - *
510.9 - * To change this template, choose Tools | Templates
510.10 - * and open the template in the editor.
510.11 - */
510.12 -
510.13 -/**
510.14 - *
510.15 - * @author sjiang
510.16 - */
510.17 -
510.18 -import java.io.IOException;
510.19 -import java.util.ArrayList;
510.20 -import javax.management.event.FetchingEventForwarder;
510.21 -
510.22 -public class MyFetchingEventForwarder extends FetchingEventForwarder {
510.23 -
510.24 - public MyFetchingEventForwarder() {
510.25 - super(1000);
510.26 - shared = this;
510.27 - setList(myList);
510.28 - }
510.29 -
510.30 - public void setAgain() {
510.31 - setList(myList);
510.32 - }
510.33 -
510.34 - public void setClientId(String clientId) throws IOException {
510.35 - used = true;
510.36 - super.setClientId(clientId);
510.37 - }
510.38 -
510.39 - public boolean isUsed() {
510.40 - return used;
510.41 - }
510.42 -
510.43 - private class MyList<TargetedNotification>
510.44 - extends ArrayList<TargetedNotification> {
510.45 -
510.46 - public boolean add(TargetedNotification e) {
510.47 - used = true;
510.48 -
510.49 - return super.add(e);
510.50 - }
510.51 - }
510.52 -
510.53 - public MyList myList = new MyList();
510.54 - public static MyFetchingEventForwarder shared;
510.55 - private boolean used = false;
510.56 -}
511.1 --- a/test/javax/management/eventService/NotSerializableNotifTest.java Mon Nov 23 10:04:47 2009 +0000
511.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
511.3 @@ -1,227 +0,0 @@
511.4 -/*
511.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
511.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
511.7 - *
511.8 - * This code is free software; you can redistribute it and/or modify it
511.9 - * under the terms of the GNU General Public License version 2 only, as
511.10 - * published by the Free Software Foundation.
511.11 - *
511.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
511.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
511.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
511.15 - * version 2 for more details (a copy is included in the LICENSE file that
511.16 - * accompanied this code).
511.17 - *
511.18 - * You should have received a copy of the GNU General Public License version
511.19 - * 2 along with this work; if not, write to the Free Software Foundation,
511.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
511.21 - *
511.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
511.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
511.24 - * have any questions.
511.25 - */
511.26 -
511.27 -
511.28 -/*
511.29 - * @test NotSerializableNotifTest.java 1.5 08/01/22
511.30 - * @bug 5108776
511.31 - * @summary Basic test for EventClient.
511.32 - * @author Shanliang JIANG
511.33 - * @run clean NotSerializableNotifTest
511.34 - * @run build NotSerializableNotifTest
511.35 - * @run main NotSerializableNotifTest
511.36 - */
511.37 -
511.38 -
511.39 -// JMX imports
511.40 -//
511.41 -import javax.management.* ;
511.42 -import javax.management.event.EventClient;
511.43 -import javax.management.event.EventClientDelegate;
511.44 -import javax.management.event.EventClientDelegateMBean;
511.45 -import javax.management.event.EventRelay;
511.46 -import javax.management.event.FetchingEventRelay;
511.47 -
511.48 -import javax.management.remote.*;
511.49 -import javax.management.remote.JMXServiceURL;
511.50 -
511.51 -public class NotSerializableNotifTest {
511.52 - private static MBeanServer mbeanServer =
511.53 - MBeanServerFactory.createMBeanServer();
511.54 - private static ObjectName emitter;
511.55 - private static int port = 2468;
511.56 -
511.57 - private static String[] protocols;
511.58 -
511.59 - private static final int sentNotifs = 50;
511.60 -
511.61 - public static void main(String[] args) throws Exception {
511.62 - System.out.println(">>> Test to send a not serializable notification");
511.63 -
511.64 - // for 1.5
511.65 - if (System.getProperty("java.version").startsWith("1.5") &&
511.66 - !mbeanServer.isRegistered(EventClientDelegateMBean.OBJECT_NAME)) {
511.67 - System.out.print("Working on "+System.getProperty("java.version")+
511.68 - " register "+EventClientDelegateMBean.OBJECT_NAME);
511.69 -
511.70 - mbeanServer.registerMBean(EventClientDelegate.
511.71 - getEventClientDelegate(mbeanServer),
511.72 - EventClientDelegateMBean.OBJECT_NAME);
511.73 - }
511.74 -
511.75 - NotificationEmitter nm = new NotificationEmitter();
511.76 - emitter = new ObjectName("Default:name=NotificationEmitter");
511.77 - mbeanServer.registerMBean(nm, emitter);
511.78 - String proto = "rmi";
511.79 -
511.80 - System.out.println(">>> Test for protocol " + proto);
511.81 -
511.82 - JMXServiceURL url = new JMXServiceURL(proto, null, 0);
511.83 -
511.84 - JMXConnectorServer server =
511.85 - JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbeanServer);
511.86 -
511.87 - server.start();
511.88 -
511.89 - url = server.getAddress();
511.90 - JMXConnector conn = JMXConnectorFactory.connect(url, null);
511.91 - MBeanServerConnection client = conn.getMBeanServerConnection();
511.92 -
511.93 - EventClientDelegateMBean ecd = EventClientDelegate.getProxy(client);
511.94 - EventRelay eventRelay = new FetchingEventRelay(
511.95 - ecd,
511.96 - FetchingEventRelay.DEFAULT_BUFFER_SIZE,
511.97 - 10,
511.98 - FetchingEventRelay.DEFAULT_MAX_NOTIFICATIONS,
511.99 - null);
511.100 - EventClient ec = new EventClient(ecd, eventRelay, null, null,
511.101 - EventClient.DEFAULT_REQUESTED_LEASE_TIME);
511.102 -
511.103 - // add listener from the client side
511.104 - Listener listener = new Listener();
511.105 - ec.addNotificationListener(emitter, listener, null, null);
511.106 -
511.107 - LostListener lostListener = new LostListener();
511.108 - ec.addEventClientListener(lostListener, null, null);
511.109 -
511.110 - // ask to send one not serializable notif
511.111 - System.out.println(">>> sending not serializable notifs ...");
511.112 -
511.113 - Object[] params = new Object[] {new Integer(sentNotifs)};
511.114 - String[] signatures = new String[] {"java.lang.Integer"};
511.115 - client.invoke(emitter, "sendNotserializableNotifs", params, signatures);
511.116 -
511.117 -// nm.sendNotserializableNotifs(sentNotifs);
511.118 -// nm.sendNotifications(1);
511.119 -
511.120 - // waiting
511.121 - synchronized(lostListener) {
511.122 - if (lostListener.lostCount != sentNotifs) {
511.123 - lostListener.wait(6000);
511.124 - }
511.125 - }
511.126 -
511.127 - Thread.sleep(100);
511.128 -
511.129 - if (lostListener.lostCount != sentNotifs) {
511.130 - System.out.println(">>> FAILED. Expected "+sentNotifs+", but got "+lostListener.lostCount);
511.131 - System.exit(1);
511.132 - }
511.133 -
511.134 - System.out.println(">>> Passed.");
511.135 -
511.136 - ec.close();
511.137 - conn.close();
511.138 - server.stop();
511.139 - }
511.140 -
511.141 -
511.142 -//--------------------------
511.143 -// private classes
511.144 -//--------------------------
511.145 - private static class Listener implements NotificationListener {
511.146 - public void handleNotification(Notification n, Object handback) {
511.147 - System.out.println(">>> Listener: receive: "+n);
511.148 - }
511.149 - }
511.150 -
511.151 -
511.152 - private static class LostListener implements NotificationListener {
511.153 - public void handleNotification(Notification n, Object handback) {
511.154 - if (!EventClient.NOTIFS_LOST.equals(n.getType())) {
511.155 - return;
511.156 - }
511.157 -
511.158 - if (!(n.getUserData() instanceof Long)) {
511.159 - System.out.println(">>> Listener: JMXConnectionNotification userData " +
511.160 - "not a Long: " + n.getUserData());
511.161 - System.exit(1);
511.162 - } else {
511.163 - int lost = ((Long) n.getUserData()).intValue();
511.164 - lostCount += lost;
511.165 - if (lostCount >= sentNotifs) {
511.166 - synchronized(this) {
511.167 - this.notifyAll();
511.168 - }
511.169 - }
511.170 - }
511.171 -
511.172 - }
511.173 -
511.174 -
511.175 - private int lostCount = 0;
511.176 - }
511.177 -
511.178 - public static class NotificationEmitter extends NotificationBroadcasterSupport
511.179 - implements NotificationEmitterMBean {
511.180 -
511.181 - public MBeanNotificationInfo[] getNotificationInfo() {
511.182 - final String[] ntfTypes = {myType};
511.183 -
511.184 - final MBeanNotificationInfo[] ntfInfoArray = {
511.185 - new MBeanNotificationInfo(ntfTypes,
511.186 - "javax.management.Notification",
511.187 - "Notifications sent by the NotificationEmitter")};
511.188 -
511.189 - return ntfInfoArray;
511.190 - }
511.191 -
511.192 - /**
511.193 - * Send not serializable Notifications.
511.194 - *
511.195 - * @param nb The number of notifications to send
511.196 - */
511.197 - public void sendNotserializableNotifs(Integer nb) {
511.198 -
511.199 - Notification notif;
511.200 - for (int i=1; i<=nb.intValue(); i++) {
511.201 - notif = new Notification(myType, this, i);
511.202 -
511.203 - notif.setUserData(new Object());
511.204 - sendNotification(notif);
511.205 - }
511.206 - }
511.207 -
511.208 - /**
511.209 - * Send Notification objects.
511.210 - *
511.211 - * @param nb The number of notifications to send
511.212 - */
511.213 - public void sendNotifications(Integer nb) {
511.214 - Notification notif;
511.215 - for (int i=1; i<=nb.intValue(); i++) {
511.216 - notif = new Notification(myType, this, i);
511.217 -
511.218 - sendNotification(notif);
511.219 - }
511.220 - }
511.221 -
511.222 - private final String myType = "notification.my_notification";
511.223 - }
511.224 -
511.225 - public interface NotificationEmitterMBean {
511.226 - public void sendNotifications(Integer nb);
511.227 -
511.228 - public void sendNotserializableNotifs(Integer nb);
511.229 - }
511.230 -}
512.1 --- a/test/javax/management/eventService/PublishTest.java Mon Nov 23 10:04:47 2009 +0000
512.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
512.3 @@ -1,184 +0,0 @@
512.4 -/*
512.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
512.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
512.7 - *
512.8 - * This code is free software; you can redistribute it and/or modify it
512.9 - * under the terms of the GNU General Public License version 2 only, as
512.10 - * published by the Free Software Foundation.
512.11 - *
512.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
512.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
512.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
512.15 - * version 2 for more details (a copy is included in the LICENSE file that
512.16 - * accompanied this code).
512.17 - *
512.18 - * You should have received a copy of the GNU General Public License version
512.19 - * 2 along with this work; if not, write to the Free Software Foundation,
512.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
512.21 - *
512.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
512.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
512.24 - * have any questions.
512.25 - */
512.26 -
512.27 -import javax.management.MBeanServer;
512.28 -import javax.management.MBeanServerConnection;
512.29 -import javax.management.MBeanServerFactory;
512.30 -import javax.management.Notification;
512.31 -import javax.management.NotificationListener;
512.32 -import javax.management.ObjectName;
512.33 -import javax.management.event.*;
512.34 -import javax.management.remote.JMXConnector;
512.35 -import javax.management.remote.JMXConnectorFactory;
512.36 -import javax.management.remote.JMXConnectorServer;
512.37 -import javax.management.remote.JMXConnectorServerFactory;
512.38 -import javax.management.remote.JMXServiceURL;
512.39 -
512.40 -/**
512.41 - *
512.42 - */
512.43 -public class PublishTest {
512.44 - private static MBeanServer mbeanServer;
512.45 - private static EventManager eventManager;
512.46 - private static ObjectName emitter;
512.47 - private static JMXServiceURL url;
512.48 - private static JMXConnectorServer server;
512.49 - private static JMXConnector conn;
512.50 - private static MBeanServerConnection client;
512.51 -
512.52 - /**
512.53 - * @param args the command line arguments
512.54 - */
512.55 - public static void main(String[] args) throws Exception {
512.56 - System.out.println(">>> PublishTest-main basic tests ...");
512.57 - mbeanServer = MBeanServerFactory.createMBeanServer();
512.58 -
512.59 - // for 1.5
512.60 - if (System.getProperty("java.version").startsWith("1.5") &&
512.61 - !mbeanServer.isRegistered(EventClientDelegateMBean.OBJECT_NAME)) {
512.62 - System.out.print("Working on "+System.getProperty("java.version")+
512.63 - " register "+EventClientDelegateMBean.OBJECT_NAME);
512.64 -
512.65 - mbeanServer.registerMBean(EventClientDelegate.
512.66 - getEventClientDelegate(mbeanServer),
512.67 - EventClientDelegateMBean.OBJECT_NAME);
512.68 - }
512.69 -
512.70 - eventManager = EventManager.getEventManager(mbeanServer);
512.71 -
512.72 - emitter = new ObjectName("Default:name=NotificationEmitter");
512.73 -
512.74 - url = new JMXServiceURL("rmi", null, 0) ;
512.75 - server =
512.76 - JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbeanServer);
512.77 - server.start();
512.78 -
512.79 - url = server.getAddress();
512.80 - conn = JMXConnectorFactory.connect(url, null);
512.81 - client = conn.getMBeanServerConnection();
512.82 -
512.83 - boolean succeed;
512.84 -
512.85 - System.out.println(">>> PublishTest-main: using the fetching EventRelay...");
512.86 - succeed = test(new EventClient(client));
512.87 -
512.88 - System.out.println(">>> PublishTest-main: using the pushing EventRelay...");
512.89 - succeed &= test(new EventClient(client,
512.90 - new RMIPushEventRelay(EventClientDelegate.getProxy(client)),
512.91 - null,
512.92 - EventClient.DEFAULT_LEASE_TIMEOUT));
512.93 -
512.94 - conn.close();
512.95 - server.stop();
512.96 -
512.97 - if (succeed) {
512.98 - System.out.println(">>> PublishTest-main: PASSE!");
512.99 - } else {
512.100 - System.out.println("\n>>> PublishTest-main: FAILED!");
512.101 - System.exit(1);
512.102 - }
512.103 - }
512.104 -
512.105 - public static boolean test(EventClient efClient) throws Exception {
512.106 - // add listener from the client side
512.107 - Listener listener = new Listener();
512.108 - efClient.subscribe(emitter, listener, null, null);
512.109 -
512.110 - ObjectName other = new ObjectName("Default:name=other");
512.111 - // publish notifs
512.112 - for (int i=0; i<sendNB; i++) {
512.113 - Notification notif = new Notification(myType, emitter, count++);
512.114 - Notification notif2 = new Notification(myType, other, 0);
512.115 - //System.out.println(">>> EventManagerService-NotificationEmitter-sendNotifications: "+i);
512.116 -
512.117 - eventManager.publish(emitter, notif);
512.118 - eventManager.publish(other, notif2); // should not received
512.119 - }
512.120 -
512.121 - // waiting
512.122 - long toWait = 6000;
512.123 - long stopTime = System.currentTimeMillis() + toWait;
512.124 -
512.125 - synchronized(listener) {
512.126 - while(listener.received < sendNB && toWait > 0) {
512.127 - listener.wait(toWait);
512.128 - toWait = stopTime - System.currentTimeMillis();
512.129 - }
512.130 - }
512.131 -
512.132 - // clean
512.133 - efClient.unsubscribe(emitter, listener);
512.134 - efClient.close();
512.135 -
512.136 - if (listener.received != sendNB) {
512.137 - System.out.println(">>> PublishTest-test: FAILED! Expected to receive "+sendNB+", but got "+listener.received);
512.138 -
512.139 - return false;
512.140 - } else if (listener.seqErr > 0) {
512.141 - System.out.println(">>> PublishTest-test: FAILED! The receiving sequence is not correct.");
512.142 -
512.143 - return false;
512.144 - } else {
512.145 - System.out.println(">>> PublishTest-test: got all expected "+listener.received);
512.146 - return true;
512.147 - }
512.148 - }
512.149 -
512.150 - private static class Listener implements NotificationListener {
512.151 - public int received = 0;
512.152 - public int seqErr = 0;
512.153 -
512.154 - private long lastSeq = -1;
512.155 -
512.156 - public void handleNotification(Notification notif, Object handback) {
512.157 - if (!myType.equals(notif.getType())) {
512.158 - System.out.println(">>> PublishTest-Listener: got unexpected notif: "+notif);
512.159 - System.exit(1);
512.160 - } else if (!emitter.equals(notif.getSource())) {
512.161 - System.out.println(">>> PublishTest-Listener: unknown ObjectName: "+notif.getSource());
512.162 - System.exit(1);
512.163 - }
512.164 -
512.165 - if (lastSeq == -1) {
512.166 - lastSeq = notif.getSequenceNumber();
512.167 - } else if (notif.getSequenceNumber() - lastSeq++ != 1) {
512.168 - seqErr++;
512.169 - }
512.170 -
512.171 - System.out.println(">>> PublishTest-Listener: got notif "+notif.getSequenceNumber());
512.172 -
512.173 - synchronized(this) {
512.174 - if (++received >= sendNB) {
512.175 - this.notify();
512.176 - }
512.177 - }
512.178 -
512.179 - System.out.println(">>> PublishTest-Listener: received = "+received);
512.180 - }
512.181 - }
512.182 -
512.183 - private static int sendNB = 20;
512.184 - private static long count = 0;
512.185 -
512.186 - private static final String myType = "notification.my_notification";
512.187 -}
513.1 --- a/test/javax/management/eventService/ReconnectableConnectorTest.java Mon Nov 23 10:04:47 2009 +0000
513.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
513.3 @@ -1,488 +0,0 @@
513.4 -/*
513.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
513.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
513.7 - *
513.8 - * This code is free software; you can redistribute it and/or modify it
513.9 - * under the terms of the GNU General Public License version 2 only, as
513.10 - * published by the Free Software Foundation.
513.11 - *
513.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
513.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
513.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
513.15 - * version 2 for more details (a copy is included in the LICENSE file that
513.16 - * accompanied this code).
513.17 - *
513.18 - * You should have received a copy of the GNU General Public License version
513.19 - * 2 along with this work; if not, write to the Free Software Foundation,
513.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
513.21 - *
513.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
513.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
513.24 - * have any questions.
513.25 - */
513.26 -
513.27 -/*
513.28 - * @test ReconnectableJMXConnector
513.29 - * @bug 5108776
513.30 - * @summary Check that the Event Service can be used to build a
513.31 - * ReconnectableJMXConnector.
513.32 - * @author Eamonn McManus
513.33 - */
513.34 -
513.35 -import java.io.IOException;
513.36 -import java.lang.reflect.InvocationHandler;
513.37 -import java.lang.reflect.InvocationTargetException;
513.38 -import java.lang.reflect.Method;
513.39 -import java.lang.reflect.Proxy;
513.40 -import java.util.Date;
513.41 -import java.util.Map;
513.42 -import java.util.NoSuchElementException;
513.43 -import java.util.concurrent.ArrayBlockingQueue;
513.44 -import java.util.concurrent.BlockingQueue;
513.45 -import java.util.concurrent.TimeUnit;
513.46 -import java.util.concurrent.atomic.AtomicLong;
513.47 -import java.util.concurrent.atomic.AtomicReference;
513.48 -import java.util.concurrent.locks.Condition;
513.49 -import java.util.concurrent.locks.Lock;
513.50 -import java.util.concurrent.locks.ReentrantLock;
513.51 -import javax.management.ListenerNotFoundException;
513.52 -import javax.management.MBeanServer;
513.53 -import javax.management.MBeanServerConnection;
513.54 -import javax.management.MBeanServerFactory;
513.55 -import javax.management.Notification;
513.56 -import javax.management.NotificationBroadcasterSupport;
513.57 -import javax.management.NotificationFilter;
513.58 -import javax.management.NotificationListener;
513.59 -import javax.management.ObjectName;
513.60 -import javax.management.event.EventClient;
513.61 -import javax.management.remote.JMXConnectionNotification;
513.62 -import javax.management.remote.JMXConnector;
513.63 -import javax.management.remote.JMXConnectorFactory;
513.64 -import javax.management.remote.JMXConnectorServer;
513.65 -import javax.management.remote.JMXConnectorServerFactory;
513.66 -import javax.management.remote.JMXServiceURL;
513.67 -import javax.security.auth.Subject;
513.68 -
513.69 -/*
513.70 - * This test checks that it is possible to use the Event Service to create
513.71 - * a "reconnectable connector".
513.72 - *
513.73 - * In the JMX Remote API, we deliberately specified that a connector client
513.74 - * (JMXConnector) that encounters a network failure is then permanently broken.
513.75 - * The idea being that adding recovery logic to the basic connector client
513.76 - * would make it much more complicated and less reliable, and the logic would
513.77 - * in any case never correspond to what a given situation needs. Some of
513.78 - * the tough questions are: Should the connector try to mask the failure by
513.79 - * blocking operations until the failure is resolved? How long should the
513.80 - * connector try to reestablish the connection before giving up? Rather than
513.81 - * try to solve this problem in the connector, we suggested that people who
513.82 - * wanted to recover from network failures could implement the JMXConnector
513.83 - * interface themselves so that it forwards to a wrapped JMXConnector that can
513.84 - * be replaced in case of network failure.
513.85 - *
513.86 - * This works fine except that the connector client has state,
513.87 - * in the form of listeners added by the user through the
513.88 - * MBeanServerConnection.addNotificationListener method. It's possible
513.89 - * for the wrapper to keep track of these listeners as well as forwarding
513.90 - * them to the wrapped JMXConnector, so that it can reapply them to
513.91 - * a replacement JMXConnector after failure recover. But it's quite
513.92 - * tricky, particularly because of the two- and four-argument versions of
513.93 - * removeNotificationListener.
513.94 - *
513.95 - * The Event Service can take care of this for you through the EventClient
513.96 - * class. Listeners added through that class are implemented in a way that
513.97 - * doesn't require the connector client to maintain any state, so they should
513.98 - * continue to work transparently after replacing the wrapped JMXConnector.
513.99 - * This test is a proof of concept that shows it works. Quite a number of
513.100 - * details would need to be changed to build a reliable reconnectable
513.101 - * connector.
513.102 - *
513.103 - * The test simulates network failure by rewrapping the wrapped JMXConnector's
513.104 - * MBeanServerConnection (MBSC) in a "breakable" MBSC which we can cause
513.105 - * to stop working. We do this in two phases. The first phase suspends
513.106 - * any MBSC calls just at the point where they would return to the caller.
513.107 - * The goal here is to block an EventClientDelegateMBean.fetchNotifications
513.108 - * operation when it has received notifications but not yet delivered them
513.109 - * to the EventClient. This is the most delicate point where a breakage
513.110 - * can occur, because the EventClientDelegate must not drop those notifs
513.111 - * from its buffer until another fetchNotifs call arrives with a later
513.112 - * sequence number (which is an implicit ack of the previous set of
513.113 - * notifs). Once the fetchNotifs call is suspended, we "kill" the MBSC,
513.114 - * causing it to throw IOException from this and any other calls. That
513.115 - * triggers the reconnect logic, which will make a new MBSC and issue
513.116 - * the same fetchNotifs call to it.
513.117 - *
513.118 - * The test could be improved by synchronizing explicitly between the
513.119 - * breakable MBSC and the mainline, so we only proceed to kill the MBSC
513.120 - * when we are sure that the fetchNotifs call is blocked. As it is,
513.121 - * we have a small delay which both ensures that no notifs are delivered
513.122 - * while the connection is suspended, and if the machine is fast enough
513.123 - * allows the fetchNotifs call to reach the blocking point.
513.124 - */
513.125 -public class ReconnectableConnectorTest {
513.126 - private static class ReconnectableJMXConnector implements JMXConnector {
513.127 - private final JMXServiceURL url;
513.128 - private AtomicReference<JMXConnector> wrappedJMXC =
513.129 - new AtomicReference<JMXConnector>();
513.130 - private AtomicReference<MBeanServerConnection> wrappedMBSC =
513.131 - new AtomicReference<MBeanServerConnection>();
513.132 - private final NotificationBroadcasterSupport broadcaster =
513.133 - new NotificationBroadcasterSupport();
513.134 - private final Lock connectLock = new ReentrantLock();
513.135 -
513.136 - ReconnectableJMXConnector(JMXServiceURL url) {
513.137 - this.url = url;
513.138 - }
513.139 -
513.140 - private class ReconnectIH implements InvocationHandler {
513.141 - public Object invoke(Object proxy, Method method, Object[] args)
513.142 - throws Throwable {
513.143 - try {
513.144 - return method.invoke(wrappedMBSC.get(), args);
513.145 - } catch (InvocationTargetException e) {
513.146 - if (e.getCause() instanceof IOException) {
513.147 - connect();
513.148 - try {
513.149 - return method.invoke(wrappedMBSC.get(),args);
513.150 - } catch (InvocationTargetException ee) {
513.151 - throw ee.getCause();
513.152 - }
513.153 - }
513.154 - throw e.getCause();
513.155 - }
513.156 - }
513.157 - }
513.158 -
513.159 - private class FailureListener implements NotificationListener {
513.160 - public void handleNotification(Notification n, Object h) {
513.161 - String type = n.getType();
513.162 - if (type.equals(JMXConnectionNotification.FAILED)) {
513.163 - try {
513.164 - connect();
513.165 - } catch (IOException e) {
513.166 - broadcaster.sendNotification(n);
513.167 - }
513.168 - } else if (type.equals(JMXConnectionNotification.NOTIFS_LOST))
513.169 - broadcaster.sendNotification(n);
513.170 - }
513.171 - }
513.172 -
513.173 - public void connect() throws IOException {
513.174 - connectLock.lock();
513.175 - try {
513.176 - connectWithLock();
513.177 - } finally {
513.178 - connectLock.unlock();
513.179 - }
513.180 - }
513.181 -
513.182 - private void connectWithLock() throws IOException {
513.183 - MBeanServerConnection mbsc = wrappedMBSC.get();
513.184 - if (mbsc != null) {
513.185 - try {
513.186 - mbsc.getDefaultDomain();
513.187 - return; // the connection works
513.188 - } catch (IOException e) {
513.189 - // OK: the connection doesn't work, so make a new one
513.190 - }
513.191 - }
513.192 - // This is where we would need to add the fancy logic that
513.193 - // allows the connection to keep failing for a while
513.194 - // before giving up.
513.195 - JMXConnector jmxc = JMXConnectorFactory.connect(url);
513.196 - jmxc.addConnectionNotificationListener(
513.197 - new FailureListener(), null, null);
513.198 - wrappedJMXC.set(jmxc);
513.199 - if (false)
513.200 - wrappedMBSC.set(jmxc.getMBeanServerConnection());
513.201 - else {
513.202 - mbsc = jmxc.getMBeanServerConnection();
513.203 - InvocationHandler ih = new BreakableIH(mbsc);
513.204 - mbsc = (MBeanServerConnection) Proxy.newProxyInstance(
513.205 - MBeanServerConnection.class.getClassLoader(),
513.206 - new Class<?>[] {MBeanServerConnection.class},
513.207 - ih);
513.208 - wrappedMBSC.set(mbsc);
513.209 - }
513.210 - }
513.211 -
513.212 - private BreakableIH breakableIH() {
513.213 - MBeanServerConnection mbsc = wrappedMBSC.get();
513.214 - return (BreakableIH) Proxy.getInvocationHandler(mbsc);
513.215 - }
513.216 -
513.217 - void suspend() {
513.218 - BreakableIH ih = breakableIH();
513.219 - ih.suspend();
513.220 - }
513.221 -
513.222 - void kill() throws IOException {
513.223 - BreakableIH ih = breakableIH();
513.224 - wrappedJMXC.get().close();
513.225 - ih.kill();
513.226 - }
513.227 -
513.228 - public void connect(Map<String, ?> env) throws IOException {
513.229 - throw new UnsupportedOperationException("Not supported yet.");
513.230 - }
513.231 -
513.232 - private final AtomicReference<MBeanServerConnection> mbscRef =
513.233 - new AtomicReference<MBeanServerConnection>();
513.234 -
513.235 - public MBeanServerConnection getMBeanServerConnection()
513.236 - throws IOException {
513.237 - connect();
513.238 - // Synchro here is not strictly correct: two threads could make
513.239 - // an MBSC at the same time. OK for a test but beware for real
513.240 - // code.
513.241 - MBeanServerConnection mbsc = mbscRef.get();
513.242 - if (mbsc != null)
513.243 - return mbsc;
513.244 - mbsc = (MBeanServerConnection) Proxy.newProxyInstance(
513.245 - MBeanServerConnection.class.getClassLoader(),
513.246 - new Class<?>[] {MBeanServerConnection.class},
513.247 - new ReconnectIH());
513.248 - mbsc = EventClient.getEventClientConnection(mbsc);
513.249 - mbscRef.set(mbsc);
513.250 - return mbsc;
513.251 - }
513.252 -
513.253 - public MBeanServerConnection getMBeanServerConnection(
513.254 - Subject delegationSubject) throws IOException {
513.255 - throw new UnsupportedOperationException("Not supported yet.");
513.256 - }
513.257 -
513.258 - public void close() throws IOException {
513.259 - wrappedJMXC.get().close();
513.260 - }
513.261 -
513.262 - public void addConnectionNotificationListener(
513.263 - NotificationListener l, NotificationFilter f, Object h) {
513.264 - broadcaster.addNotificationListener(l, f, h);
513.265 - }
513.266 -
513.267 - public void removeConnectionNotificationListener(NotificationListener l)
513.268 - throws ListenerNotFoundException {
513.269 - broadcaster.removeNotificationListener(l);
513.270 - }
513.271 -
513.272 - public void removeConnectionNotificationListener(
513.273 - NotificationListener l, NotificationFilter f, Object h)
513.274 - throws ListenerNotFoundException {
513.275 - broadcaster.removeNotificationListener(l, f, h);
513.276 - }
513.277 -
513.278 - public String getConnectionId() throws IOException {
513.279 - return wrappedJMXC.get().getConnectionId();
513.280 - }
513.281 - }
513.282 -
513.283 - // InvocationHandler that allows us to perform a two-phase "break" of
513.284 - // an object. The first phase suspends the object, so that calls to
513.285 - // it are blocked just before they return. The second phase unblocks
513.286 - // suspended threads and causes them to throw IOException.
513.287 - private static class BreakableIH implements InvocationHandler {
513.288 - private final Object wrapped;
513.289 - private final Holder<String> state = new Holder<String>("running");
513.290 -
513.291 - BreakableIH(Object wrapped) {
513.292 - this.wrapped = wrapped;
513.293 - }
513.294 -
513.295 - void suspend() {
513.296 - state.set("suspended");
513.297 - }
513.298 -
513.299 - void kill() {
513.300 - state.set("killed");
513.301 - }
513.302 -
513.303 - public Object invoke(Object proxy, Method method, Object[] args)
513.304 - throws Throwable {
513.305 - Object result;
513.306 - try {
513.307 - result = method.invoke(wrapped, args);
513.308 - } catch (InvocationTargetException e) {
513.309 - throw e.getCause();
513.310 - }
513.311 - String s = state.get();
513.312 - if (s.equals("suspended"))
513.313 - state.waitUntilEqual("killed", 3, TimeUnit.SECONDS);
513.314 - else if (s.equals("killed"))
513.315 - throw new IOException("Broken");
513.316 - return result;
513.317 - }
513.318 - }
513.319 -
513.320 - private static class Holder<T> {
513.321 - private T held;
513.322 - private Lock lock = new ReentrantLock();
513.323 - private Condition changed = lock.newCondition();
513.324 -
513.325 - Holder(T value) {
513.326 - lock.lock();
513.327 - this.held = value;
513.328 - lock.unlock();
513.329 - }
513.330 -
513.331 - void waitUntilEqual(T value, long timeout, TimeUnit units)
513.332 - throws InterruptedException {
513.333 - long millis = units.toMillis(timeout);
513.334 - long stop = System.currentTimeMillis() + millis;
513.335 - Date stopDate = new Date(stop);
513.336 - lock.lock();
513.337 - try {
513.338 - while (!value.equals(held)) {
513.339 - boolean ok = changed.awaitUntil(stopDate);
513.340 - if (!ok)
513.341 - throw new InterruptedException("Timed out");
513.342 - }
513.343 - } finally {
513.344 - lock.unlock();
513.345 - }
513.346 - }
513.347 -
513.348 - void set(T value) {
513.349 - lock.lock();
513.350 - try {
513.351 - held = value;
513.352 - changed.signalAll();
513.353 - } finally {
513.354 - lock.unlock();
513.355 - }
513.356 - }
513.357 -
513.358 - T get() {
513.359 - lock.lock();
513.360 - try {
513.361 - return held;
513.362 - } finally {
513.363 - lock.unlock();
513.364 - }
513.365 - }
513.366 - }
513.367 -
513.368 - private static class StoreListener implements NotificationListener {
513.369 - final BlockingQueue<Notification> queue =
513.370 - new ArrayBlockingQueue<Notification>(100);
513.371 -
513.372 - public void handleNotification(Notification n, Object h) {
513.373 - queue.add(n);
513.374 - }
513.375 -
513.376 - Notification nextNotification(long time, TimeUnit units)
513.377 - throws InterruptedException {
513.378 - Notification n = queue.poll(time, units);
513.379 - if (n == null)
513.380 - throw new NoSuchElementException("Notification wait timed out");
513.381 - return n;
513.382 - }
513.383 -
513.384 - int notifCount() {
513.385 - return queue.size();
513.386 - }
513.387 - }
513.388 -
513.389 - public static interface SenderMBean {}
513.390 - public static class Sender
513.391 - extends NotificationBroadcasterSupport implements SenderMBean {
513.392 - private AtomicLong seqNo = new AtomicLong(0);
513.393 -
513.394 - void send() {
513.395 - Notification n =
513.396 - new Notification("type", this, seqNo.getAndIncrement());
513.397 - sendNotification(n);
513.398 - }
513.399 - }
513.400 -
513.401 - public static void main(String[] args) throws Exception {
513.402 - MBeanServer mbs = MBeanServerFactory.newMBeanServer();
513.403 - Sender sender = new Sender();
513.404 - ObjectName name = new ObjectName("a:b=c");
513.405 - mbs.registerMBean(sender, name);
513.406 -
513.407 - System.out.println("Creating connector server");
513.408 - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///");
513.409 - JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(
513.410 - url, null, mbs);
513.411 - cs.start();
513.412 -
513.413 - StoreListener csListener = new StoreListener();
513.414 - cs.addNotificationListener(csListener, null, null);
513.415 -
513.416 - System.out.println("Creating reconnectable client");
513.417 - JMXServiceURL addr = cs.getAddress();
513.418 - ReconnectableJMXConnector cc = new ReconnectableJMXConnector(addr);
513.419 - MBeanServerConnection mbsc = cc.getMBeanServerConnection();
513.420 -
513.421 - System.out.println("Checking server has sent new-client notif");
513.422 - Notification csn = csListener.nextNotification(1, TimeUnit.SECONDS);
513.423 - assertEquals("CS notif type",
513.424 - JMXConnectionNotification.OPENED, csn.getType());
513.425 -
513.426 - StoreListener listener = new StoreListener();
513.427 - mbsc.addNotificationListener(name, listener, null, null);
513.428 -
513.429 - System.out.println("Sending 10 notifs and checking they are received");
513.430 - for (int i = 0; i < 10; i++)
513.431 - sender.send();
513.432 - checkNotifs(listener, 0, 10);
513.433 -
513.434 - System.out.println("Suspending the fetchNotifs operation");
513.435 - cc.suspend();
513.436 - System.out.println("Sending a notif while fetchNotifs is suspended");
513.437 - sender.send();
513.438 - System.out.println("Brief wait before checking no notif is received");
513.439 - Thread.sleep(2);
513.440 - // dumpThreads();
513.441 - assertEquals("notif queue while connector suspended",
513.442 - 0, listener.notifCount());
513.443 - assertEquals("connector server notif queue while connector suspended",
513.444 - 0, csListener.notifCount());
513.445 -
513.446 - System.out.println("Breaking the connection so fetchNotifs will fail over");
513.447 - cc.kill();
513.448 -
513.449 - System.out.println("Checking that client has reconnected");
513.450 - csn = csListener.nextNotification(1, TimeUnit.SECONDS);
513.451 - assertEquals("First CS notif type after kill",
513.452 - JMXConnectionNotification.CLOSED, csn.getType());
513.453 - csn = csListener.nextNotification(1, TimeUnit.SECONDS);
513.454 - assertEquals("Second CS notif type after kill",
513.455 - JMXConnectionNotification.OPENED, csn.getType());
513.456 -
513.457 - System.out.println("Checking that suspended notif has been received");
513.458 - checkNotifs(listener, 10, 11);
513.459 - }
513.460 -
513.461 - private static void checkNotifs(
513.462 - StoreListener sl, long start, long stop)
513.463 - throws Exception {
513.464 - for (long i = start; i < stop; i++) {
513.465 - Notification n = sl.nextNotification(1, TimeUnit.SECONDS);
513.466 - assertEquals("received sequence number", i, n.getSequenceNumber());
513.467 - }
513.468 - }
513.469 -
513.470 - private static void assertEquals(String what, Object expect, Object actual)
513.471 - throws Exception {
513.472 - if (!expect.equals(actual)) {
513.473 - fail(what + " should be " + expect + " but is " + actual);
513.474 - }
513.475 - }
513.476 -
513.477 - private static void fail(String why) throws Exception {
513.478 - throw new Exception("TEST FAILED: " + why);
513.479 - }
513.480 -
513.481 - private static void dumpThreads() {
513.482 - System.out.println("Thread stack dump");
513.483 - Map<Thread, StackTraceElement[]> traces = Thread.getAllStackTraces();
513.484 - for (Map.Entry<Thread, StackTraceElement[]> entry : traces.entrySet()) {
513.485 - Thread t = entry.getKey();
513.486 - System.out.println("===Thread " + t.getName() + "===");
513.487 - for (StackTraceElement ste : entry.getValue())
513.488 - System.out.println(" " + ste);
513.489 - }
513.490 - }
513.491 -}
514.1 --- a/test/javax/management/eventService/SharingThreadTest.java Mon Nov 23 10:04:47 2009 +0000
514.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
514.3 @@ -1,365 +0,0 @@
514.4 -/*
514.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
514.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
514.7 - *
514.8 - * This code is free software; you can redistribute it and/or modify it
514.9 - * under the terms of the GNU General Public License version 2 only, as
514.10 - * published by the Free Software Foundation.
514.11 - *
514.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
514.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
514.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
514.15 - * version 2 for more details (a copy is included in the LICENSE file that
514.16 - * accompanied this code).
514.17 - *
514.18 - * You should have received a copy of the GNU General Public License version
514.19 - * 2 along with this work; if not, write to the Free Software Foundation,
514.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
514.21 - *
514.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
514.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
514.24 - * have any questions.
514.25 - */
514.26 -
514.27 -/*
514.28 - * @test SharingThreadTest.java 1.3 08/01/22
514.29 - * @bug 5108776
514.30 - * @summary Basic test for EventClient to see internal thread management.
514.31 - * @author Shanliang JIANG
514.32 - * @run clean SharingThreadTest
514.33 - * @run build SharingThreadTest
514.34 - * @run main SharingThreadTest
514.35 - */
514.36 -
514.37 -import java.io.IOException;
514.38 -import java.util.concurrent.ArrayBlockingQueue;
514.39 -import java.util.concurrent.Executor;
514.40 -import java.util.concurrent.ThreadPoolExecutor;
514.41 -import java.util.concurrent.TimeUnit;
514.42 -import javax.management.MBeanServer;
514.43 -import javax.management.MBeanServerFactory;
514.44 -import javax.management.Notification;
514.45 -import javax.management.NotificationBroadcasterSupport;
514.46 -import javax.management.NotificationFilter;
514.47 -import javax.management.NotificationListener;
514.48 -import javax.management.ObjectName;
514.49 -import javax.management.event.EventClient;
514.50 -import javax.management.event.EventClientDelegate;
514.51 -import javax.management.event.EventClientDelegateMBean;
514.52 -import javax.management.event.FetchingEventRelay;
514.53 -import javax.management.event.RMIPushEventRelay;
514.54 -import javax.management.remote.JMXConnector;
514.55 -import javax.management.remote.JMXConnectorFactory;
514.56 -import javax.management.remote.JMXConnectorServer;
514.57 -import javax.management.remote.JMXConnectorServerFactory;
514.58 -import javax.management.remote.JMXServiceURL;
514.59 -
514.60 -
514.61 -public class SharingThreadTest {
514.62 -
514.63 - private static MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer();
514.64 - private static ObjectName emitter;
514.65 - private static NotificationEmitter emitterImpl;
514.66 - private static JMXServiceURL url;
514.67 - private static JMXConnectorServer server;
514.68 -
514.69 -
514.70 - private static int toSend = 10;
514.71 - private static final long bigWaiting = 6000;
514.72 - private static int counter = 0;
514.73 - private static int jobs = 10;
514.74 - private static int endedJobs = 0;
514.75 -
514.76 - private static volatile String failure;
514.77 -
514.78 - private static Executor sharedExecutor = new ThreadPoolExecutor(0, 1, 1000,
514.79 - TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(jobs));
514.80 - //Executors.newFixedThreadPool(1);
514.81 -
514.82 - public static void main(String[] args) throws Exception {
514.83 - System.out.println(">>> Test on sharing threads for multiple EventClient.");
514.84 -
514.85 - // for 1.5
514.86 - if (System.getProperty("java.version").startsWith("1.5") &&
514.87 - !mbeanServer.isRegistered(EventClientDelegateMBean.OBJECT_NAME)) {
514.88 - System.out.print("Working on "+System.getProperty("java.version")+
514.89 - " register "+EventClientDelegateMBean.OBJECT_NAME);
514.90 -
514.91 - mbeanServer.registerMBean(EventClientDelegate.
514.92 - getEventClientDelegate(mbeanServer),
514.93 - EventClientDelegateMBean.OBJECT_NAME);
514.94 -
514.95 - sharedExecutor = new ThreadPoolExecutor(1, 1, 1000,
514.96 - TimeUnit.MILLISECONDS, new ArrayBlockingQueue<Runnable>(jobs));
514.97 - }
514.98 -
514.99 - emitter = new ObjectName("Default:name=NotificationEmitter");
514.100 - emitterImpl = new NotificationEmitter();
514.101 - mbeanServer.registerMBean(emitterImpl, emitter);
514.102 -
514.103 - String[] types = new String[]{"PushEventRelay", "FetchingEventRelay"};
514.104 - String[] protos = new String[]{"rmi", "iiop", "jmxmp"};
514.105 - for (String prot : protos) {
514.106 - url = new JMXServiceURL(prot, null, 0);
514.107 -
514.108 - try {
514.109 - server =
514.110 - JMXConnectorServerFactory.newJMXConnectorServer(url,
514.111 - null, mbeanServer);
514.112 - server.start();
514.113 - } catch (Exception e) {
514.114 - System.out.println(">>> Skip "+prot+", not support.");
514.115 - continue;
514.116 - }
514.117 -
514.118 - url = server.getAddress();
514.119 -
514.120 - // noise
514.121 - Thread noise = new Thread(new Runnable() {
514.122 - public void run() {
514.123 - while (true) {
514.124 - emitterImpl.sendNotif(1, null);
514.125 - try {
514.126 - Thread.sleep(10);
514.127 - } catch (Exception e) {
514.128 - // OK
514.129 - }
514.130 - }
514.131 - }
514.132 - });
514.133 - noise.setDaemon(true);
514.134 - noise.start();
514.135 -
514.136 - try {
514.137 - for (String type: types) {
514.138 - System.out.println("\n\n>>> Testing "+type+" on "+url+" ...");
514.139 - JMXConnector conn = newConn();
514.140 - try {
514.141 - testType(type, conn);
514.142 - } finally {
514.143 - conn.close();
514.144 - System.out.println(">>> Testing "+type+" on "+url+" ... done");
514.145 - }
514.146 - }
514.147 - } finally {
514.148 - server.stop();
514.149 - }
514.150 - }
514.151 - }
514.152 -
514.153 - private static void testType(String type, JMXConnector conn) throws Exception {
514.154 - Thread[] threads = new Thread[jobs];
514.155 - for (int i=0; i<jobs; i++) {
514.156 - threads[i] = new Thread(new Job(type, conn));
514.157 - threads[i].setDaemon(true);
514.158 - threads[i].start();
514.159 - }
514.160 -
514.161 - // to wait
514.162 - long toWait = bigWaiting*jobs;
514.163 - long stopTime = System.currentTimeMillis() + toWait;
514.164 -
514.165 - synchronized(SharingThreadTest.class) {
514.166 - while (endedJobs < jobs && toWait > 0 && failure == null) {
514.167 - SharingThreadTest.class.wait(toWait);
514.168 - toWait = stopTime - System.currentTimeMillis();
514.169 - }
514.170 - }
514.171 -
514.172 - if (endedJobs != jobs && failure == null) {
514.173 - throw new RuntimeException("Need to set bigger waiting timeout?");
514.174 - }
514.175 -
514.176 - endedJobs = 0;
514.177 - }
514.178 -
514.179 - public static class Job implements Runnable {
514.180 - public Job(String type, JMXConnector conn) {
514.181 - this.type = type;
514.182 - this.conn = conn;
514.183 - }
514.184 - public void run() {
514.185 - try {
514.186 - test(type, conn);
514.187 -
514.188 - synchronized(SharingThreadTest.class) {
514.189 - endedJobs++;
514.190 - if (endedJobs>=jobs) {
514.191 - SharingThreadTest.class.notify();
514.192 - }
514.193 - }
514.194 - } catch (RuntimeException re) {
514.195 - re.printStackTrace(System.out);
514.196 - throw re;
514.197 - } catch (Exception e) {
514.198 - throw new RuntimeException(e);
514.199 - }
514.200 - }
514.201 -
514.202 - private final String type;
514.203 - private final JMXConnector conn;
514.204 - }
514.205 -
514.206 - private static void test(String type, JMXConnector conn) throws Exception {
514.207 - String id = getId();
514.208 -
514.209 - Listener listener = new Listener(id);
514.210 - Filter filter = new Filter(id);
514.211 -
514.212 - //newConn();
514.213 - EventClient ec = newEventClient(type, conn);
514.214 -
514.215 - System.out.println(">>> ("+id+") To receive notifications "+toSend);
514.216 - ec.addNotificationListener(emitter,
514.217 - listener, filter, null);
514.218 -
514.219 - emitterImpl.sendNotif(toSend, id);
514.220 - listener.waitNotifs(bigWaiting, toSend);
514.221 - if (listener.received != toSend) {
514.222 - throw new RuntimeException(">>> ("+id+") Expected to receive: "
514.223 - +toSend+", but got: "+listener.received);
514.224 - }
514.225 -
514.226 - ec.close();
514.227 - }
514.228 -
514.229 -//--------------------------
514.230 -// private classes
514.231 -//--------------------------
514.232 -
514.233 - private static class Listener implements NotificationListener {
514.234 - public Listener(String id) {
514.235 - this.id = id;
514.236 - }
514.237 - public void handleNotification(Notification notif, Object handback) {
514.238 - if (!id.equals(notif.getUserData())) {
514.239 - System.out.println("("+id+") Filter error, my id is: "+id+
514.240 - ", but got "+notif.getUserData());
514.241 - System.exit(1);
514.242 - }
514.243 - System.out.println("("+id+") received "+notif.getSequenceNumber());
514.244 - synchronized (this) {
514.245 - received++;
514.246 -
514.247 - if (sequenceNB < 0) {
514.248 - sequenceNB = notif.getSequenceNumber();
514.249 - } else if(++sequenceNB != notif.getSequenceNumber()) {
514.250 - fail("(" + id + ") Wrong sequence number, expected: "
514.251 - +sequenceNB+", but got: "+notif.getSequenceNumber());
514.252 - }
514.253 - if (received >= toSend || failure != null) {
514.254 - this.notify();
514.255 - }
514.256 - }
514.257 - }
514.258 -
514.259 - public void waitNotifs(long timeout, int nb) throws Exception {
514.260 - long toWait = timeout;
514.261 - long stopTime = System.currentTimeMillis() + timeout;
514.262 - synchronized(this) {
514.263 - while (received < nb && toWait > 0 && failure == null) {
514.264 - this.wait(toWait);
514.265 - toWait = stopTime - System.currentTimeMillis();
514.266 - }
514.267 - }
514.268 - }
514.269 -
514.270 - private String id;
514.271 - private int received = 0;
514.272 -
514.273 - private long sequenceNB = -1;
514.274 - }
514.275 -
514.276 - private static class Filter implements NotificationFilter {
514.277 - public Filter(String id) {
514.278 - this.id = id;
514.279 - }
514.280 -
514.281 - public boolean isNotificationEnabled(Notification n) {
514.282 - return id.equals(n.getUserData());
514.283 - }
514.284 - private String id;
514.285 - }
514.286 -
514.287 - public static class NotificationEmitter extends NotificationBroadcasterSupport
514.288 - implements NotificationEmitterMBean {
514.289 -
514.290 - /**
514.291 - * Send Notification objects.
514.292 - *
514.293 - * @param nb The number of notifications to send
514.294 - */
514.295 - public void sendNotif(int nb, String userData) {
514.296 - new Thread(new SendJob(nb, userData)).start();
514.297 - }
514.298 -
514.299 - private class SendJob implements Runnable {
514.300 - public SendJob(int nb, String userData) {
514.301 - this.nb = nb;
514.302 - this.userData = userData;
514.303 - }
514.304 -
514.305 - public void run() {
514.306 - if (userData != null) {
514.307 - System.out.println(">>> ("+userData+") sending "+nb);
514.308 - }
514.309 - long sequenceNumber = 0;
514.310 - for (int i = 0; i<nb; i++) {
514.311 - Notification notif = new Notification(myType, emitter,
514.312 - sequenceNumber++);
514.313 - notif.setUserData(userData);
514.314 - sendNotification(notif);
514.315 - Thread.yield();
514.316 - try {
514.317 - Thread.sleep(1);
514.318 - } catch (Exception e) {}
514.319 - }
514.320 - if (userData != null) {
514.321 - System.out.println(">>> ("+userData+") sending done");
514.322 - }
514.323 - }
514.324 - private int nb;
514.325 - private String userData;
514.326 - }
514.327 - private final String myType = "notification.my_notification";
514.328 - }
514.329 -
514.330 - public interface NotificationEmitterMBean {
514.331 - public void sendNotif(int nb, String userData);
514.332 - }
514.333 -
514.334 - private static JMXConnector newConn() throws IOException {
514.335 - return JMXConnectorFactory.connect(url);
514.336 - }
514.337 -
514.338 - private static EventClient newEventClient(String type, JMXConnector conn)
514.339 - throws Exception {
514.340 - EventClientDelegateMBean proxy =
514.341 - EventClientDelegate.getProxy(conn.getMBeanServerConnection());
514.342 - if (type.equals("PushEventRelay")) {
514.343 - return new EventClient(proxy,
514.344 - new RMIPushEventRelay(proxy), sharedExecutor, null, 600);
514.345 - } else if (type.equals("FetchingEventRelay")) {
514.346 - return new EventClient(proxy,
514.347 - new FetchingEventRelay(proxy,
514.348 - FetchingEventRelay.DEFAULT_BUFFER_SIZE,
514.349 - 10,
514.350 - FetchingEventRelay.DEFAULT_MAX_NOTIFICATIONS,
514.351 - sharedExecutor),
514.352 - null, null, 600);
514.353 - } else {
514.354 - throw new RuntimeException("Wrong event client type: "+type);
514.355 - }
514.356 - }
514.357 -
514.358 - private static String getId() {
514.359 - synchronized(SharingThreadTest.class) {
514.360 - return String.valueOf(counter++);
514.361 - }
514.362 - }
514.363 -
514.364 - private static void fail(String msg) {
514.365 - System.out.println("FAIL: " + msg);
514.366 - failure = msg;
514.367 - }
514.368 -}
515.1 --- a/test/javax/management/eventService/SubUnsubTest.java Mon Nov 23 10:04:47 2009 +0000
515.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
515.3 @@ -1,125 +0,0 @@
515.4 -/*
515.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
515.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
515.7 - *
515.8 - * This code is free software; you can redistribute it and/or modify it
515.9 - * under the terms of the GNU General Public License version 2 only, as
515.10 - * published by the Free Software Foundation.
515.11 - *
515.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
515.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
515.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
515.15 - * version 2 for more details (a copy is included in the LICENSE file that
515.16 - * accompanied this code).
515.17 - *
515.18 - * You should have received a copy of the GNU General Public License version
515.19 - * 2 along with this work; if not, write to the Free Software Foundation,
515.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
515.21 - *
515.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
515.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
515.24 - * have any questions.
515.25 - */
515.26 -
515.27 -/*
515.28 - * @test SubUnsubTest
515.29 - * @bug 6736611
515.30 - * @summary Test not to remove other listeners when calling unsubscribe
515.31 - * @author Shanliang JIANG
515.32 - * @run clean SubUnsubTest
515.33 - * @run build SubUnsubTest
515.34 - * @run main SubUnsubTest
515.35 - */
515.36 -
515.37 -import java.lang.management.ManagementFactory;
515.38 -import javax.management.MBeanServer;
515.39 -import javax.management.Notification;
515.40 -import javax.management.NotificationFilter;
515.41 -import javax.management.NotificationBroadcasterSupport;
515.42 -import javax.management.NotificationListener;
515.43 -import javax.management.ObjectName;
515.44 -import javax.management.event.EventSubscriber;
515.45 -import javax.management.event.EventClient;
515.46 -public class SubUnsubTest {
515.47 - private static class CountListener implements NotificationListener {
515.48 - volatile int count;
515.49 -
515.50 - public void handleNotification(Notification n, Object h) {
515.51 - count++;
515.52 - }
515.53 - }
515.54 -
515.55 - public static interface SenderMBean {}
515.56 -
515.57 - public static class Sender extends NotificationBroadcasterSupport
515.58 - implements SenderMBean {
515.59 - void send() {
515.60 - Notification n = new Notification("type", this, 1L);
515.61 - sendNotification(n);
515.62 - }
515.63 - }
515.64 -
515.65 - public static void main(String[] args) throws Exception {
515.66 - System.out.println("Testing EventSubscriber-unsubscribe method.");
515.67 -
515.68 - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
515.69 - ObjectName name1 = new ObjectName("d:type=Sender,id=1");
515.70 - ObjectName name2 = new ObjectName("d:type=Sender,id=2");
515.71 - ObjectName pattern = new ObjectName("d:type=Sender,*");
515.72 - Sender sender1 = new Sender();
515.73 - Sender sender2 = new Sender();
515.74 - mbs.registerMBean(sender1, name1);
515.75 - mbs.registerMBean(sender2, name2);
515.76 -
515.77 - EventSubscriber sub = EventSubscriber.getEventSubscriber(mbs);
515.78 -
515.79 - System.out.println("Single subscribe covering both MBeans");
515.80 - CountListener listener = new CountListener();
515.81 -
515.82 - System.out.println("Subscribing and adding listeners ...");
515.83 - sub.subscribe(pattern, listener, null, null);
515.84 - sub.subscribe(name2, listener, null, null);
515.85 - mbs.addNotificationListener(name2, listener, null, null);
515.86 -
515.87 - sender1.send();
515.88 - sender2.send();
515.89 - if (listener.count != 4) {
515.90 - throw new RuntimeException("Do not receive all notifications: "+
515.91 - "Expect 4, got "+listener.count);
515.92 - }
515.93 -
515.94 - System.out.println("Unsubscribe the listener with the pattern.");
515.95 - sub.unsubscribe(pattern, listener);
515.96 - listener.count = 0;
515.97 - sender1.send();
515.98 - sender2.send();
515.99 - if (listener.count != 2) {
515.100 - throw new RuntimeException("The method unsubscribe removes wrong listeners.");
515.101 - }
515.102 -
515.103 - System.out.println("Unsubscribe the listener with the ObjectName.");
515.104 - sub.unsubscribe(name2, listener);
515.105 - listener.count = 0;
515.106 - sender1.send();
515.107 - sender2.send();
515.108 - if (listener.count != 1) {
515.109 - throw new RuntimeException("The method unsubscribe removes wrong listeners.");
515.110 - }
515.111 -
515.112 - System.out.println("Subscribe twice to same MBean with same listener " +
515.113 - "but different handback.");
515.114 - sub.subscribe(name1, listener, null, new Object());
515.115 - sub.subscribe(name1, listener, null, new Object());
515.116 - listener.count = 0;
515.117 -
515.118 - sub.unsubscribe(name1, listener);
515.119 - sender1.send();
515.120 - if (listener.count > 0) {
515.121 - throw new RuntimeException("EventSubscriber: the method unsubscribe" +
515.122 - " does not remove a listener which was subscribed 2 times.");
515.123 - }
515.124 -
515.125 - System.out.println("Bye bye!");
515.126 - return;
515.127 - }
515.128 -}
515.129 \ No newline at end of file
516.1 --- a/test/javax/management/eventService/SubscribeTest.java Mon Nov 23 10:04:47 2009 +0000
516.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
516.3 @@ -1,127 +0,0 @@
516.4 -/*
516.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
516.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
516.7 - *
516.8 - * This code is free software; you can redistribute it and/or modify it
516.9 - * under the terms of the GNU General Public License version 2 only, as
516.10 - * published by the Free Software Foundation.
516.11 - *
516.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
516.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
516.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
516.15 - * version 2 for more details (a copy is included in the LICENSE file that
516.16 - * accompanied this code).
516.17 - *
516.18 - * You should have received a copy of the GNU General Public License version
516.19 - * 2 along with this work; if not, write to the Free Software Foundation,
516.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
516.21 - *
516.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
516.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
516.24 - * have any questions.
516.25 - */
516.26 -
516.27 -/*
516.28 - * @test
516.29 - * @bug 5108776
516.30 - * @summary Test that EventSubscriber.subscribe works
516.31 - * @author Eamonn McManus
516.32 - */
516.33 -
516.34 -import java.lang.management.ManagementFactory;
516.35 -import javax.management.MBeanServer;
516.36 -import javax.management.Notification;
516.37 -import javax.management.NotificationBroadcasterSupport;
516.38 -import javax.management.NotificationFilter;
516.39 -import javax.management.NotificationListener;
516.40 -import javax.management.ObjectName;
516.41 -import javax.management.event.EventSubscriber;
516.42 -
516.43 -public class SubscribeTest {
516.44 - private static class CountListener implements NotificationListener {
516.45 - volatile int count;
516.46 -
516.47 - public void handleNotification(Notification n, Object h) {
516.48 - count++;
516.49 - }
516.50 - }
516.51 -
516.52 - private static class SwitchFilter implements NotificationFilter {
516.53 - volatile boolean enabled;
516.54 -
516.55 - public boolean isNotificationEnabled(Notification n) {
516.56 - return enabled;
516.57 - }
516.58 - }
516.59 -
516.60 - public static interface SenderMBean {}
516.61 -
516.62 - public static class Sender extends NotificationBroadcasterSupport
516.63 - implements SenderMBean {
516.64 - void send() {
516.65 - Notification n = new Notification("type", this, 1L);
516.66 - sendNotification(n);
516.67 - }
516.68 - }
516.69 -
516.70 - public static void main(String[] args) throws Exception {
516.71 - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
516.72 - ObjectName name1 = new ObjectName("d:type=Sender,id=1");
516.73 - ObjectName name2 = new ObjectName("d:type=Sender,id=2");
516.74 - ObjectName pattern = new ObjectName("d:type=Sender,*");
516.75 - Sender sender1 = new Sender();
516.76 - Sender sender2 = new Sender();
516.77 - mbs.registerMBean(sender1, name1);
516.78 - mbs.registerMBean(sender2, name2);
516.79 -
516.80 - EventSubscriber sub = EventSubscriber.getEventSubscriber(mbs);
516.81 -
516.82 - System.out.println("Single subscribe covering both MBeans");
516.83 - CountListener listen1 = new CountListener();
516.84 - sub.subscribe(pattern, listen1, null, null);
516.85 - sender1.send();
516.86 - assertEquals("Notifs after sender1 send", 1, listen1.count);
516.87 - sender2.send();
516.88 - assertEquals("Notifs after sender2 send", 2, listen1.count);
516.89 -
516.90 - System.out.println("Unsubscribe");
516.91 - sub.unsubscribe(pattern, listen1);
516.92 - sender1.send();
516.93 - assertEquals("Notifs after sender1 send", 2, listen1.count);
516.94 -
516.95 - System.out.println("Subscribe twice to same MBean with same listener " +
516.96 - "but different filters");
516.97 - SwitchFilter filter1 = new SwitchFilter();
516.98 - sub.subscribe(name1, listen1, null, null);
516.99 - sub.subscribe(name1, listen1, filter1, null);
516.100 - listen1.count = 0;
516.101 - sender1.send();
516.102 - // switch is off, so only one notif expected
516.103 - assertEquals("Notifs after sender1 send", 1, listen1.count);
516.104 - filter1.enabled = true;
516.105 - sender1.send();
516.106 - // switch is on, so two more notifs expected
516.107 - assertEquals("Notifs after sender1 send", 3, listen1.count);
516.108 -
516.109 - System.out.println("Remove those subscriptions");
516.110 - sub.unsubscribe(name1, listen1);
516.111 - sender1.send();
516.112 - assertEquals("Notifs after sender1 send", 3, listen1.count);
516.113 - }
516.114 -
516.115 - private static void assertEquals(String what, Object expected, Object actual)
516.116 - throws Exception {
516.117 - if (!equal(expected, actual)) {
516.118 - String msg = "Expected " + expected + "; got " + actual;
516.119 - throw new Exception("TEST FAILED: " + what + ": " + msg);
516.120 - }
516.121 - }
516.122 -
516.123 - private static boolean equal(Object x, Object y) {
516.124 - if (x == y)
516.125 - return true;
516.126 - if (x == null)
516.127 - return false;
516.128 - return (x.equals(y));
516.129 - }
516.130 -}
517.1 --- a/test/javax/management/eventService/UsingEventService.java Mon Nov 23 10:04:47 2009 +0000
517.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
517.3 @@ -1,107 +0,0 @@
517.4 -/*
517.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
517.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
517.7 - *
517.8 - * This code is free software; you can redistribute it and/or modify it
517.9 - * under the terms of the GNU General Public License version 2 only, as
517.10 - * published by the Free Software Foundation.
517.11 - *
517.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
517.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
517.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
517.15 - * version 2 for more details (a copy is included in the LICENSE file that
517.16 - * accompanied this code).
517.17 - *
517.18 - * You should have received a copy of the GNU General Public License version
517.19 - * 2 along with this work; if not, write to the Free Software Foundation,
517.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
517.21 - *
517.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
517.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
517.24 - * have any questions.
517.25 - */
517.26 -
517.27 -/*
517.28 - * @test UsingEventService.java 1.10 08/01/22
517.29 - * @bug 5108776
517.30 - * @summary Basic test for EventManager.
517.31 - * @author Shanliang JIANG
517.32 - * @run clean UsingEventService
517.33 - * @run build UsingEventService
517.34 - * @run main UsingEventService
517.35 - */
517.36 -
517.37 -import java.util.HashMap;
517.38 -import java.util.Map;
517.39 -import javax.management.MBeanServer;
517.40 -import javax.management.MBeanServerConnection;
517.41 -import javax.management.MBeanServerFactory;
517.42 -import javax.management.Notification;
517.43 -import javax.management.NotificationListener;
517.44 -import javax.management.ObjectName;
517.45 -import javax.management.event.EventConsumer;
517.46 -import javax.management.remote.JMXConnector;
517.47 -import javax.management.remote.JMXConnectorFactory;
517.48 -import javax.management.remote.JMXConnectorServer;
517.49 -import javax.management.remote.JMXConnectorServerFactory;
517.50 -import javax.management.remote.JMXServiceURL;
517.51 -
517.52 -public class UsingEventService {
517.53 - private static JMXServiceURL url;
517.54 - private static JMXConnectorServer server;
517.55 - private static JMXConnector conn;
517.56 - private static MBeanServerConnection client;
517.57 -
517.58 - public static void main(String[] args) throws Exception {
517.59 - if (System.getProperty("java.version").startsWith("1.5")) {
517.60 - System.out.println(">>> UsingEventService-main not available for JDK1.5, bye");
517.61 - return;
517.62 - }
517.63 -
517.64 - ObjectName oname = new ObjectName("test:t=t");
517.65 - Notification n = new Notification("", oname, 0);
517.66 -
517.67 - System.out.println(">>> UsingEventService-main basic tests ...");
517.68 - MBeanServer mbeanServer = MBeanServerFactory.createMBeanServer();
517.69 -
517.70 - url = new JMXServiceURL("rmi", null, 0) ;
517.71 - JMXConnectorServer server =
517.72 - JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbeanServer);
517.73 - server.start();
517.74 - url = server.getAddress();
517.75 -
517.76 - System.out.println(">>> UsingEventService-main test to not use the event service...");
517.77 - conn = JMXConnectorFactory.connect(url, null);
517.78 - client = conn.getMBeanServerConnection();
517.79 -
517.80 - System.out.println(">>> UsingEventService-main test to use the event service...");
517.81 - Map env = new HashMap(1);
517.82 - env.put("jmx.remote.use.event.service", "true");
517.83 - conn = JMXConnectorFactory.connect(url, env);
517.84 - client = conn.getMBeanServerConnection();
517.85 -
517.86 - ((EventConsumer)client).subscribe(oname, listener, null, null);
517.87 -
517.88 - System.out.println(">>> UsingEventService-main using event service as expected!");
517.89 -
517.90 - System.out.println(">>> UsingEventService-main test to use" +
517.91 - " the event service with system property...");
517.92 -
517.93 - System.setProperty("jmx.remote.use.event.service", "true");
517.94 - conn = JMXConnectorFactory.connect(url, null);
517.95 - client = conn.getMBeanServerConnection();
517.96 -
517.97 - ((EventConsumer)client).subscribe(oname, listener, null, null);
517.98 -
517.99 - System.out.println("" +
517.100 - ">>> UsingEventService-main using event service as expected!");
517.101 -
517.102 - System.out.println(">>> Happy bye bye!");
517.103 - }
517.104 -
517.105 - private final static NotificationListener listener = new NotificationListener() {
517.106 - public void handleNotification(Notification n, Object hk) {
517.107 - //
517.108 - }
517.109 - };
517.110 -}
518.1 --- a/test/javax/management/interop/MBeanExceptionInteropTest.java Mon Nov 23 10:04:47 2009 +0000
518.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
518.3 @@ -1,166 +0,0 @@
518.4 -/*
518.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
518.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
518.7 - *
518.8 - * This code is free software; you can redistribute it and/or modify it
518.9 - * under the terms of the GNU General Public License version 2 only, as
518.10 - * published by the Free Software Foundation.
518.11 - *
518.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
518.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
518.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
518.15 - * version 2 for more details (a copy is included in the LICENSE file that
518.16 - * accompanied this code).
518.17 - *
518.18 - * You should have received a copy of the GNU General Public License version
518.19 - * 2 along with this work; if not, write to the Free Software Foundation,
518.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
518.21 - *
518.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
518.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
518.24 - * have any questions.
518.25 - */
518.26 -
518.27 -/*
518.28 - * @test
518.29 - * @bug 6456269
518.30 - * @summary Test that an MBeanException serialized on JDK 6 deserializes
518.31 - * correctly on JDK 7.
518.32 - * @author Eamonn McManus
518.33 - */
518.34 -
518.35 -import java.io.ByteArrayInputStream;
518.36 -import java.io.ByteArrayOutputStream;
518.37 -import java.io.ObjectInputStream;
518.38 -import java.io.ObjectOutputStream;
518.39 -import javax.management.MBeanException;
518.40 -
518.41 -// In JDK 6, the Throwable.cause field was always null for an MBeanException,
518.42 -// but it didn't matter because we overrode getCause() to return
518.43 -// MBeanException.exception instead. In JDK 7, we no longer override getCause()
518.44 -// because MBeanException doubles as the serial form of GenericMBeanException.
518.45 -// So we need some care to make sure that objects deserialized from JDK 6
518.46 -// have the right getCause() behaviour.
518.47 -public class MBeanExceptionInteropTest {
518.48 - private static final byte[] SERIALIZED_MBEAN_EXCEPTION = {
518.49 - -84,-19,0,5,115,114,0,31,106,97,118,97,120,46,109,97,
518.50 - 110,97,103,101,109,101,110,116,46,77,66,101,97,110,69,120,
518.51 - 99,101,112,116,105,111,110,56,110,-116,-27,110,87,49,-50,2,
518.52 - 0,1,76,0,9,101,120,99,101,112,116,105,111,110,116,0,
518.53 - 21,76,106,97,118,97,47,108,97,110,103,47,69,120,99,101,
518.54 - 112,116,105,111,110,59,120,114,0,28,106,97,118,97,120,46,
518.55 - 109,97,110,97,103,101,109,101,110,116,46,74,77,69,120,99,
518.56 - 101,112,116,105,111,110,4,-35,76,-20,-109,-99,126,113,2,0,
518.57 - 0,120,114,0,19,106,97,118,97,46,108,97,110,103,46,69,
518.58 - 120,99,101,112,116,105,111,110,-48,-3,31,62,26,59,28,-60,
518.59 - 2,0,0,120,114,0,19,106,97,118,97,46,108,97,110,103,
518.60 - 46,84,104,114,111,119,97,98,108,101,-43,-58,53,39,57,119,
518.61 - -72,-53,3,0,3,76,0,5,99,97,117,115,101,116,0,21,
518.62 - 76,106,97,118,97,47,108,97,110,103,47,84,104,114,111,119,
518.63 - 97,98,108,101,59,76,0,13,100,101,116,97,105,108,77,101,
518.64 - 115,115,97,103,101,116,0,18,76,106,97,118,97,47,108,97,
518.65 - 110,103,47,83,116,114,105,110,103,59,91,0,10,115,116,97,
518.66 - 99,107,84,114,97,99,101,116,0,30,91,76,106,97,118,97,
518.67 - 47,108,97,110,103,47,83,116,97,99,107,84,114,97,99,101,
518.68 - 69,108,101,109,101,110,116,59,120,112,113,0,126,0,8,116,
518.69 - 0,7,79,104,32,100,101,97,114,117,114,0,30,91,76,106,
518.70 - 97,118,97,46,108,97,110,103,46,83,116,97,99,107,84,114,
518.71 - 97,99,101,69,108,101,109,101,110,116,59,2,70,42,60,60,
518.72 - -3,34,57,2,0,0,120,112,0,0,0,2,115,114,0,27,
518.73 - 106,97,118,97,46,108,97,110,103,46,83,116,97,99,107,84,
518.74 - 114,97,99,101,69,108,101,109,101,110,116,97,9,-59,-102,38,
518.75 - 54,-35,-123,2,0,4,73,0,10,108,105,110,101,78,117,109,
518.76 - 98,101,114,76,0,14,100,101,99,108,97,114,105,110,103,67,
518.77 - 108,97,115,115,113,0,126,0,6,76,0,8,102,105,108,101,
518.78 - 78,97,109,101,113,0,126,0,6,76,0,10,109,101,116,104,
518.79 - 111,100,78,97,109,101,113,0,126,0,6,120,112,0,0,0,
518.80 - 63,116,0,25,77,66,101,97,110,69,120,99,101,112,116,105,
518.81 - 111,110,73,110,116,101,114,111,112,84,101,115,116,116,0,30,
518.82 - 77,66,101,97,110,69,120,99,101,112,116,105,111,110,73,110,
518.83 - 116,101,114,111,112,84,101,115,116,46,106,97,118,97,116,0,
518.84 - 5,119,114,105,116,101,115,113,0,126,0,12,0,0,0,46,
518.85 - 113,0,126,0,14,113,0,126,0,15,116,0,4,109,97,105,
518.86 - 110,120,115,114,0,34,106,97,118,97,46,108,97,110,103,46,
518.87 - 73,108,108,101,103,97,108,65,114,103,117,109,101,110,116,69,
518.88 - 120,99,101,112,116,105,111,110,-75,-119,115,-45,125,102,-113,-68,
518.89 - 2,0,0,120,114,0,26,106,97,118,97,46,108,97,110,103,
518.90 - 46,82,117,110,116,105,109,101,69,120,99,101,112,116,105,111,
518.91 - 110,-98,95,6,71,10,52,-125,-27,2,0,0,120,113,0,126,
518.92 - 0,3,113,0,126,0,21,116,0,3,66,97,100,117,113,0,
518.93 - 126,0,10,0,0,0,2,115,113,0,126,0,12,0,0,0,
518.94 - 62,113,0,126,0,14,113,0,126,0,15,113,0,126,0,16,
518.95 - 115,113,0,126,0,12,0,0,0,46,113,0,126,0,14,113,
518.96 - 0,126,0,15,113,0,126,0,18,120,
518.97 - };
518.98 -
518.99 - private static volatile String failure;
518.100 -
518.101 - public static void main(String[] args) throws Exception {
518.102 - if (args.length > 0) {
518.103 - if (args[0].equals("write") && args.length == 1) {
518.104 - write();
518.105 - return;
518.106 - } else {
518.107 - System.err.println(
518.108 - "Usage: java MBeanExceptionInteropTest");
518.109 - System.err.println(
518.110 - "or: java MBeanExceptionInteropTest write");
518.111 - System.exit(1);
518.112 - }
518.113 - }
518.114 -
518.115 - // Read the serialized object and check it is correct.
518.116 - ByteArrayInputStream bin =
518.117 - new ByteArrayInputStream(SERIALIZED_MBEAN_EXCEPTION);
518.118 - ObjectInputStream oin = new ObjectInputStream(bin);
518.119 - MBeanException mbeanEx = (MBeanException) oin.readObject();
518.120 - assertEquals("MBeanException message", "Oh dear", mbeanEx.getMessage());
518.121 - System.out.println("getCause(): " + mbeanEx.getCause() + "; " +
518.122 - "getTargetException(): " + mbeanEx.getTargetException());
518.123 - for (Throwable t :
518.124 - new Throwable[] {mbeanEx.getCause(), mbeanEx.getTargetException()}) {
518.125 - if (!(t instanceof IllegalArgumentException))
518.126 - fail("Nested exception not an IllegalArgumentException: " + t);
518.127 - else
518.128 - assertEquals("Nested exception message", "Bad", t.getMessage());
518.129 - }
518.130 -
518.131 - if (failure == null)
518.132 - System.out.println("TEST PASSED");
518.133 - else
518.134 - throw new Exception("TEST FAILED: " + failure);
518.135 - }
518.136 -
518.137 - // Write a file that can be inserted into this source file as the
518.138 - // contents of the SERIALIZED_MBEAN_EXCEPTION array. Run this program
518.139 - // on JDK 6 to generate the array, then test on JDK 7.
518.140 - private static void write() throws Exception {
518.141 - Exception wrapped = new IllegalArgumentException("Bad");
518.142 - MBeanException mbeanEx = new MBeanException(wrapped, "Oh dear");
518.143 - ByteArrayOutputStream bout = new ByteArrayOutputStream();
518.144 - ObjectOutputStream oout = new ObjectOutputStream(bout);
518.145 - oout.writeObject(mbeanEx);
518.146 - oout.close();
518.147 - byte[] bytes = bout.toByteArray();
518.148 - for (int i = 0; i < bytes.length; i++) {
518.149 - System.out.printf("%d,", bytes[i]);
518.150 - if (i % 16 == 15)
518.151 - System.out.println();
518.152 - }
518.153 - if (bytes.length % 16 != 0)
518.154 - System.out.println();
518.155 - }
518.156 -
518.157 - private static void assertEquals(String what, Object expect, Object actual) {
518.158 - boolean equal = (expect == null) ? (actual == null) : expect.equals(actual);
518.159 - if (equal)
518.160 - System.out.println("OK: " + what + ": " + expect);
518.161 - else
518.162 - fail(what + ": expected " + expect + ", got " + actual);
518.163 - }
518.164 -
518.165 - private static void fail(String why) {
518.166 - System.out.println("FAIL: " + why);
518.167 - failure = why;
518.168 - }
518.169 -}
519.1 --- a/test/javax/management/modelmbean/DefaultDescriptorFieldTest.java Mon Nov 23 10:04:47 2009 +0000
519.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
519.3 @@ -1,354 +0,0 @@
519.4 -/*
519.5 - * Copyright 2007 Sun Microsystems, Inc. All Rights Reserved.
519.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
519.7 - *
519.8 - * This code is free software; you can redistribute it and/or modify it
519.9 - * under the terms of the GNU General Public License version 2 only, as
519.10 - * published by the Free Software Foundation.
519.11 - *
519.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
519.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
519.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
519.15 - * version 2 for more details (a copy is included in the LICENSE file that
519.16 - * accompanied this code).
519.17 - *
519.18 - * You should have received a copy of the GNU General Public License version
519.19 - * 2 along with this work; if not, write to the Free Software Foundation,
519.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
519.21 - *
519.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
519.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
519.24 - * have any questions.
519.25 - */
519.26 -
519.27 -/*
519.28 - * @test
519.29 - * @bug 6252592 4967755
519.30 - * @summary Check that default fields are correctly added to Descriptors
519.31 - * and that input Descriptors are never modified
519.32 - * @author Lars Westergren
519.33 - */
519.34 -
519.35 -import java.lang.reflect.Constructor;
519.36 -import java.lang.reflect.InvocationTargetException;
519.37 -import java.lang.reflect.Method;
519.38 -import javax.management.Descriptor;
519.39 -import javax.management.IntrospectionException;
519.40 -import javax.management.MBeanAttributeInfo;
519.41 -import javax.management.MBeanConstructorInfo;
519.42 -import javax.management.MBeanException;
519.43 -import javax.management.MBeanNotificationInfo;
519.44 -import javax.management.MBeanOperationInfo;
519.45 -import javax.management.RuntimeOperationsException;
519.46 -import javax.management.modelmbean.DescriptorSupport;
519.47 -import javax.management.modelmbean.ModelMBeanAttributeInfo;
519.48 -import javax.management.modelmbean.ModelMBeanConstructorInfo;
519.49 -import javax.management.modelmbean.ModelMBeanInfo;
519.50 -import javax.management.modelmbean.ModelMBeanInfoSupport;
519.51 -import javax.management.modelmbean.ModelMBeanNotificationInfo;
519.52 -import javax.management.modelmbean.ModelMBeanOperationInfo;
519.53 -
519.54 -/**
519.55 - * Junit tests for bugs:
519.56 - * 6252592 Provide for the user mandatory fields missing in Descriptor given
519.57 - * to Model*Info constructors
519.58 - * 4967755 ModelMBeanAttributeInfo constructor modifies its Descriptor argument
519.59 - *
519.60 - * @author Lars Westergren
519.61 - */
519.62 -public class DefaultDescriptorFieldTest /*extends TestCase*/ {
519.63 - public static void main(String[] args) throws Exception {
519.64 - boolean fail = false;
519.65 - Object test = new DefaultDescriptorFieldTest("Test");
519.66 - for (Method m : DefaultDescriptorFieldTest.class.getMethods()) {
519.67 - if (m.getName().startsWith("test") &&
519.68 - m.getParameterTypes().length == 0) {
519.69 - System.out.println("Testing " + m.getName());
519.70 - try {
519.71 - m.invoke(test);
519.72 - } catch (InvocationTargetException e) {
519.73 - fail = true;
519.74 - Throwable t = e.getCause();
519.75 - System.out.println("FAILED: exception: " + t);
519.76 - t.printStackTrace(System.out);
519.77 - }
519.78 - }
519.79 - }
519.80 - if (fail)
519.81 - throw new Exception("TEST FAILED");
519.82 - }
519.83 -
519.84 - //No check WHICH constructor is reflected, at least when the classes tested are constructed,
519.85 - //so I just use first one that came to mind.
519.86 - final Constructor[] constArr = String.class.getConstructors();
519.87 - final Constructor dummyConstructor = constArr[0];
519.88 -
519.89 -
519.90 - Method getMethod = null;
519.91 -
519.92 - /** Creates a new instance of MBeanTest */
519.93 - public DefaultDescriptorFieldTest(final String name) {
519.94 - try {
519.95 - getMethod = String.class.getMethod("toString");
519.96 - } catch (SecurityException ex) {
519.97 - ex.printStackTrace();
519.98 - } catch (NoSuchMethodException ex) {
519.99 - ex.printStackTrace();
519.100 - }
519.101 - }
519.102 -
519.103 - /**
519.104 - * Test instantiating the 5 different classes with a null
519.105 - * Descriptor, and also setting a null descriptor after.
519.106 - * Expected: Default Descriptors created.
519.107 - */
519.108 - public void testNullDescriptors()
519.109 - throws IntrospectionException, MBeanException {
519.110 - final ModelMBeanConstructorInfo constInfo =
519.111 - new ModelMBeanConstructorInfo("Dummy", dummyConstructor, null);
519.112 - constInfo.setDescriptor(null);
519.113 - ModelMBeanAttributeInfo attInfo =
519.114 - new ModelMBeanAttributeInfo("dummyAttInfoName", "dummyAttInfoDesc", getMethod, null, null);
519.115 - attInfo.setDescriptor(null);
519.116 - ModelMBeanNotificationInfo notInfo =
519.117 - new ModelMBeanNotificationInfo(null, "notificationClassName", "daName", null);
519.118 - notInfo.setDescriptor(null);
519.119 - ModelMBeanOperationInfo opInfo =
519.120 - new ModelMBeanOperationInfo("test", getMethod, null);
519.121 - opInfo.setDescriptor(null);
519.122 - ModelMBeanInfoSupport infoSupport =
519.123 - new ModelMBeanInfoSupport(new DummyModelMBeanInfo());
519.124 - infoSupport.setDescriptor(null,null);
519.125 - infoSupport.setDescriptor(null, "mbean");
519.126 - }
519.127 -
519.128 - /**
519.129 - * Test instantiating and setting a Descriptor without the "name",
519.130 - * "descriptorType" or "role" fields. This also tests whether the
519.131 - * Descriptor is cloned before default values are set, since
519.132 - * default values for one class will be incorrect for the next.
519.133 - * Expected: Descriptor should be cloned, missing default values should be
519.134 - * set
519.135 - */
519.136 - public void testFieldlessDescriptor()
519.137 - throws IntrospectionException, MBeanException {
519.138 - Descriptor theNamelessOne = new DescriptorSupport();
519.139 - final ModelMBeanConstructorInfo constInfo =
519.140 - new ModelMBeanConstructorInfo("Dummy", dummyConstructor, theNamelessOne);
519.141 - constInfo.setDescriptor(theNamelessOne);
519.142 - ModelMBeanAttributeInfo attInfo =
519.143 - new ModelMBeanAttributeInfo("dummyAttInfoName", "dummyAttInfoDesc", getMethod, null, theNamelessOne);
519.144 - attInfo.setDescriptor(theNamelessOne);
519.145 - ModelMBeanNotificationInfo notInfo =
519.146 - new ModelMBeanNotificationInfo(null, "notificationClassName", "daName", theNamelessOne);
519.147 - notInfo.setDescriptor(theNamelessOne);
519.148 - ModelMBeanOperationInfo opInfo =
519.149 - new ModelMBeanOperationInfo("test", getMethod, theNamelessOne);
519.150 - opInfo.setDescriptor(theNamelessOne);
519.151 - ModelMBeanInfoSupport infoSupport = new ModelMBeanInfoSupport(new DummyModelMBeanInfo());
519.152 - infoSupport.setDescriptor(theNamelessOne, null);
519.153 - infoSupport.setDescriptor(theNamelessOne, "mbean");
519.154 - }
519.155 -
519.156 -
519.157 - /**
519.158 - * Creates an empty DescriptorSupport and then test that ModelMBeanConstructorInfo accepts
519.159 - * the correct fields in validation one by one.
519.160 - */
519.161 - public void testCorrectConstructorDescriptors()
519.162 - throws NoSuchMethodException, IllegalAccessException, InvocationTargetException {
519.163 - Descriptor cDesc = new DescriptorSupport(new String[0],new String[0]);
519.164 - final ModelMBeanConstructorInfo constInfo =
519.165 - new ModelMBeanConstructorInfo("Dummy", dummyConstructor, cDesc);
519.166 - assertFalse(fieldRefuted(constInfo, cDesc, "name" , "java.lang.String"));
519.167 - assertFalse(fieldRefuted(constInfo, cDesc, "role" , "constructor"));
519.168 - assertFalse(fieldRefuted(constInfo, cDesc, "descriptorType" , "operation"));
519.169 - }
519.170 -
519.171 - /**
519.172 - * Test that ModelMBeanConstructorInfo refutes incorrect fields in validation one by one.
519.173 - */
519.174 - public void testIncorrectConstructorDescriptors()
519.175 - throws NoSuchMethodException, IllegalAccessException {
519.176 - Descriptor cDesc = new DescriptorSupport(
519.177 - new String[] {"getMethod", "setMethod", "role", "Class", "name", "descriptorType"},
519.178 - new String[] {"dummyGetMethod", "dummySetMethod", "constructor", "dummyClass", "java.lang.String", "operation"});
519.179 - final ModelMBeanConstructorInfo constInfo = new ModelMBeanConstructorInfo("Dummy", dummyConstructor, cDesc);
519.180 - assertTrue(fieldRefuted(constInfo, cDesc, "name" , "blah"));
519.181 - assertTrue(fieldRefuted(constInfo, cDesc, "descriptorType", "mbean"));
519.182 - assertTrue(fieldRefuted(constInfo, cDesc, "descriptorType", "notification"));
519.183 - assertTrue(fieldRefuted(constInfo, cDesc, "descriptorType", "constructor"));
519.184 - assertTrue(fieldRefuted(constInfo, cDesc, "role", "operation"));
519.185 - }
519.186 -
519.187 - public void testCorrectAttributeDescriptors()
519.188 - throws IntrospectionException, NoSuchMethodException, IllegalAccessException {
519.189 - Descriptor aDesc = new DescriptorSupport(new String[0],new String[0]);
519.190 - final ModelMBeanAttributeInfo attInfo = new ModelMBeanAttributeInfo("dummyAttInfoName", "dummyAttInfoDesc", getMethod, null, null);
519.191 - assertFalse(fieldRefuted(attInfo, aDesc, "name" , "dummyAttInfoName"));
519.192 - assertFalse(fieldRefuted(attInfo, aDesc, "descriptorType" , "attribute"));
519.193 - }
519.194 -
519.195 - public void testIncorrectAttributeDescriptors()
519.196 - throws IntrospectionException, NoSuchMethodException, IllegalAccessException {
519.197 - Descriptor aDesc = new DescriptorSupport();
519.198 - final ModelMBeanAttributeInfo attInfo = new ModelMBeanAttributeInfo("dummyAttInfoName", "dummyAttInfoDesc", getMethod, null, null);
519.199 - assertTrue(fieldRefuted(attInfo, aDesc, "name" , "blah"));
519.200 - assertTrue(fieldRefuted(attInfo, aDesc, "descriptorType" , "constructor"));
519.201 - assertTrue(fieldRefuted(attInfo, aDesc, "descriptorType" , "notification"));
519.202 - }
519.203 -
519.204 - public void testCorrectNotificationDescriptors()
519.205 - throws NoSuchMethodException, IllegalAccessException {
519.206 - Descriptor nDesc = new DescriptorSupport();
519.207 - final ModelMBeanNotificationInfo nInfo = new ModelMBeanNotificationInfo(null, "notificationClassName", "daName", nDesc);
519.208 - assertFalse(fieldRefuted(nInfo, nDesc, "name" , "notificationClassName"));
519.209 - assertFalse(fieldRefuted(nInfo, nDesc, "descriptorType" , "notification"));
519.210 - }
519.211 -
519.212 - public void testIncorrectNotificationDescriptors()
519.213 - throws NoSuchMethodException, IllegalAccessException {
519.214 - Descriptor nDesc = new DescriptorSupport();
519.215 - final ModelMBeanNotificationInfo nInfo = new ModelMBeanNotificationInfo(null, "notificationClassName", "daName", nDesc);
519.216 - assertTrue(fieldRefuted(nInfo, nDesc, "name" , "blah"));
519.217 - assertTrue(fieldRefuted(nInfo, nDesc, "descriptorType" , "constructor"));
519.218 - assertTrue(fieldRefuted(nInfo, nDesc, "descriptorType" , "operation"));
519.219 - }
519.220 -
519.221 - public void testCorrectOperationDescriptors()
519.222 - throws NoSuchMethodException, IllegalAccessException {
519.223 - Descriptor opDesc = new DescriptorSupport();
519.224 - final ModelMBeanOperationInfo opInfo = new ModelMBeanOperationInfo("test", "readable description", null, "type", 1, opDesc);
519.225 - assertFalse(fieldRefuted(opInfo, opDesc, "name" , "test"));
519.226 - assertFalse(fieldRefuted(opInfo, opDesc, "descriptorType" , "operation"));
519.227 - assertFalse(fieldRefuted(opInfo, opDesc, "role" , "operation"));
519.228 - assertFalse(fieldRefuted(opInfo, opDesc, "role" , "getter"));
519.229 - assertFalse(fieldRefuted(opInfo, opDesc, "role" , "setter"));
519.230 - }
519.231 -
519.232 - public void testIncorrectOperationDescriptors()
519.233 - throws NoSuchMethodException, IllegalAccessException {
519.234 - Descriptor opDesc = new DescriptorSupport();
519.235 - final ModelMBeanOperationInfo opInfo = new ModelMBeanOperationInfo("test", "readable description", null, "type", 1, opDesc);
519.236 - assertTrue(fieldRefuted(opInfo, opDesc, "name" , "DENIED!!"));
519.237 - assertTrue(fieldRefuted(opInfo, opDesc, "descriptorType" , "constructor"));
519.238 - assertTrue(fieldRefuted(opInfo, opDesc, "descriptorType" , "attribute"));
519.239 - assertTrue(fieldRefuted(opInfo, opDesc, "descriptorType" , "notification"));
519.240 - assertTrue(fieldRefuted(opInfo, opDesc, "descriptorType" , "x"));
519.241 - }
519.242 -
519.243 - //TODO also test ModelMBeanInfoSupport perhaps. Slightly more difficult to set up and test.
519.244 -
519.245 - /**
519.246 - * Clones descriptor, sets a new value in the clone and tries to apply clone to
519.247 - * reflected Model*Info object method. The new field should be refuted if it
519.248 - * is a bad value.
519.249 - */
519.250 - //I like java, but this is one case where duck typing would have been slightly easier I think. :)
519.251 - private boolean fieldRefuted(Object mbeanInfo, Descriptor desc, String fieldName, String newValue)
519.252 - throws NoSuchMethodException, IllegalAccessException {
519.253 - Method setDescMethod = mbeanInfo.getClass().getMethod("setDescriptor", Descriptor.class);
519.254 - Descriptor newDesc = (Descriptor)desc.clone();
519.255 - boolean refused = false;
519.256 - newDesc.setField(fieldName, newValue);
519.257 - try {
519.258 - setDescMethod.invoke(mbeanInfo, newDesc);
519.259 - } catch (InvocationTargetException ex) {
519.260 - //If we get classcast exception, someone passed in a bad object to reflection.
519.261 - //Perhaps an unnecessary check, this cast?
519.262 - RuntimeOperationsException rex = (RuntimeOperationsException)ex.getTargetException();
519.263 - refused = true;
519.264 - }
519.265 - return refused;
519.266 - }
519.267 -
519.268 - /**
519.269 - * Dummy class used to create test objects. May not be needed.
519.270 - */
519.271 - private class DummyModelMBeanInfo implements ModelMBeanInfo {
519.272 - public Descriptor[] getDescriptors(String inDescriptorType)
519.273 - throws MBeanException, RuntimeOperationsException {
519.274 - return null;
519.275 - }
519.276 -
519.277 - public void setDescriptors(Descriptor[] inDescriptors)
519.278 - throws MBeanException, RuntimeOperationsException {
519.279 -
519.280 - }
519.281 -
519.282 - public Descriptor getDescriptor(String inDescriptorName, String inDescriptorType)
519.283 - throws MBeanException, RuntimeOperationsException {
519.284 - return null;
519.285 - }
519.286 -
519.287 - public void setDescriptor(Descriptor inDescriptor, String inDescriptorType)
519.288 - throws MBeanException, RuntimeOperationsException {
519.289 -
519.290 - }
519.291 -
519.292 - public Descriptor getMBeanDescriptor()
519.293 - throws MBeanException, RuntimeOperationsException {
519.294 - return null;
519.295 - }
519.296 -
519.297 - public void setMBeanDescriptor(Descriptor inDescriptor)
519.298 - throws MBeanException, RuntimeOperationsException {
519.299 -
519.300 - }
519.301 -
519.302 - public ModelMBeanAttributeInfo getAttribute(String inName)
519.303 - throws MBeanException, RuntimeOperationsException {
519.304 - return null;
519.305 - }
519.306 -
519.307 - public ModelMBeanOperationInfo getOperation(String inName)
519.308 - throws MBeanException, RuntimeOperationsException {
519.309 - return null;
519.310 - }
519.311 -
519.312 - public ModelMBeanNotificationInfo getNotification(String inName)
519.313 - throws MBeanException, RuntimeOperationsException {
519.314 - return null;
519.315 - }
519.316 -
519.317 - public MBeanAttributeInfo[] getAttributes() {
519.318 - return null;
519.319 - }
519.320 -
519.321 - public String getClassName() {
519.322 - return "AnonMBeanInfoImpl";
519.323 - }
519.324 -
519.325 - public MBeanConstructorInfo[] getConstructors() {
519.326 - return null;
519.327 - }
519.328 -
519.329 - public String getDescription() {
519.330 - return null;
519.331 - }
519.332 -
519.333 - public MBeanNotificationInfo[] getNotifications() {
519.334 - return null;
519.335 - }
519.336 -
519.337 - public MBeanOperationInfo[] getOperations() {
519.338 - return null;
519.339 - }
519.340 -
519.341 - public Object clone() {
519.342 - return null;
519.343 -
519.344 - }
519.345 -
519.346 - }
519.347 -
519.348 - private static void assertFalse(boolean x) {
519.349 - assertTrue(!x);
519.350 - }
519.351 -
519.352 - private static void assertTrue(boolean x) {
519.353 - if (!x)
519.354 - throw new AssertionError("Assertion failed");
519.355 - }
519.356 -
519.357 -}
520.1 --- a/test/javax/management/monitor/AttributeArbitraryDataTypeTest.java Mon Nov 23 10:04:47 2009 +0000
520.2 +++ b/test/javax/management/monitor/AttributeArbitraryDataTypeTest.java Wed Nov 25 11:08:25 2009 -0800
520.3 @@ -32,9 +32,13 @@
520.4 * @run main AttributeArbitraryDataTypeTest
520.5 */
520.6
520.7 +import java.beans.BeanInfo;
520.8 import java.beans.IntrospectionException;
520.9 import java.beans.PropertyDescriptor;
520.10 import java.beans.SimpleBeanInfo;
520.11 +import java.lang.reflect.Array;
520.12 +import java.lang.reflect.InvocationTargetException;
520.13 +import javax.management.AttributeNotFoundException;
520.14 import javax.management.MBeanServer;
520.15 import javax.management.MBeanServerFactory;
520.16 import javax.management.Notification;
520.17 @@ -723,12 +727,49 @@
520.18 System.out.println(message);
520.19 }
520.20
520.21 + public static Object elementFromComplex(Object complex, String element)
520.22 + throws AttributeNotFoundException {
520.23 + try {
520.24 + if (complex.getClass().isArray() && element.equals("length")) {
520.25 + return Array.getLength(complex);
520.26 + } else if (complex instanceof CompositeData) {
520.27 + return ((CompositeData) complex).get(element);
520.28 + } else {
520.29 + // Java Beans introspection
520.30 + //
520.31 + BeanInfo bi = java.beans.Introspector.getBeanInfo(complex.getClass());
520.32 + PropertyDescriptor[] pds = bi.getPropertyDescriptors();
520.33 + System.out.println("PDs: " + pds.length);
520.34 + for (PropertyDescriptor pd : pds) {
520.35 + System.out.println("Property: " + pd.getName());
520.36 + if (pd.getName().equals(element))
520.37 + return pd.getReadMethod().invoke(complex);
520.38 + }
520.39 + throw new AttributeNotFoundException(
520.40 + "Could not find the getter method for the property " +
520.41 + element + " using the Java Beans introspector");
520.42 + }
520.43 + } catch (InvocationTargetException e) {
520.44 + throw new IllegalArgumentException(e);
520.45 + } catch (AttributeNotFoundException e) {
520.46 + throw e;
520.47 + } catch (Exception e) {
520.48 + AttributeNotFoundException anfe =
520.49 + new AttributeNotFoundException(e.getMessage());
520.50 + anfe.initCause(e);
520.51 + throw anfe;
520.52 + }
520.53 + }
520.54 +
520.55 /*
520.56 * Standalone entry point.
520.57 *
520.58 * Run the test and report to stdout.
520.59 */
520.60 public static void main (String args[]) throws Exception {
520.61 + Match match = Match.do_match_now;
520.62 + String name = (String) elementFromComplex(match, "name");
520.63 + System.out.println("name: " + name);
520.64 AttributeArbitraryDataTypeTest test =
520.65 new AttributeArbitraryDataTypeTest();
520.66 int error = test.monitorNotifications();
521.1 --- a/test/javax/management/monitor/InstantiateMonitorNotificationTest.java Mon Nov 23 10:04:47 2009 +0000
521.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
521.3 @@ -1,52 +0,0 @@
521.4 -
521.5 -import javax.management.ObjectName;
521.6 -import javax.management.monitor.MonitorNotification;
521.7 -
521.8 -/*
521.9 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
521.10 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
521.11 - *
521.12 - * This code is free software; you can redistribute it and/or modify it
521.13 - * under the terms of the GNU General Public License version 2 only, as
521.14 - * published by the Free Software Foundation.
521.15 - *
521.16 - * This code is distributed in the hope that it will be useful, but WITHOUT
521.17 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
521.18 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
521.19 - * version 2 for more details (a copy is included in the LICENSE file that
521.20 - * accompanied this code).
521.21 - *
521.22 - * You should have received a copy of the GNU General Public License version
521.23 - * 2 along with this work; if not, write to the Free Software Foundation,
521.24 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
521.25 - *
521.26 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
521.27 - * CA 95054 USA or visit www.sun.com if you need additional information or
521.28 - * have any questions.
521.29 - */
521.30 -
521.31 -/*
521.32 - * @test
521.33 - * @bug 6373143
521.34 - * @summary Test MonitorNotification public constructor
521.35 - * @author JFDenise
521.36 - * @run clean InstantiateMonitorNotificationTest
521.37 - * @run build InstantiateMonitorNotificationTest
521.38 - * @run main InstantiateMonitorNotificationTest
521.39 - */
521.40 -
521.41 -public class InstantiateMonitorNotificationTest {
521.42 -
521.43 - public static void main(String[] args) throws Exception {
521.44 - MonitorNotification notif = new MonitorNotification("com.foo.test",
521.45 - ObjectName.valueOf(":type=Monitor"),
521.46 - 999,
521.47 - 999,
521.48 - "A message",
521.49 - ObjectName.valueOf(":type=Observed"),
521.50 - "MyAttribute",
521.51 - Integer.valueOf(14),
521.52 - Integer.valueOf(15));
521.53 - System.out.println("Test passed");
521.54 - }
521.55 -}
522.1 --- a/test/javax/management/mxbean/CustomTypeTest.java Mon Nov 23 10:04:47 2009 +0000
522.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
522.3 @@ -1,642 +0,0 @@
522.4 -/*
522.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
522.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
522.7 - *
522.8 - * This code is free software; you can redistribute it and/or modify it
522.9 - * under the terms of the GNU General Public License version 2 only, as
522.10 - * published by the Free Software Foundation.
522.11 - *
522.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
522.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
522.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
522.15 - * version 2 for more details (a copy is included in the LICENSE file that
522.16 - * accompanied this code).
522.17 - *
522.18 - * You should have received a copy of the GNU General Public License version
522.19 - * 2 along with this work; if not, write to the Free Software Foundation,
522.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
522.21 - *
522.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
522.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
522.24 - * have any questions.
522.25 - */
522.26 -
522.27 -/* @test %M% %I%
522.28 - * @bug 6562936 6750935
522.29 - * @run compile customtypes/package-info.java
522.30 - * @run main CustomTypeTest
522.31 - */
522.32 -
522.33 -import java.io.InvalidObjectException;
522.34 -import java.lang.management.ManagementFactory;
522.35 -import java.lang.reflect.Array;
522.36 -import java.lang.reflect.InvocationHandler;
522.37 -import java.lang.reflect.Method;
522.38 -import java.lang.reflect.Proxy;
522.39 -import java.lang.reflect.Type;
522.40 -import java.util.ArrayList;
522.41 -import java.util.Arrays;
522.42 -import java.util.Collection;
522.43 -import java.util.Date;
522.44 -import java.util.Iterator;
522.45 -import java.util.List;
522.46 -import javax.management.JMX;
522.47 -import javax.management.MBeanServer;
522.48 -import javax.management.ObjectName;
522.49 -import javax.management.StandardMBean;
522.50 -import javax.management.Descriptor;
522.51 -import javax.management.MBeanServerInvocationHandler;
522.52 -import javax.management.NotCompliantMBeanException;
522.53 -import javax.management.openmbean.ArrayType;
522.54 -import javax.management.openmbean.CompositeData;
522.55 -import javax.management.openmbean.CompositeDataSupport;
522.56 -import javax.management.openmbean.CompositeType;
522.57 -import javax.management.openmbean.MXBeanMapping;
522.58 -import javax.management.openmbean.MXBeanMappingClass;
522.59 -import javax.management.openmbean.MXBeanMappingFactory;
522.60 -import javax.management.openmbean.MXBeanMappingFactoryClass;
522.61 -import javax.management.openmbean.OpenDataException;
522.62 -import javax.management.openmbean.OpenType;
522.63 -import javax.management.openmbean.SimpleType;
522.64 -import javax.management.openmbean.TabularData;
522.65 -
522.66 -import static javax.management.JMX.MBeanOptions;
522.67 -
522.68 -import customtypes.*;
522.69 -
522.70 -public class CustomTypeTest {
522.71 - @MXBeanMappingClass(LinkedListMapping.class)
522.72 - public static class LinkedList {
522.73 - private final String name;
522.74 - private final LinkedList next;
522.75 -
522.76 - public LinkedList(String name, LinkedList next) {
522.77 - this.name = name;
522.78 - this.next = next;
522.79 - }
522.80 -
522.81 - public String getName() {
522.82 - return name;
522.83 - }
522.84 -
522.85 - public LinkedList getNext() {
522.86 - return next;
522.87 - }
522.88 -
522.89 - public String toString() {
522.90 - if (next == null)
522.91 - return "(" + name + ")";
522.92 - else
522.93 - return "(" + name + " " + next + ")";
522.94 - }
522.95 -
522.96 - public boolean equals(Object x) {
522.97 - if (!(x instanceof LinkedList))
522.98 - return false;
522.99 - LinkedList other = (LinkedList) x;
522.100 - return (this.name.equals(other.name) &&
522.101 - (this.next == null ? other.next == null :
522.102 - this.next.equals(other.next)));
522.103 - }
522.104 - }
522.105 -
522.106 - public static class LinkedListMapping extends MXBeanMapping {
522.107 - public LinkedListMapping(Type type) throws OpenDataException {
522.108 - super(LinkedList.class, ArrayType.getArrayType(SimpleType.STRING));
522.109 - if (type != LinkedList.class) {
522.110 - throw new OpenDataException("Mapping only valid for " +
522.111 - LinkedList.class);
522.112 - }
522.113 - }
522.114 -
522.115 - public Object fromOpenValue(Object openValue) throws InvalidObjectException {
522.116 - String[] array = (String[]) openValue;
522.117 - LinkedList list = null;
522.118 - for (int i = array.length - 1; i >= 0; i--)
522.119 - list = new LinkedList(array[i], list);
522.120 - return list;
522.121 - }
522.122 -
522.123 - public Object toOpenValue(Object javaValue) throws OpenDataException {
522.124 - ArrayList<String> array = new ArrayList<String>();
522.125 - for (LinkedList list = (LinkedList) javaValue; list != null;
522.126 - list = list.getNext())
522.127 - array.add(list.getName());
522.128 - return array.toArray(new String[0]);
522.129 - }
522.130 - }
522.131 -
522.132 - public static interface LinkedListMXBean {
522.133 - public LinkedList getLinkedList();
522.134 - }
522.135 -
522.136 - public static class LinkedListImpl implements LinkedListMXBean {
522.137 - public LinkedList getLinkedList() {
522.138 - return new LinkedList("car", new LinkedList("cdr", null));
522.139 - }
522.140 - }
522.141 -
522.142 - public static class ObjectMXBeanMapping extends MXBeanMapping {
522.143 - private static final CompositeType wildcardType;
522.144 -
522.145 - static {
522.146 - try {
522.147 - wildcardType =
522.148 - new CompositeType(Object.class.getName(),
522.149 - "Wildcard type for Object",
522.150 - new String[0], // itemNames
522.151 - new String[0], // itemDescriptions
522.152 - new OpenType<?>[0]); // itemTypes
522.153 - } catch (OpenDataException e) {
522.154 - throw new RuntimeException(e);
522.155 - }
522.156 - }
522.157 -
522.158 - public ObjectMXBeanMapping() {
522.159 - super(Object.class, wildcardType);
522.160 - }
522.161 -
522.162 - public Object fromOpenValue(Object openValue) throws InvalidObjectException {
522.163 - if (!(openValue instanceof CompositeData)) {
522.164 - throw new InvalidObjectException("Not a CompositeData: " +
522.165 - openValue.getClass());
522.166 - }
522.167 - CompositeData cd = (CompositeData) openValue;
522.168 - if (!cd.containsKey("value")) {
522.169 - throw new InvalidObjectException("CompositeData does not " +
522.170 - "contain a \"value\" item: " + cd);
522.171 - }
522.172 - Object x = cd.get("value");
522.173 - if (!(x instanceof CompositeData || x instanceof TabularData ||
522.174 - x instanceof Object[]))
522.175 - return x;
522.176 -
522.177 - String typeName = (String) cd.get("type");
522.178 - if (typeName == null) {
522.179 - throw new InvalidObjectException("CompositeData does not " +
522.180 - "contain a \"type\" item: " + cd);
522.181 - }
522.182 - Class<?> c;
522.183 - try {
522.184 - c = Class.forName(typeName);
522.185 - } catch (ClassNotFoundException e) {
522.186 - InvalidObjectException ioe =
522.187 - new InvalidObjectException("Could not find type");
522.188 - ioe.initCause(e);
522.189 - throw ioe;
522.190 - }
522.191 - MXBeanMapping mapping;
522.192 - try {
522.193 - mapping = objectMappingFactory.mappingForType(c, objectMappingFactory);
522.194 - } catch (OpenDataException e) {
522.195 - InvalidObjectException ioe =
522.196 - new InvalidObjectException("Could not map object's " +
522.197 - "type " + c.getName());
522.198 - ioe.initCause(e);
522.199 - throw ioe;
522.200 - }
522.201 - return mapping.fromOpenValue(x);
522.202 - }
522.203 -
522.204 - public Object toOpenValue(Object javaValue) throws OpenDataException {
522.205 - OpenType<?> openType;
522.206 - Object openValue;
522.207 - String typeName;
522.208 - if (javaValue == null) {
522.209 - openType = SimpleType.VOID;
522.210 - openValue = null;
522.211 - typeName = null;
522.212 - } else {
522.213 - Class<?> c = javaValue.getClass();
522.214 - if (c.equals(Object.class))
522.215 - throw new OpenDataException("Cannot map Object to an open value");
522.216 - MXBeanMapping mapping =
522.217 - objectMappingFactory.mappingForType(c, objectMappingFactory);
522.218 - openType = mapping.getOpenType();
522.219 - openValue = mapping.toOpenValue(javaValue);
522.220 - typeName = c.getName();
522.221 - }
522.222 - CompositeType ct = new CompositeType(
522.223 - (javaValue == null) ? "null" : openType.getClassName(),
522.224 - "Open Mapping for Object",
522.225 - new String[] {"type", "value"},
522.226 - new String[] {"type", "value"},
522.227 - new OpenType<?>[] {SimpleType.STRING, openType});
522.228 - return new CompositeDataSupport(
522.229 - ct,
522.230 - new String[] {"type", "value"},
522.231 - new Object[] {typeName, openValue});
522.232 - }
522.233 - }
522.234 -
522.235 - public static class ObjectMappingFactory extends MXBeanMappingFactory {
522.236 - private static MXBeanMapping objectMapping =
522.237 - new ObjectMXBeanMapping();
522.238 -
522.239 - @Override
522.240 - public MXBeanMapping mappingForType(Type t, MXBeanMappingFactory f)
522.241 - throws OpenDataException {
522.242 - if (t.equals(Object.class))
522.243 - return objectMapping;
522.244 - else
522.245 - return MXBeanMappingFactory.DEFAULT.mappingForType(t, f);
522.246 - }
522.247 - }
522.248 -
522.249 - private static MXBeanMappingFactory objectMappingFactory =
522.250 - new ObjectMappingFactory();
522.251 -
522.252 - public static interface ObjectMXBean {
522.253 - public Object getObject();
522.254 - public Object[] getObjects();
522.255 - public List<Object> getObjectList();
522.256 - public Object[][] getMoreObjects();
522.257 - }
522.258 -
522.259 - public static class ObjectImpl implements ObjectMXBean {
522.260 - public Object getObject() {
522.261 - return 123;
522.262 - }
522.263 -
522.264 - private static Object[] objects = {
522.265 - "foo", 3, 3.14f, 3.14, 3L, new Date(), ObjectName.WILDCARD,
522.266 - new byte[3], new char[3], new int[3][3],
522.267 - new LinkedListImpl().getLinkedList(),
522.268 - };
522.269 -
522.270 - public Object[] getObjects() {
522.271 - return objects;
522.272 - }
522.273 -
522.274 - public List<Object> getObjectList() {
522.275 - return Arrays.asList(getObjects());
522.276 - }
522.277 -
522.278 - public Object[][] getMoreObjects() {
522.279 - return new Object[][] {{getObjects()}};
522.280 - }
522.281 - }
522.282 -
522.283 - @MXBeanMappingFactoryClass(ObjectMappingFactory.class)
522.284 - public static interface AnnotatedObjectMXBean extends ObjectMXBean {}
522.285 -
522.286 - public static class AnnotatedObjectImpl extends ObjectImpl
522.287 - implements AnnotatedObjectMXBean {}
522.288 -
522.289 - public static class BrokenMappingFactory extends MXBeanMappingFactory {
522.290 - public MXBeanMapping mappingForType(Type t, MXBeanMappingFactory f)
522.291 - throws OpenDataException {
522.292 - throw new OpenDataException(t.toString());
522.293 - }
522.294 - }
522.295 -
522.296 - public static class ReallyBrokenMappingFactory extends BrokenMappingFactory {
522.297 - public ReallyBrokenMappingFactory() {
522.298 - throw new RuntimeException("Oops");
522.299 - }
522.300 - }
522.301 -
522.302 - @MXBeanMappingFactoryClass(BrokenMappingFactory.class)
522.303 - public static interface BrokenMXBean {
522.304 - public int getX();
522.305 - }
522.306 -
522.307 - public static class BrokenImpl implements BrokenMXBean {
522.308 - public int getX() {return 0;}
522.309 - }
522.310 -
522.311 - @MXBeanMappingFactoryClass(ReallyBrokenMappingFactory.class)
522.312 - public static interface ReallyBrokenMXBean {
522.313 - public int getX();
522.314 - }
522.315 -
522.316 - public static class ReallyBrokenImpl implements ReallyBrokenMXBean {
522.317 - public int getX() {return 0;}
522.318 - }
522.319 -
522.320 - public static class BrokenMapping extends MXBeanMapping {
522.321 - public BrokenMapping(Type t) {
522.322 - super(t, SimpleType.STRING);
522.323 - throw new RuntimeException("Oops");
522.324 - }
522.325 -
522.326 - public Object fromOpenValue(Object openValue) throws InvalidObjectException {
522.327 - throw new AssertionError();
522.328 - }
522.329 -
522.330 - public Object toOpenValue(Object javaValue) throws OpenDataException {
522.331 - throw new AssertionError();
522.332 - }
522.333 - }
522.334 -
522.335 - @MXBeanMappingClass(BrokenMapping.class)
522.336 - public static class BrokenType {}
522.337 -
522.338 - public static interface BrokenTypeMXBean {
522.339 - BrokenType getBroken();
522.340 - }
522.341 -
522.342 - public static class BrokenTypeImpl implements BrokenTypeMXBean {
522.343 - public BrokenType getBroken() {
522.344 - throw new AssertionError();
522.345 - }
522.346 - }
522.347 -
522.348 - public static class BadConstructorMXBeanMappingFactory1 extends
522.349 - MXBeanMappingFactory {
522.350 - private BadConstructorMXBeanMappingFactory1() {}
522.351 -
522.352 - @Override
522.353 - public MXBeanMapping mappingForType(Type arg0, MXBeanMappingFactory arg1)
522.354 - throws OpenDataException {
522.355 - throw new UnsupportedOperationException("Should not be called");
522.356 - }
522.357 - }
522.358 -
522.359 - public static class BadConstructorMXBeanMappingFactory2 extends
522.360 - MXBeanMappingFactory {
522.361 - public BadConstructorMXBeanMappingFactory2(boolean oops) {}
522.362 -
522.363 - @Override
522.364 - public MXBeanMapping mappingForType(Type arg0, MXBeanMappingFactory arg1)
522.365 - throws OpenDataException {
522.366 - throw new UnsupportedOperationException("Should not be called");
522.367 - }
522.368 - }
522.369 -
522.370 - @MXBeanMappingFactoryClass(BadConstructorMXBeanMappingFactory1.class)
522.371 - public static interface BadConstructor1MXBean {}
522.372 -
522.373 - public static class BadConstructor1 implements BadConstructor1MXBean {}
522.374 -
522.375 - @MXBeanMappingFactoryClass(BadConstructorMXBeanMappingFactory2.class)
522.376 - public static interface BadConstructor2MXBean {}
522.377 -
522.378 - public static class BadConstructor2 implements BadConstructor2MXBean {}
522.379 -
522.380 - public static void main(String[] args) throws Exception {
522.381 - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
522.382 -
522.383 - System.out.println("Test @MXBeanMappingClass");
522.384 - ObjectName linkedName = new ObjectName("d:type=LinkedList");
522.385 - LinkedListMXBean linkedListMXBean = new LinkedListImpl();
522.386 - LinkedList list1 = linkedListMXBean.getLinkedList();
522.387 - mbs.registerMBean(linkedListMXBean, linkedName);
522.388 - LinkedListMXBean linkedProxy =
522.389 - JMX.newMXBeanProxy(mbs, linkedName, LinkedListMXBean.class);
522.390 - MBeanServerInvocationHandler mbsih = (MBeanServerInvocationHandler)
522.391 - Proxy.getInvocationHandler(linkedProxy);
522.392 - if (!mbsih.isMXBean())
522.393 - fail("not MXBean proxy");
522.394 - LinkedList list2 = linkedProxy.getLinkedList();
522.395 - if (list1 == list2)
522.396 - fail("lists identical!");
522.397 - // They should have gone through the mapping and back,
522.398 - // and the mapping doesn't do anything that would allow it
522.399 - // to restore the identical object.
522.400 - if (!list1.equals(list2))
522.401 - fail("lists different: " + list1 + " vs " + list2);
522.402 - System.out.println("...success");
522.403 -
522.404 - System.out.println("Test StandardMBean with MXBeanMappingFactory");
522.405 - ObjectMXBean wildcardMBean = new ObjectImpl();
522.406 - MBeanOptions options = new MBeanOptions();
522.407 - options.setMXBeanMappingFactory(objectMappingFactory);
522.408 - if (!options.isMXBean())
522.409 - fail("Setting MXBeanMappingFactory should imply MXBean");
522.410 - StandardMBean wildcardStandardMBean =
522.411 - new StandardMBean(wildcardMBean, ObjectMXBean.class, options);
522.412 - testWildcardMBean(mbs, wildcardMBean, wildcardStandardMBean,
522.413 - options, ObjectMXBean.class);
522.414 -
522.415 - System.out.println("Test @MXBeanMappingFactoryClass on interface");
522.416 - ObjectMXBean annotatedWildcardMBean = new AnnotatedObjectImpl();
522.417 - testWildcardMBean(mbs, annotatedWildcardMBean, annotatedWildcardMBean,
522.418 - null, AnnotatedObjectMXBean.class);
522.419 -
522.420 - System.out.println("Test @MXBeanMappingFactoryClass on package");
522.421 - CustomMXBean custom = zeroProxy(CustomMXBean.class);
522.422 - ObjectName customName = new ObjectName("d:type=Custom");
522.423 - mbs.registerMBean(custom, customName);
522.424 - Object x = mbs.getAttribute(customName, "X");
522.425 - if (!(x instanceof String))
522.426 - fail("Should be String: " + x + " (a " + x.getClass().getName() + ")");
522.427 - CustomMXBean customProxy =
522.428 - JMX.newMXBeanProxy(mbs, customName, CustomMXBean.class);
522.429 - x = customProxy.getX();
522.430 - if (!(x instanceof Integer) || (Integer) x != 0)
522.431 - fail("Wrong return from proxy: " + x + " (a " + x.getClass().getName() + ")");
522.432 -
522.433 - System.out.println("Test MXBeanMappingFactory exception");
522.434 - try {
522.435 - mbs.registerMBean(new BrokenImpl(), new ObjectName("d:type=Broken"));
522.436 - fail("Register did not throw exception");
522.437 - } catch (NotCompliantMBeanException e) {
522.438 - System.out.println("...OK: threw: " + e);
522.439 - }
522.440 -
522.441 - System.out.println("Test MXBeanMappingFactory constructor exception");
522.442 - try {
522.443 - mbs.registerMBean(new ReallyBrokenImpl(), new ObjectName("d:type=Broken"));
522.444 - fail("Register did not throw exception");
522.445 - } catch (NotCompliantMBeanException e) {
522.446 - System.out.println("...OK: threw: " + e);
522.447 - } catch (Exception e) {
522.448 - fail("Register threw wrong exception: " + e);
522.449 - }
522.450 -
522.451 - System.out.println("Test MXBeanMappingFactory exception with StandardMBean");
522.452 - MXBeanMappingFactory brokenF = new BrokenMappingFactory();
522.453 - MBeanOptions brokenO = new MBeanOptions();
522.454 - brokenO.setMXBeanMappingFactory(brokenF);
522.455 - try {
522.456 - new StandardMBean(wildcardMBean, ObjectMXBean.class, brokenO);
522.457 - fail("StandardMBean with broken factory did not throw exception");
522.458 - } catch (IllegalArgumentException e) {
522.459 - if (!(e.getCause() instanceof NotCompliantMBeanException)) {
522.460 - fail("StandardMBean with broken factory threw wrong exception: "
522.461 - + e.getCause());
522.462 - }
522.463 - }
522.464 -
522.465 - System.out.println("Test MXBeanMappingClass exception");
522.466 - try {
522.467 - mbs.registerMBean(new BrokenTypeImpl(), new ObjectName("d:type=Broken"));
522.468 - fail("Broken MXBeanMappingClass did not throw exception");
522.469 - } catch (NotCompliantMBeanException e) {
522.470 - System.out.println("...OK: threw: " + e);
522.471 - }
522.472 -
522.473 - System.out.println("Test MXBeanMappingFactoryClass constructor exception");
522.474 - for (Object mbean : new Object[] {
522.475 - new BadConstructor1(), new BadConstructor2(),
522.476 - }) {
522.477 - String testName = mbean.getClass().getSimpleName();
522.478 - try {
522.479 - ObjectName name = new ObjectName("d:type=" + testName);
522.480 - mbs.registerMBean(mbean, name);
522.481 - fail("Broken MXBeanMappingFactoryClass did not throw exception" +
522.482 - " (" + testName + ")");
522.483 - } catch (NotCompliantMBeanException e) {
522.484 - System.out.println("...OK: " + testName + " threw: " + e);
522.485 - } catch (Exception e) {
522.486 - fail("Broken MXBeanMappingFactoryClass " + testName + " threw " +
522.487 - "wrong exception: " + e);
522.488 - }
522.489 - }
522.490 -
522.491 - if (failure == null)
522.492 - System.out.println("TEST PASSED");
522.493 - else
522.494 - throw new Exception("TEST FAILED: " + failure);
522.495 - }
522.496 -
522.497 - private static void testWildcardMBean(MBeanServer mbs, ObjectMXBean impl,
522.498 - Object mbean,
522.499 - MBeanOptions proxyOptions,
522.500 - Class<? extends ObjectMXBean> intf)
522.501 - throws Exception {
522.502 - ObjectName wildcardName = new ObjectName("d:type=Object");
522.503 - mbs.registerMBean(mbean, wildcardName);
522.504 - try {
522.505 - testWildcardMBean2(mbs, impl, wildcardName, proxyOptions, intf);
522.506 - } finally {
522.507 - mbs.unregisterMBean(wildcardName);
522.508 - }
522.509 - }
522.510 -
522.511 - private static void testWildcardMBean2(MBeanServer mbs, ObjectMXBean impl,
522.512 - ObjectName wildcardName,
522.513 - MBeanOptions proxyOptions,
522.514 - Class<? extends ObjectMXBean> intf)
522.515 - throws Exception {
522.516 - if (proxyOptions == null) {
522.517 - proxyOptions = new MBeanOptions();
522.518 - MXBeanMappingFactory f = MXBeanMappingFactory.forInterface(intf);
522.519 - proxyOptions.setMXBeanMappingFactory(f);
522.520 - }
522.521 - Descriptor d = mbs.getMBeanInfo(wildcardName).getDescriptor();
522.522 - String factoryName = (String)
522.523 - d.getFieldValue(JMX.MXBEAN_MAPPING_FACTORY_CLASS_FIELD);
522.524 - if (!ObjectMappingFactory.class.getName().equals(factoryName)) {
522.525 - fail("Descriptor has wrong MXBeanMappingFactory: " + factoryName +
522.526 - " should be " + ObjectMappingFactory.class.getName());
522.527 - }
522.528 - ObjectMXBean wildcardProxy =
522.529 - JMX.newMBeanProxy(mbs, wildcardName, intf, proxyOptions);
522.530 - MBeanServerInvocationHandler mbsih = (MBeanServerInvocationHandler)
522.531 - Proxy.getInvocationHandler(wildcardProxy);
522.532 - MBeanOptions opts = mbsih.getMBeanOptions();
522.533 - if (!opts.equals(proxyOptions)) {
522.534 - fail("Proxy options differ from request: " + opts + " vs " +
522.535 - proxyOptions);
522.536 - }
522.537 - Method[] wildcardMethods = ObjectMXBean.class.getMethods();
522.538 - for (Method m : wildcardMethods) {
522.539 - System.out.println("..." + m.getName());
522.540 - Object orig = m.invoke(impl);
522.541 - Object copy = m.invoke(wildcardProxy);
522.542 - if (!deepEquals(orig, copy)) {
522.543 - fail("objects differ: " + deepToString(orig) + " vs " +
522.544 - deepToString(copy));
522.545 - }
522.546 - }
522.547 - }
522.548 -
522.549 - private static <T> T zeroProxy(Class<T> intf) {
522.550 - return intf.cast(Proxy.newProxyInstance(intf.getClassLoader(),
522.551 - new Class<?>[] {intf},
522.552 - new ZeroInvocationHandler()));
522.553 - }
522.554 -
522.555 - private static class ZeroInvocationHandler implements InvocationHandler {
522.556 - public Object invoke(Object proxy, Method method, Object[] args)
522.557 - throws Throwable {
522.558 - return 0;
522.559 - }
522.560 - }
522.561 -
522.562 - private static boolean deepEquals(Object x, Object y) {
522.563 - if (x == y)
522.564 - return true;
522.565 - if (x == null || y == null)
522.566 - return false;
522.567 -
522.568 - if (x instanceof Collection<?>) {
522.569 - if (!(y instanceof Collection<?>))
522.570 - return false;
522.571 - Collection<?> xcoll = (Collection<?>) x;
522.572 - Collection<?> ycoll = (Collection<?>) y;
522.573 - if (xcoll.size() != ycoll.size())
522.574 - return false;
522.575 - Iterator<?> xit = xcoll.iterator();
522.576 - Iterator<?> yit = ycoll.iterator();
522.577 - while (xit.hasNext()) {
522.578 - if (!deepEquals(xit.next(), yit.next()))
522.579 - return false;
522.580 - }
522.581 - return true;
522.582 - }
522.583 -
522.584 - Class<?> xclass = x.getClass();
522.585 - Class<?> yclass = y.getClass();
522.586 - if (xclass.isArray()) {
522.587 - if (!yclass.isArray())
522.588 - return false;
522.589 - if (!xclass.getComponentType().equals(yclass.getComponentType()))
522.590 - return false;
522.591 - int len = Array.getLength(x);
522.592 - if (Array.getLength(y) != len)
522.593 - return false;
522.594 - for (int i = 0; i < len; i++) {
522.595 - if (!deepEquals(Array.get(x, i), Array.get(y, i)))
522.596 - return false;
522.597 - }
522.598 - return true;
522.599 - }
522.600 -
522.601 -// return x.equals(y);
522.602 - if (x.equals(y))
522.603 - return true;
522.604 - System.out.println("Not equal: <" + x + "> and <" + y + ">");
522.605 - return false;
522.606 - }
522.607 -
522.608 - private static String deepToString(Object x) {
522.609 - if (x == null)
522.610 - return "null";
522.611 -
522.612 - if (x instanceof Collection<?>) {
522.613 - Collection<?> xcoll = (Collection<?>) x;
522.614 - StringBuilder sb = new StringBuilder("[");
522.615 - for (Object e : xcoll) {
522.616 - if (sb.length() > 1)
522.617 - sb.append(", ");
522.618 - sb.append(deepToString(e));
522.619 - }
522.620 - sb.append("]");
522.621 - return sb.toString();
522.622 - }
522.623 -
522.624 - if (x instanceof Object[]) {
522.625 - Object[] xarr = (Object[]) x;
522.626 - return deepToString(Arrays.asList(xarr));
522.627 - }
522.628 -
522.629 - if (x.getClass().isArray()) { // primitive array
522.630 - String s = Arrays.deepToString(new Object[] {x});
522.631 - return s.substring(1, s.length() - 1);
522.632 - }
522.633 -
522.634 - return x.toString();
522.635 - }
522.636 -
522.637 - private static void fail(String msg) {
522.638 - System.out.println("TEST FAILED: " + msg);
522.639 - if (msg.length() > 100)
522.640 - msg = msg.substring(0, 100) + "...";
522.641 - failure = msg;
522.642 - }
522.643 -
522.644 - private static String failure;
522.645 -}
523.1 --- a/test/javax/management/mxbean/ExceptionDiagnosisTest.java Mon Nov 23 10:04:47 2009 +0000
523.2 +++ b/test/javax/management/mxbean/ExceptionDiagnosisTest.java Wed Nov 25 11:08:25 2009 -0800
523.3 @@ -1,3 +1,26 @@
523.4 +/*
523.5 + * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
523.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
523.7 + *
523.8 + * This code is free software; you can redistribute it and/or modify it
523.9 + * under the terms of the GNU General Public License version 2 only, as
523.10 + * published by the Free Software Foundation.
523.11 + *
523.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
523.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
523.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
523.15 + * version 2 for more details (a copy is included in the LICENSE file that
523.16 + * accompanied this code).
523.17 + *
523.18 + * You should have received a copy of the GNU General Public License version
523.19 + * 2 along with this work; if not, write to the Free Software Foundation,
523.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
523.21 + *
523.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
523.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
523.24 + * have any questions.
523.25 + */
523.26 +
523.27 /*
523.28 * @test
523.29 * @bug 6713777
523.30 @@ -180,7 +203,6 @@
523.31 private static void testCaseProb() throws Exception {
523.32 MBeanServer mbs = MBeanServerFactory.newMBeanServer();
523.33 ObjectName name = new ObjectName("a:b=c");
523.34 - Object mbean = new CaseProbImpl();
523.35 mbs.registerMBean(new CaseProbImpl(), name);
523.36 CaseProbMXBean proxy = JMX.newMXBeanProxy(mbs, name, CaseProbMXBean.class);
523.37 try {
524.1 --- a/test/javax/management/mxbean/JMXServiceURLTest.java Mon Nov 23 10:04:47 2009 +0000
524.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
524.3 @@ -1,216 +0,0 @@
524.4 -/*
524.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
524.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
524.7 - *
524.8 - * This code is free software; you can redistribute it and/or modify it
524.9 - * under the terms of the GNU General Public License version 2 only, as
524.10 - * published by the Free Software Foundation.
524.11 - *
524.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
524.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
524.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
524.15 - * version 2 for more details (a copy is included in the LICENSE file that
524.16 - * accompanied this code).
524.17 - *
524.18 - * You should have received a copy of the GNU General Public License version
524.19 - * 2 along with this work; if not, write to the Free Software Foundation,
524.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
524.21 - *
524.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
524.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
524.24 - * have any questions.
524.25 - */
524.26 -
524.27 -/*
524.28 - * @test JMXServiceURLTest
524.29 - * @bug 6607114 6670375 6731410
524.30 - * @summary Test that JMXServiceURL works correctly in MXBeans
524.31 - * @author Eamonn McManus
524.32 - */
524.33 -
524.34 -import java.io.InvalidObjectException;
524.35 -import java.lang.management.ManagementFactory;
524.36 -import java.util.ArrayList;
524.37 -import java.util.HashMap;
524.38 -import java.util.List;
524.39 -import java.util.Map;
524.40 -import javax.management.Attribute;
524.41 -import javax.management.JMX;
524.42 -import javax.management.MBeanException;
524.43 -import javax.management.MBeanServer;
524.44 -import javax.management.ObjectName;
524.45 -import javax.management.openmbean.CompositeData;
524.46 -import javax.management.openmbean.CompositeDataSupport;
524.47 -import javax.management.openmbean.CompositeType;
524.48 -import javax.management.openmbean.OpenType;
524.49 -import javax.management.openmbean.SimpleType;
524.50 -import javax.management.remote.JMXServiceURL;
524.51 -
524.52 -public class JMXServiceURLTest {
524.53 - public static interface UrlMXBean {
524.54 - public JMXServiceURL getUrl();
524.55 - public void setUrl(JMXServiceURL url);
524.56 - }
524.57 -
524.58 - public static class UrlImpl implements UrlMXBean {
524.59 - volatile JMXServiceURL url;
524.60 -
524.61 - public JMXServiceURL getUrl() {
524.62 - return url;
524.63 - }
524.64 -
524.65 - public void setUrl(JMXServiceURL url) {
524.66 - this.url = url;
524.67 - }
524.68 - }
524.69 -
524.70 - private static enum Part {
524.71 - PROTOCOL("protocol", SimpleType.STRING, "rmi", 25, "", "a:b", "/", "?", "#"),
524.72 - HOST("host", SimpleType.STRING, "a.b.c", 25, "a..b", ".a.b", "a.b."),
524.73 - PORT("port", SimpleType.INTEGER, 25, "25", -25),
524.74 - PATH("URLPath", SimpleType.STRING, "/tiddly", 25, "tiddly");
524.75 -
524.76 - Part(String name, OpenType openType, Object validValue, Object... bogusValues) {
524.77 - this.name = name;
524.78 - this.openType = openType;
524.79 - this.validValue = validValue;
524.80 - this.bogusValues = bogusValues;
524.81 - }
524.82 -
524.83 - final String name;
524.84 - final OpenType openType;
524.85 - final Object validValue;
524.86 - final Object[] bogusValues;
524.87 - }
524.88 -
524.89 - public static void main(String[] args) throws Exception {
524.90 - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
524.91 - ObjectName name = new ObjectName("a:b=c");
524.92 - UrlImpl urlImpl = new UrlImpl();
524.93 - mbs.registerMBean(urlImpl, name);
524.94 -
524.95 - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://host:8000/noddy");
524.96 - UrlMXBean proxy = JMX.newMXBeanProxy(mbs, name, UrlMXBean.class);
524.97 - proxy.setUrl(url);
524.98 - assertEquals(url, urlImpl.url);
524.99 - JMXServiceURL url2 = proxy.getUrl();
524.100 - assertEquals(url, url2);
524.101 -
524.102 - CompositeData cd = (CompositeData) mbs.getAttribute(name, "Url");
524.103 - CompositeType ct = cd.getCompositeType();
524.104 - // Make sure it looks like what we expect. This will have to be
524.105 - // changed if ever we add new properties to CompositeType. In that
524.106 - // case this test should also check interoperability between the
524.107 - // current version and the new version.
524.108 - assertEquals(4, ct.keySet().size());
524.109 - Object[][] expectedItems = {
524.110 - {"protocol", SimpleType.STRING, "rmi"},
524.111 - {"host", SimpleType.STRING, "host"},
524.112 - {"port", SimpleType.INTEGER, 8000},
524.113 - {"URLPath", SimpleType.STRING, "/noddy"},
524.114 - };
524.115 - for (Object[] expectedItem : expectedItems) {
524.116 - String itemName = (String) expectedItem[0];
524.117 - OpenType expectedType = (OpenType) expectedItem[1];
524.118 - Object expectedValue = expectedItem[2];
524.119 - OpenType actualType = ct.getType(itemName);
524.120 - assertEquals(expectedType, actualType);
524.121 - Object actualValue = cd.get(itemName);
524.122 - assertEquals(expectedValue, actualValue);
524.123 - }
524.124 -
524.125 - // Now make sure we reject any bogus-looking CompositeData items.
524.126 - // We first try every combination of omitted items (items can be
524.127 - // null but cannot be omitted), then we try every combination of
524.128 - // valid and bogus items.
524.129 - final Part[] parts = Part.values();
524.130 - final int nParts = parts.length;
524.131 - final int maxPartMask = (1 << nParts) - 1;
524.132 - // Iterate over all possibilities of included and omitted, except
524.133 - // 0, because a CompositeDataSupport must have at least one element,
524.134 - // and maxPartMask, where all items are included and the result is valid.
524.135 - for (int mask = 1; mask < maxPartMask; mask++) {
524.136 - Map<String, Object> cdMap = new HashMap<String, Object>();
524.137 - List<String> names = new ArrayList<String>();
524.138 - List<OpenType> types = new ArrayList<OpenType>();
524.139 - for (int i = 0; i < nParts; i++) {
524.140 - if ((mask & (1 << i)) != 0) {
524.141 - Part part = parts[i];
524.142 - cdMap.put(part.name, part.validValue);
524.143 - names.add(part.name);
524.144 - types.add(openTypeForValue(part.validValue));
524.145 - }
524.146 - }
524.147 - String[] nameArray = names.toArray(new String[0]);
524.148 - OpenType[] typeArray = types.toArray(new OpenType[0]);
524.149 - CompositeType badct = new CompositeType(
524.150 - "bad", "descr", nameArray, nameArray, typeArray);
524.151 - CompositeData badcd = new CompositeDataSupport(badct, cdMap);
524.152 - checkBad(mbs, name, badcd);
524.153 - }
524.154 -
524.155 - int nBogus = 1;
524.156 - for (Part part : parts)
524.157 - nBogus *= (part.bogusValues.length + 1);
524.158 - // Iterate over all combinations of bogus values. We are basically
524.159 - // treating each Part as a digit while counting up from 1. A digit
524.160 - // value of 0 stands for the valid value of that Part, and 1 on
524.161 - // stand for the bogus values. Hence an integer where all the digits
524.162 - // are 0 would represent a valid CompositeData, which is why we
524.163 - // start from 1.
524.164 - for (int bogusCount = 1; bogusCount < nBogus; bogusCount++) {
524.165 - List<String> names = new ArrayList<String>();
524.166 - List<OpenType> types = new ArrayList<OpenType>();
524.167 - int x = bogusCount;
524.168 - Map<String, Object> cdMap = new HashMap<String, Object>();
524.169 - for (Part part : parts) {
524.170 - int digitMax = part.bogusValues.length + 1;
524.171 - int digit = x % digitMax;
524.172 - Object value = (digit == 0) ?
524.173 - part.validValue : part.bogusValues[digit - 1];
524.174 - cdMap.put(part.name, value);
524.175 - names.add(part.name);
524.176 - types.add(openTypeForValue(value));
524.177 - x /= digitMax;
524.178 - }
524.179 - String[] nameArray = names.toArray(new String[0]);
524.180 - OpenType[] typeArray = types.toArray(new OpenType[0]);
524.181 - CompositeType badct = new CompositeType(
524.182 - "bad", "descr", nameArray, nameArray, typeArray);
524.183 - CompositeData badcd = new CompositeDataSupport(badct, cdMap);
524.184 - checkBad(mbs, name, badcd);
524.185 - }
524.186 - }
524.187 -
524.188 - private static OpenType openTypeForValue(Object value) {
524.189 - if (value instanceof String)
524.190 - return SimpleType.STRING;
524.191 - else if (value instanceof Integer)
524.192 - return SimpleType.INTEGER;
524.193 - else
524.194 - throw new AssertionError("Value has invalid type: " + value);
524.195 - }
524.196 -
524.197 - private static void checkBad(
524.198 - MBeanServer mbs, ObjectName name, CompositeData badcd)
524.199 - throws Exception {
524.200 - try {
524.201 - mbs.setAttribute(name, new Attribute("Url", badcd));
524.202 - throw new Exception("Expected exception for: " + badcd);
524.203 - } catch (MBeanException e) {
524.204 - if (!(e.getCause() instanceof InvalidObjectException)) {
524.205 - throw new Exception(
524.206 - "Wrapped exception should be InvalidObjectException", e);
524.207 - }
524.208 - System.out.println("OK: rejected " + badcd);
524.209 - }
524.210 - }
524.211 -
524.212 - private static void assertEquals(Object expect, Object actual)
524.213 - throws Exception {
524.214 - if (expect.equals(actual))
524.215 - System.out.println("Equal: " + expect);
524.216 - else
524.217 - throw new Exception("Expected " + expect + ", got " + actual);
524.218 - }
524.219 -}
525.1 --- a/test/javax/management/mxbean/customtypes/CustomLongMXBean.java Mon Nov 23 10:04:47 2009 +0000
525.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
525.3 @@ -1,31 +0,0 @@
525.4 -/*
525.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
525.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
525.7 - *
525.8 - * This code is free software; you can redistribute it and/or modify it
525.9 - * under the terms of the GNU General Public License version 2 only, as
525.10 - * published by the Free Software Foundation.
525.11 - *
525.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
525.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
525.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
525.15 - * version 2 for more details (a copy is included in the LICENSE file that
525.16 - * accompanied this code).
525.17 - *
525.18 - * You should have received a copy of the GNU General Public License version
525.19 - * 2 along with this work; if not, write to the Free Software Foundation,
525.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
525.21 - *
525.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
525.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
525.24 - * have any questions.
525.25 - */
525.26 -
525.27 -// CustomLongMXBean.java - see CustomTypeTest
525.28 -
525.29 -package customtypes;
525.30 -
525.31 -import javax.management.openmbean.MXBeanMappingFactoryClass;
525.32 -
525.33 -@MXBeanMappingFactoryClass(IntegerIsLongFactory.class)
525.34 -public interface CustomLongMXBean extends CustomMXBean {}
526.1 --- a/test/javax/management/mxbean/customtypes/CustomMXBean.java Mon Nov 23 10:04:47 2009 +0000
526.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
526.3 @@ -1,30 +0,0 @@
526.4 -/*
526.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
526.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
526.7 - *
526.8 - * This code is free software; you can redistribute it and/or modify it
526.9 - * under the terms of the GNU General Public License version 2 only, as
526.10 - * published by the Free Software Foundation.
526.11 - *
526.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
526.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
526.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
526.15 - * version 2 for more details (a copy is included in the LICENSE file that
526.16 - * accompanied this code).
526.17 - *
526.18 - * You should have received a copy of the GNU General Public License version
526.19 - * 2 along with this work; if not, write to the Free Software Foundation,
526.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
526.21 - *
526.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
526.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
526.24 - * have any questions.
526.25 - */
526.26 -
526.27 -// CustomMXBean.java - see CustomTypeTest
526.28 -
526.29 -package customtypes;
526.30 -
526.31 -public interface CustomMXBean {
526.32 - public Integer getX();
526.33 -}
527.1 --- a/test/javax/management/mxbean/customtypes/IntegerIsLongFactory.java Mon Nov 23 10:04:47 2009 +0000
527.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
527.3 @@ -1,74 +0,0 @@
527.4 -/*
527.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
527.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
527.7 - *
527.8 - * This code is free software; you can redistribute it and/or modify it
527.9 - * under the terms of the GNU General Public License version 2 only, as
527.10 - * published by the Free Software Foundation.
527.11 - *
527.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
527.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
527.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
527.15 - * version 2 for more details (a copy is included in the LICENSE file that
527.16 - * accompanied this code).
527.17 - *
527.18 - * You should have received a copy of the GNU General Public License version
527.19 - * 2 along with this work; if not, write to the Free Software Foundation,
527.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
527.21 - *
527.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
527.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
527.24 - * have any questions.
527.25 - */
527.26 -
527.27 -// IntegerIsLongFactory.java - see CustomTypeTest
527.28 -
527.29 -package customtypes;
527.30 -
527.31 -import java.io.InvalidObjectException;
527.32 -import java.lang.reflect.Type;
527.33 -import javax.management.openmbean.MXBeanMapping;
527.34 -import javax.management.openmbean.MXBeanMappingFactory;
527.35 -import javax.management.openmbean.OpenDataException;
527.36 -import javax.management.openmbean.SimpleType;
527.37 -
527.38 -public class IntegerIsLongFactory implements MXBeanMappingFactory {
527.39 - public MXBeanMapping forType(Type t, MXBeanMappingFactory f)
527.40 - throws OpenDataException {
527.41 - if (t == Integer.class)
527.42 - return IntegerIsLongMapping;
527.43 - else
527.44 - return MXBeanMappingFactory.DEFAULT.forType(t, f);
527.45 - }
527.46 -
527.47 - private static final MXBeanMapping IntegerIsLongMapping =
527.48 - new IntegerIsLongMapping();
527.49 -
527.50 - private static class IntegerIsLongMapping extends MXBeanMapping {
527.51 - IntegerIsLongMapping() {
527.52 - super(Integer.class, SimpleType.STRING);
527.53 - }
527.54 -
527.55 - public Object fromOpenValue(Object openValue)
527.56 - throws InvalidObjectException {
527.57 - try {
527.58 - return (Long) openValue;
527.59 - } catch (Exception e) {
527.60 - InvalidObjectException ioe = new InvalidObjectException("oops");
527.61 - ioe.initCause(e);
527.62 - throw ioe;
527.63 - }
527.64 - }
527.65 -
527.66 - public Object toOpenValue(Object javaValue) throws OpenDataException {
527.67 - try {
527.68 - Integer i = (Integer) javaValue;
527.69 - return new Long((int) i);
527.70 - } catch (Exception e) {
527.71 - OpenDataException ode = new OpenDataException("oops");
527.72 - ode.initCause(e);
527.73 - throw ode;
527.74 - }
527.75 - }
527.76 - }
527.77 -}
528.1 --- a/test/javax/management/mxbean/customtypes/IntegerIsStringFactory.java Mon Nov 23 10:04:47 2009 +0000
528.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
528.3 @@ -1,76 +0,0 @@
528.4 -/*
528.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
528.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
528.7 - *
528.8 - * This code is free software; you can redistribute it and/or modify it
528.9 - * under the terms of the GNU General Public License version 2 only, as
528.10 - * published by the Free Software Foundation.
528.11 - *
528.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
528.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
528.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
528.15 - * version 2 for more details (a copy is included in the LICENSE file that
528.16 - * accompanied this code).
528.17 - *
528.18 - * You should have received a copy of the GNU General Public License version
528.19 - * 2 along with this work; if not, write to the Free Software Foundation,
528.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
528.21 - *
528.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
528.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
528.24 - * have any questions.
528.25 - */
528.26 -
528.27 -// IntegerIsStringFactory.java - see CustomTypeTest
528.28 -
528.29 -package customtypes;
528.30 -
528.31 -import java.io.InvalidObjectException;
528.32 -import java.lang.reflect.Type;
528.33 -import javax.management.openmbean.MXBeanMapping;
528.34 -import javax.management.openmbean.MXBeanMappingFactory;
528.35 -import javax.management.openmbean.OpenDataException;
528.36 -import javax.management.openmbean.SimpleType;
528.37 -
528.38 -public class IntegerIsStringFactory extends MXBeanMappingFactory {
528.39 - @Override
528.40 - public MXBeanMapping mappingForType(Type t, MXBeanMappingFactory f)
528.41 - throws OpenDataException {
528.42 - if (t == Integer.class)
528.43 - return integerIsStringMapping;
528.44 - else
528.45 - return MXBeanMappingFactory.DEFAULT.mappingForType(t, f);
528.46 - }
528.47 -
528.48 - private static final MXBeanMapping integerIsStringMapping =
528.49 - new IntegerIsStringMapping();
528.50 -
528.51 - private static class IntegerIsStringMapping extends MXBeanMapping {
528.52 - IntegerIsStringMapping() {
528.53 - super(Integer.class, SimpleType.STRING);
528.54 - }
528.55 -
528.56 - public Object fromOpenValue(Object openValue)
528.57 - throws InvalidObjectException {
528.58 - try {
528.59 - String s = (String) openValue;
528.60 - return Integer.parseInt(s);
528.61 - } catch (Exception e) {
528.62 - InvalidObjectException ioe = new InvalidObjectException("oops");
528.63 - ioe.initCause(e);
528.64 - throw ioe;
528.65 - }
528.66 - }
528.67 -
528.68 - public Object toOpenValue(Object javaValue) throws OpenDataException {
528.69 - try {
528.70 - Integer i = (Integer) javaValue;
528.71 - return i.toString();
528.72 - } catch (Exception e) {
528.73 - OpenDataException ode = new OpenDataException("oops");
528.74 - ode.initCause(e);
528.75 - throw ode;
528.76 - }
528.77 - }
528.78 - }
528.79 -}
529.1 --- a/test/javax/management/mxbean/customtypes/package-info.java Mon Nov 23 10:04:47 2009 +0000
529.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
529.3 @@ -1,27 +0,0 @@
529.4 -/*
529.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
529.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
529.7 - *
529.8 - * This code is free software; you can redistribute it and/or modify it
529.9 - * under the terms of the GNU General Public License version 2 only, as
529.10 - * published by the Free Software Foundation.
529.11 - *
529.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
529.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
529.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
529.15 - * version 2 for more details (a copy is included in the LICENSE file that
529.16 - * accompanied this code).
529.17 - *
529.18 - * You should have received a copy of the GNU General Public License version
529.19 - * 2 along with this work; if not, write to the Free Software Foundation,
529.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
529.21 - *
529.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
529.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
529.24 - * have any questions.
529.25 - */
529.26 -
529.27 -// package-info.java - test package annotations for custom types
529.28 -
529.29 -@javax.management.openmbean.MXBeanMappingFactoryClass(IntegerIsStringFactory.class)
529.30 -package customtypes;
530.1 --- a/test/javax/management/namespace/DomainCreationTest.java Mon Nov 23 10:04:47 2009 +0000
530.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
530.3 @@ -1,330 +0,0 @@
530.4 -/*
530.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
530.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
530.7 - *
530.8 - * This code is free software; you can redistribute it and/or modify it
530.9 - * under the terms of the GNU General Public License version 2 only, as
530.10 - * published by the Free Software Foundation.
530.11 - *
530.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
530.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
530.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
530.15 - * version 2 for more details (a copy is included in the LICENSE file that
530.16 - * accompanied this code).
530.17 - *
530.18 - * You should have received a copy of the GNU General Public License version
530.19 - * 2 along with this work; if not, write to the Free Software Foundation,
530.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
530.21 - *
530.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
530.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
530.24 - * have any questions.
530.25 - */
530.26 -/*
530.27 - *
530.28 - * @test DomainCreationTest.java
530.29 - * @bug 5072476
530.30 - * @summary Test the creation and registration of JMXDomain instances.
530.31 - * @author Daniel Fuchs
530.32 - * @run clean DomainCreationTest Wombat WombatMBean
530.33 - * @run build DomainCreationTest Wombat WombatMBean
530.34 - * @run main DomainCreationTest
530.35 - */
530.36 -
530.37 -
530.38 -import java.util.Collections;
530.39 -import java.util.Map;
530.40 -import java.util.Set;
530.41 -import javax.management.Attribute;
530.42 -import javax.management.AttributeList;
530.43 -import javax.management.AttributeNotFoundException;
530.44 -import javax.management.DynamicMBean;
530.45 -import javax.management.InstanceNotFoundException;
530.46 -import javax.management.InvalidAttributeValueException;
530.47 -import javax.management.MBeanException;
530.48 -import javax.management.MBeanInfo;
530.49 -import javax.management.MBeanRegistration;
530.50 -import javax.management.MBeanServer;
530.51 -import javax.management.MBeanServerFactory;
530.52 -import javax.management.NotificationEmitter;
530.53 -import javax.management.ObjectInstance;
530.54 -import javax.management.ObjectName;
530.55 -import javax.management.ReflectionException;
530.56 -import javax.management.RuntimeMBeanException;
530.57 -import javax.management.RuntimeOperationsException;
530.58 -import javax.management.namespace.JMXDomain;
530.59 -import javax.management.namespace.MBeanServerSupport;
530.60 -
530.61 -/**
530.62 - * Test simple creation/registration of namespace.
530.63 - *
530.64 - */
530.65 -public class DomainCreationTest {
530.66 - private static Map<String,Object> emptyEnvMap() {
530.67 - return Collections.emptyMap();
530.68 - }
530.69 -
530.70 -
530.71 - public static class LocalDomainRepository
530.72 - extends MBeanServerSupport {
530.73 - private final MBeanServer server;
530.74 - private final String domain;
530.75 -
530.76 -
530.77 - public class DynamicMBeanProxy implements DynamicMBean {
530.78 -
530.79 - private final MBeanServer server;
530.80 - private final ObjectName name;
530.81 -
530.82 - public DynamicMBeanProxy(MBeanServer s, ObjectName n) {
530.83 - this.server = s;
530.84 - this.name = n;
530.85 - }
530.86 -
530.87 - public Object getAttribute(String attribute)
530.88 - throws AttributeNotFoundException,
530.89 - MBeanException, ReflectionException {
530.90 - try {
530.91 - return server.getAttribute(name, attribute);
530.92 - } catch (RuntimeException x) {
530.93 - throw x;
530.94 - } catch (Exception x) {
530.95 - throw new RuntimeException(x);
530.96 - }
530.97 - }
530.98 -
530.99 - public void setAttribute(Attribute attribute)
530.100 - throws AttributeNotFoundException,
530.101 - InvalidAttributeValueException, MBeanException,
530.102 - ReflectionException {
530.103 - try {
530.104 - server.setAttribute(name, attribute);
530.105 - } catch (RuntimeException x) {
530.106 - throw x;
530.107 - } catch (Exception x) {
530.108 - throw new RuntimeException(x);
530.109 - }
530.110 - }
530.111 -
530.112 - public AttributeList getAttributes(String[] attributes) {
530.113 - try {
530.114 - return server.getAttributes(name, attributes);
530.115 - } catch (RuntimeException x) {
530.116 - throw x;
530.117 - } catch (Exception x) {
530.118 - throw new RuntimeException(x);
530.119 - }
530.120 - }
530.121 -
530.122 - public AttributeList setAttributes(AttributeList attributes) {
530.123 - try {
530.124 - return server.setAttributes(name, attributes);
530.125 - } catch (RuntimeException x) {
530.126 - throw x;
530.127 - } catch (Exception x) {
530.128 - throw new RuntimeException(x);
530.129 - }
530.130 - }
530.131 -
530.132 - public Object invoke(String actionName, Object[] params,
530.133 - String[] signature) throws MBeanException,
530.134 - ReflectionException {
530.135 - try {
530.136 - return server.invoke(name, actionName, params, signature);
530.137 - } catch (RuntimeException x) {
530.138 - throw x;
530.139 - } catch (Exception x) {
530.140 - throw new RuntimeException(x);
530.141 - }
530.142 - }
530.143 -
530.144 - public MBeanInfo getMBeanInfo() {
530.145 - try {
530.146 - return server.getMBeanInfo(name);
530.147 - } catch (RuntimeException x) {
530.148 - throw x;
530.149 - } catch (Exception x) {
530.150 - throw new RuntimeException(x);
530.151 - }
530.152 - }
530.153 - }
530.154 -
530.155 - public LocalDomainRepository(String domain) {
530.156 - this.server = MBeanServerFactory.newMBeanServer();
530.157 - this.domain = domain;
530.158 - }
530.159 -
530.160 - @Override
530.161 - protected Set<ObjectName> getNames() {
530.162 - try {
530.163 - final ObjectName name =
530.164 - ObjectName.getInstance(domain+":*");
530.165 - return server.queryNames(name, null);
530.166 - } catch (RuntimeException x) {
530.167 - throw x;
530.168 - } catch (Exception x) {
530.169 - throw new RuntimeException(x);
530.170 - }
530.171 - }
530.172 -
530.173 - @Override
530.174 - public DynamicMBean getDynamicMBeanFor(ObjectName name)
530.175 - throws InstanceNotFoundException {
530.176 - return new DynamicMBeanProxy(server, name);
530.177 - }
530.178 -
530.179 - @Override
530.180 - public NotificationEmitter
530.181 - getNotificationEmitterFor(ObjectName name)
530.182 - throws InstanceNotFoundException {
530.183 - DynamicMBean mbean = getDynamicMBeanFor(name);
530.184 - if (mbean instanceof NotificationEmitter)
530.185 - return (NotificationEmitter) mbean;
530.186 - return null;
530.187 - }
530.188 -
530.189 - }
530.190 -
530.191 - private static MBeanServer newMBeanServer() {
530.192 - return MBeanServerFactory.newMBeanServer();
530.193 - }
530.194 -
530.195 - public static interface ThingMBean {}
530.196 - public static class Thing implements ThingMBean, MBeanRegistration {
530.197 - public ObjectName preRegister(MBeanServer server, ObjectName name)
530.198 - throws Exception {
530.199 - if (name == null) return new ObjectName(":type=Thing");
530.200 - else return name;
530.201 - }
530.202 - public void postRegister(Boolean registrationDone) {
530.203 - }
530.204 -
530.205 - public void preDeregister() throws Exception {
530.206 - }
530.207 - public void postDeregister() {
530.208 - }
530.209 - }
530.210 -
530.211 - /**
530.212 - * Test that it is possible to create a dummy MBean with a null
530.213 - * ObjectName - this is just a sanity check - as there are already
530.214 - * other JMX tests that check that.
530.215 - *
530.216 - * @throws java.lang.Exception
530.217 - */
530.218 - public static void testCreateWithNull() throws Exception {
530.219 - final MBeanServer server = newMBeanServer();
530.220 - final ObjectInstance oi = server.registerMBean(new Thing(),null);
530.221 - server.unregisterMBean(oi.getObjectName());
530.222 - System.out.println("testCreateWithNull PASSED");
530.223 - }
530.224 -
530.225 - /**
530.226 - * Check that we can register a JMXNamespace MBean, using its standard
530.227 - * ObjectName.
530.228 - * @throws java.lang.Exception
530.229 - */
530.230 - public static void testGoodObjectName() throws Exception {
530.231 - MBeanServer server = newMBeanServer();
530.232 - final ObjectName name =
530.233 - JMXDomain.getDomainObjectName("gloups");
530.234 - final ObjectInstance oi =
530.235 - server.registerMBean(new JMXDomain(
530.236 - new LocalDomainRepository("gloups")),name);
530.237 - System.out.println("Succesfully registered namespace: "+name);
530.238 - try {
530.239 - if (! name.equals(oi.getObjectName()))
530.240 - throw new RuntimeException("testGoodObjectName: TEST failed: " +
530.241 - "namespace registered as: "+
530.242 - oi.getObjectName()+" expected: "+name);
530.243 - } finally {
530.244 - server.unregisterMBean(oi.getObjectName());
530.245 - }
530.246 - System.out.println("Succesfully unregistered namespace: "+name);
530.247 - System.out.println("testGoodObjectName PASSED");
530.248 - }
530.249 -
530.250 - /**
530.251 - * Check that we cannot register a JMXNamespace MBean, if we don't use
530.252 - * its standard ObjectName.
530.253 - * @throws java.lang.Exception
530.254 - */
530.255 - public static void testBadObjectName() throws Exception {
530.256 - MBeanServer server = newMBeanServer();
530.257 - Throwable exp = null;
530.258 - final ObjectName name = new ObjectName("d:k=v");
530.259 - try {
530.260 - server.registerMBean(new JMXDomain(
530.261 - new LocalDomainRepository("d")),name);
530.262 - System.out.println("testBadObjectName: " +
530.263 - "Error: MBean registered, no exception thrown.");
530.264 - } catch(RuntimeMBeanException x) {
530.265 - exp = x.getCause();
530.266 - } catch(Exception x) {
530.267 - throw new RuntimeException("testBadObjectName: TEST failed: " +
530.268 - "expected RuntimeMBeanException - got "+
530.269 - x);
530.270 - }
530.271 - if (exp == null) server.unregisterMBean(name);
530.272 - if (exp == null)
530.273 - throw new RuntimeException("testBadObjectName: TEST failed: " +
530.274 - "expected IllegalArgumentException - got none");
530.275 - if (!(exp instanceof IllegalArgumentException))
530.276 - throw new RuntimeException("testBadObjectName: TEST failed: " +
530.277 - "expected IllegalArgumentException - got "+
530.278 - exp.toString(),exp);
530.279 - System.out.println("Got expected exception: "+exp);
530.280 - System.out.println("testBadObjectName PASSED");
530.281 - }
530.282 -
530.283 - /**
530.284 - * Check that we cannot register a Domain MBean in a domain that already
530.285 - * exists.
530.286 - *
530.287 - * @throws java.lang.Exception
530.288 - */
530.289 - public static void testBadDomain() throws Exception {
530.290 - MBeanServer server = newMBeanServer();
530.291 - Throwable exp = null;
530.292 - final ObjectName name = new ObjectName("glips:k=v");
530.293 - server.registerMBean(new Wombat(),name);
530.294 -
530.295 - final ObjectName dname =
530.296 - JMXDomain.getDomainObjectName("glips");
530.297 -
530.298 - try {
530.299 - server.registerMBean(new JMXDomain(
530.300 - new LocalDomainRepository("glips")),dname);
530.301 - System.out.println("testBadDomain: " +
530.302 - "Error: MBean registered, no exception thrown.");
530.303 - } catch(RuntimeOperationsException x) {
530.304 - exp = x.getCause();
530.305 - } catch(Exception x) {
530.306 - throw new RuntimeException("testBadDomain: TEST failed: " +
530.307 - "expected RuntimeOperationsException - got "+
530.308 - x);
530.309 - } finally {
530.310 - server.unregisterMBean(name);
530.311 - }
530.312 - if (exp == null) {
530.313 - server.unregisterMBean(dname);
530.314 - }
530.315 - if (exp == null)
530.316 - throw new RuntimeException("testBadDomain: TEST failed: " +
530.317 - "expected IllegalArgumentException - got none");
530.318 - if (!(exp instanceof IllegalArgumentException))
530.319 - throw new RuntimeException("testBadDomain: TEST failed: " +
530.320 - "expected IllegalArgumentException - got "+
530.321 - exp.toString(),exp);
530.322 - System.out.println("Got expected exception: "+exp);
530.323 - System.out.println("testBadDomain PASSED");
530.324 - }
530.325 -
530.326 -
530.327 - public static void main(String... args) throws Exception {
530.328 - testCreateWithNull();
530.329 - testGoodObjectName();
530.330 - testBadObjectName();
530.331 - testBadDomain();
530.332 - }
530.333 -}
531.1 --- a/test/javax/management/namespace/EventWithNamespaceControlTest.java Mon Nov 23 10:04:47 2009 +0000
531.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
531.3 @@ -1,94 +0,0 @@
531.4 -/*
531.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
531.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
531.7 - *
531.8 - * This code is free software; you can redistribute it and/or modify it
531.9 - * under the terms of the GNU General Public License version 2 only, as
531.10 - * published by the Free Software Foundation.
531.11 - *
531.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
531.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
531.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
531.15 - * version 2 for more details (a copy is included in the LICENSE file that
531.16 - * accompanied this code).
531.17 - *
531.18 - * You should have received a copy of the GNU General Public License version
531.19 - * 2 along with this work; if not, write to the Free Software Foundation,
531.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
531.21 - *
531.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
531.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
531.24 - * have any questions.
531.25 - */
531.26 -
531.27 -/*
531.28 - *
531.29 - * @test EventWithNamespaceControlTest.java
531.30 - * @summary Check -Djmx.remote.use.event.service=true and
531.31 - * -Djmx.remote.delegate.event.service
531.32 - * @author Daniel Fuchs
531.33 - * @bug 5072476 5108776
531.34 - * @run clean EventWithNamespaceTest EventWithNamespaceControlTest
531.35 - * Wombat WombatMBean JMXRemoteTargetNamespace
531.36 - * NamespaceController NamespaceControllerMBean
531.37 - * @compile -XDignore.symbol.file=true EventWithNamespaceTest.java
531.38 - EventWithNamespaceControlTest.java
531.39 - * Wombat.java WombatMBean.java JMXRemoteTargetNamespace.java
531.40 - * NamespaceController.java NamespaceControllerMBean.java
531.41 - * @run main/othervm -Djmx.remote.use.event.service=true EventWithNamespaceControlTest
531.42 - * @run main/othervm EventWithNamespaceControlTest
531.43 - * @run main/othervm -Djmx.remote.delegate.event.service=false EventWithNamespaceControlTest java.lang.UnsupportedOperationException
531.44 - */
531.45 -
531.46 -import java.util.Collections;
531.47 -import java.util.Map;
531.48 -import java.util.logging.Logger;
531.49 -import javax.management.RuntimeOperationsException;
531.50 -
531.51 -/**
531.52 - *
531.53 - * @author Sun Microsystems, Inc.
531.54 - */
531.55 -public class EventWithNamespaceControlTest extends EventWithNamespaceTest {
531.56 -
531.57 - /**
531.58 - * A logger for this class.
531.59 - **/
531.60 - private static final Logger LOG =
531.61 - Logger.getLogger(EventWithNamespaceControlTest.class.getName());
531.62 -
531.63 - /** Creates a new instance of EventWithNamespaceTest */
531.64 - public EventWithNamespaceControlTest() {
531.65 - }
531.66 -
531.67 -
531.68 -
531.69 - public static void main(String[] args) {
531.70 - final EventWithNamespaceControlTest test =
531.71 - new EventWithNamespaceControlTest();
531.72 - if (args.length == 0) {
531.73 - test.run(args);
531.74 - System.out.println("Test successfully passed");
531.75 - } else {
531.76 - try {
531.77 - test.run(args);
531.78 - throw new RuntimeException("Test should have failed.");
531.79 - } catch (RuntimeOperationsException x) {
531.80 - if (! args[0].equals(x.getCause().getClass().getName())) {
531.81 - System.err.println("Unexpected wrapped exception: "+
531.82 - x.getCause());
531.83 - throw x;
531.84 - } else {
531.85 - System.out.println("Got expected exception: "+x.getCause());
531.86 - }
531.87 - }
531.88 - }
531.89 - }
531.90 -
531.91 - @Override
531.92 - public Map<String, ?> getServerMap() {
531.93 - Map<String, ?> retValue = Collections.emptyMap();
531.94 - return retValue;
531.95 - }
531.96 -
531.97 -}
532.1 --- a/test/javax/management/namespace/EventWithNamespaceTest.java Mon Nov 23 10:04:47 2009 +0000
532.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
532.3 @@ -1,241 +0,0 @@
532.4 -/*
532.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
532.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
532.7 - *
532.8 - * This code is free software; you can redistribute it and/or modify it
532.9 - * under the terms of the GNU General Public License version 2 only, as
532.10 - * published by the Free Software Foundation.
532.11 - *
532.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
532.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
532.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
532.15 - * version 2 for more details (a copy is included in the LICENSE file that
532.16 - * accompanied this code).
532.17 - *
532.18 - * You should have received a copy of the GNU General Public License version
532.19 - * 2 along with this work; if not, write to the Free Software Foundation,
532.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
532.21 - *
532.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
532.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
532.24 - * have any questions.
532.25 - */
532.26 -
532.27 -/*
532.28 - *
532.29 - * @test EventWithNamespaceTest.java 1.8
532.30 - * @bug 6539857 5072476 5108776
532.31 - * @summary General Namespace & Notifications test.
532.32 - * @author Daniel Fuchs
532.33 - * @run clean EventWithNamespaceTest Wombat WombatMBean
532.34 - * JMXRemoteTargetNamespace
532.35 - * NamespaceController NamespaceControllerMBean
532.36 - * @compile -XDignore.symbol.file=true EventWithNamespaceTest.java
532.37 - * Wombat.java WombatMBean.java JMXRemoteTargetNamespace.java
532.38 - * NamespaceController.java NamespaceControllerMBean.java
532.39 - * @run main EventWithNamespaceTest
532.40 - */
532.41 -
532.42 -import java.lang.management.ManagementFactory;
532.43 -import java.util.HashMap;
532.44 -import java.util.Map;
532.45 -import java.util.logging.Logger;
532.46 -
532.47 -import javax.management.JMX;
532.48 -import javax.management.MBeanServer;
532.49 -import javax.management.MBeanServerConnection;
532.50 -import javax.management.MBeanServerFactory;
532.51 -import javax.management.Notification;
532.52 -import javax.management.NotificationEmitter;
532.53 -import javax.management.NotificationListener;
532.54 -import javax.management.ObjectInstance;
532.55 -import javax.management.ObjectName;
532.56 -import javax.management.namespace.JMXNamespaces;
532.57 -import javax.management.remote.JMXConnector;
532.58 -import javax.management.remote.JMXConnectorFactory;
532.59 -import javax.management.remote.JMXConnectorServer;
532.60 -import javax.management.remote.JMXConnectorServerFactory;
532.61 -import javax.management.remote.JMXServiceURL;
532.62 -
532.63 -/**
532.64 - *
532.65 - * @author Sun Microsystems, Inc.
532.66 - */
532.67 -public class EventWithNamespaceTest {
532.68 -
532.69 - /**
532.70 - * A logger for this class.
532.71 - **/
532.72 - private static final Logger LOG =
532.73 - Logger.getLogger(EventWithNamespaceTest.class.getName());
532.74 -
532.75 - /** Creates a new instance of EventWithNamespaceTest */
532.76 - public EventWithNamespaceTest() {
532.77 - }
532.78 -
532.79 - private static Map<String,?> singletonMap(String key, Object value) {
532.80 - final Map<String,Object> map = new HashMap<String,Object>();
532.81 - map.put(key,value);
532.82 - return map;
532.83 - }
532.84 -
532.85 - public Map<String,?> getServerMap() {
532.86 - return singletonMap(JMXConnectorServer.DELEGATE_TO_EVENT_SERVICE,"true");
532.87 - }
532.88 -
532.89 - public JMXServiceURL export(MBeanServer server)
532.90 - throws Exception {
532.91 - final JMXServiceURL in = new JMXServiceURL("rmi",null,0);
532.92 - final Map<String,?> env = getServerMap();
532.93 -
532.94 - final JMXConnectorServer cs =
532.95 - JMXConnectorServerFactory.newJMXConnectorServer(in,env,null);
532.96 - final ObjectName csname = ObjectName.
532.97 - getInstance(cs.getClass().getPackage().getName()+
532.98 - ":type="+cs.getClass().getSimpleName());
532.99 - server.registerMBean(cs,csname);
532.100 - cs.start();
532.101 - return cs.getAddress();
532.102 - }
532.103 -
532.104 - public static class Counter {
532.105 - int count;
532.106 - public synchronized int count() {
532.107 - count++;
532.108 - notifyAll();
532.109 - return count;
532.110 - }
532.111 - public synchronized int peek() {
532.112 - return count;
532.113 - }
532.114 - public synchronized int waitfor(int max, long timeout)
532.115 - throws InterruptedException {
532.116 - final long start = System.currentTimeMillis();
532.117 - while (count < max && timeout > 0) {
532.118 - final long rest = timeout -
532.119 - (System.currentTimeMillis() - start);
532.120 - if (rest <= 0) break;
532.121 - wait(rest);
532.122 - }
532.123 - return count;
532.124 - }
532.125 - }
532.126 -
532.127 - public static class CounterListener
532.128 - implements NotificationListener {
532.129 - final private Counter counter;
532.130 - public CounterListener(Counter counter) {
532.131 - this.counter = counter;
532.132 - }
532.133 - public void handleNotification(Notification notification,
532.134 - Object handback) {
532.135 - System.out.println("Received notif from " + handback +
532.136 - ":\n\t" + notification);
532.137 - if (!notification.getSource().equals(handback)) {
532.138 - System.err.println("OhOh... Unexpected source: \n\t"+
532.139 - notification.getSource()+"\n\twas expecting:\n\t"+
532.140 - handback);
532.141 - }
532.142 - counter.count();
532.143 - }
532.144 - }
532.145 -
532.146 - public void simpleTest(String[] args) {
532.147 - try {
532.148 - final MBeanServer server1 =
532.149 - ManagementFactory.getPlatformMBeanServer();
532.150 - final JMXServiceURL url1 = export(server1);
532.151 -
532.152 - final MBeanServer server2 =
532.153 - MBeanServerFactory.createMBeanServer("server2");
532.154 - final JMXServiceURL url2 = export(server2);
532.155 -
532.156 - final MBeanServer server3 =
532.157 - MBeanServerFactory.createMBeanServer("server3");
532.158 - final JMXServiceURL url3 = export(server3);
532.159 -
532.160 - final ObjectInstance ncinst =
532.161 - NamespaceController.createInstance(server1);
532.162 -
532.163 - final NamespaceControllerMBean nc =
532.164 - JMX.newMBeanProxy(server1,ncinst.getObjectName(),
532.165 - NamespaceControllerMBean.class);
532.166 -
532.167 - final String mount2 = nc.mount(url2,"server2",null);
532.168 - final String mount3 = nc.mount(url3,"server2//server3",
532.169 - null);
532.170 -
532.171 - final ObjectName deep =
532.172 - new ObjectName("server2//server3//bush:type=Wombat,name=kanga");
532.173 - server1.createMBean(Wombat.class.getName(),deep);
532.174 -
532.175 - System.err.println("There's a wombat in the bush!");
532.176 -
532.177 - final Counter counter = new Counter();
532.178 -
532.179 - final NotificationListener listener =
532.180 - new CounterListener(counter);
532.181 -
532.182 - final JMXConnector jc = JMXConnectorFactory.connect(url1);
532.183 - final MBeanServerConnection conn1 =
532.184 - jc.getMBeanServerConnection();
532.185 - final ObjectName shallow =
532.186 - new ObjectName("bush:"+
532.187 - deep.getKeyPropertyListString());
532.188 - final MBeanServerConnection conn2 =
532.189 - JMXNamespaces.narrowToNamespace(conn1,"server2//server3");
532.190 -
532.191 - final WombatMBean proxy1 =
532.192 - JMX.newMBeanProxy(conn1,deep,WombatMBean.class,true);
532.193 - final WombatMBean proxy2 =
532.194 - JMX.newMBeanProxy(conn2,shallow,WombatMBean.class,true);
532.195 -
532.196 -
532.197 - System.err.println("Adding first Notification Listener");
532.198 - conn1.addNotificationListener(deep,listener,null,deep);
532.199 - System.err.println("Adding second Notification Listener");
532.200 - ((NotificationEmitter)proxy2).
532.201 - addNotificationListener(listener,null,shallow);
532.202 - final JMXConnector c3 = JMXConnectorFactory.connect(url3,
532.203 - singletonMap(JMXConnector.USE_EVENT_SERVICE,"false"));
532.204 - System.err.println("Adding third Notification Listener");
532.205 - c3.getMBeanServerConnection().
532.206 - addNotificationListener(shallow,listener,null,shallow);
532.207 - System.err.println("Set attribute to trigger notif");
532.208 - proxy1.setCaption("I am a new Wombat!");
532.209 - System.err.println("Get attribute");
532.210 - System.err.println("New caption: "+proxy2.getCaption());
532.211 - System.err.println("Wait for Notifs...");
532.212 - final int rcvcount = counter.waitfor(3,3000);
532.213 - if (rcvcount != 3)
532.214 - throw new RuntimeException("simpleTest failed: "+
532.215 - "received count is " +rcvcount);
532.216 - System.err.println("simpleTest: got expected "+rcvcount+
532.217 - " notifs");
532.218 -
532.219 - System.err.println("removing all listeners");
532.220 - conn1.removeNotificationListener(deep,listener,null,deep);
532.221 - ((NotificationEmitter)proxy2)
532.222 - .removeNotificationListener(listener,null,shallow);
532.223 - c3.getMBeanServerConnection().
532.224 - removeNotificationListener(shallow,listener,null,shallow);
532.225 -
532.226 - System.err.println("simpleTest passed: got "+rcvcount+
532.227 - " notifs");
532.228 -
532.229 - } catch (RuntimeException x) {
532.230 - throw x;
532.231 - } catch (Exception x) {
532.232 - throw new RuntimeException("simpleTest failed: " + x,x);
532.233 - }
532.234 - }
532.235 -
532.236 - public void run(String[] args) {
532.237 - simpleTest(args);
532.238 - }
532.239 -
532.240 - public static void main(String[] args) {
532.241 - new EventWithNamespaceTest().run(args);
532.242 - }
532.243 -
532.244 -}
533.1 --- a/test/javax/management/namespace/ExportNamespaceTest.java Mon Nov 23 10:04:47 2009 +0000
533.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
533.3 @@ -1,100 +0,0 @@
533.4 -/*
533.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
533.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
533.7 - *
533.8 - * This code is free software; you can redistribute it and/or modify it
533.9 - * under the terms of the GNU General Public License version 2 only, as
533.10 - * published by the Free Software Foundation.
533.11 - *
533.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
533.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
533.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
533.15 - * version 2 for more details (a copy is included in the LICENSE file that
533.16 - * accompanied this code).
533.17 - *
533.18 - * You should have received a copy of the GNU General Public License version
533.19 - * 2 along with this work; if not, write to the Free Software Foundation,
533.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
533.21 - *
533.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
533.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
533.24 - * have any questions.
533.25 - */
533.26 -/*
533.27 - *
533.28 - * @test ExportNamespaceTest.java
533.29 - * @summary Test that you can export a single namespace through a
533.30 - * JMXConnectorServer.
533.31 - * @author Daniel Fuchs
533.32 - * @bug 5072476
533.33 - * @run clean ExportNamespaceTest Wombat WombatMBean
533.34 - * @run build ExportNamespaceTest Wombat WombatMBean
533.35 - * @run main ExportNamespaceTest
533.36 - */
533.37 -
533.38 -import javax.management.JMX;
533.39 -import javax.management.ObjectName;
533.40 -import javax.management.namespace.JMXNamespace;
533.41 -import javax.management.namespace.JMXNamespaces;
533.42 -import javax.management.MBeanServer;
533.43 -import javax.management.MBeanServerConnection;
533.44 -import javax.management.MBeanServerFactory;
533.45 -import javax.management.remote.JMXConnector;
533.46 -import javax.management.remote.JMXConnectorFactory;
533.47 -import javax.management.remote.JMXConnectorServer;
533.48 -import javax.management.remote.JMXConnectorServerFactory;
533.49 -import javax.management.remote.JMXServiceURL;
533.50 -
533.51 -
533.52 -/**
533.53 - * Test simple creation/registration of namespace.
533.54 - *
533.55 - */
533.56 -public class ExportNamespaceTest {
533.57 -
533.58 - public static void testExport() throws Exception {
533.59 - final JMXNamespace my =
533.60 - new JMXNamespace(MBeanServerFactory.newMBeanServer());
533.61 - final MBeanServer s = MBeanServerFactory.newMBeanServer();
533.62 - final ObjectName myname = JMXNamespaces.getNamespaceObjectName("my");
533.63 - final ObjectName wname = ObjectName.getInstance("backyard:type=Wombat");
533.64 - my.getSourceServer().registerMBean(new Wombat(),wname);
533.65 - s.registerMBean(my,myname);
533.66 -
533.67 - if (!s.queryNames(new ObjectName("my//b*:*"),null).contains(
533.68 - JMXNamespaces.insertPath("my", wname))) {
533.69 - throw new RuntimeException("1: Wombat not found: "+wname);
533.70 - }
533.71 -
533.72 - final MBeanServer cd = JMXNamespaces.narrowToNamespace(s, "my");
533.73 - if (!cd.queryNames(new ObjectName("b*:*"),null).contains(wname)) {
533.74 - throw new RuntimeException("2: Wombat not found: "+wname);
533.75 - }
533.76 -
533.77 - final JMXServiceURL url = new JMXServiceURL("rmi",null,0);
533.78 - final JMXConnectorServer server =
533.79 - JMXConnectorServerFactory.newJMXConnectorServer(url, null, cd);
533.80 - server.start();
533.81 -
533.82 - final JMXConnector jc = JMXConnectorFactory.
533.83 - connect(server.getAddress(),null);
533.84 - final MBeanServerConnection mbsc = jc.getMBeanServerConnection();
533.85 -
533.86 - if (!mbsc.queryNames(new ObjectName("b*:*"),null).contains(wname)) {
533.87 - throw new RuntimeException("3: Wombat not found: "+wname);
533.88 - }
533.89 - System.out.println("Found a Wombat in my backyard.");
533.90 -
533.91 - final String deepThoughts = "I want to leave this backyard!";
533.92 - final WombatMBean w = JMX.newMBeanProxy(mbsc, wname, WombatMBean.class);
533.93 - w.setCaption(deepThoughts);
533.94 - if (!deepThoughts.equals(w.getCaption()))
533.95 - throw new RuntimeException("4: Wombat is not thinking right: "+
533.96 - w.getCaption());
533.97 -
533.98 - }
533.99 -
533.100 - public static void main(String... args) throws Exception {
533.101 - testExport();
533.102 - }
533.103 -}
534.1 --- a/test/javax/management/namespace/JMXDomainTest.java Mon Nov 23 10:04:47 2009 +0000
534.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
534.3 @@ -1,513 +0,0 @@
534.4 -/*
534.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
534.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
534.7 - *
534.8 - * This code is free software; you can redistribute it and/or modify it
534.9 - * under the terms of the GNU General Public License version 2 only, as
534.10 - * published by the Free Software Foundation.
534.11 - *
534.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
534.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
534.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
534.15 - * version 2 for more details (a copy is included in the LICENSE file that
534.16 - * accompanied this code).
534.17 - *
534.18 - * You should have received a copy of the GNU General Public License version
534.19 - * 2 along with this work; if not, write to the Free Software Foundation,
534.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
534.21 - *
534.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
534.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
534.24 - * have any questions.
534.25 - */
534.26 -/*
534.27 - *
534.28 - * @test JMXDomainTest.java
534.29 - * @bug 5072476
534.30 - * @summary Basic test for JMXDomain.
534.31 - * @author Daniel Fuchs
534.32 - * @run clean JMXDomainTest Wombat WombatMBean
534.33 - * @run build JMXDomainTest Wombat WombatMBean
534.34 - * @run main JMXDomainTest
534.35 - */
534.36 -
534.37 -
534.38 -import java.util.Collections;
534.39 -import java.util.concurrent.ArrayBlockingQueue;
534.40 -import java.util.concurrent.BlockingQueue;
534.41 -import java.util.concurrent.TimeUnit;
534.42 -import java.util.Map;
534.43 -import java.util.Set;
534.44 -import javax.management.Attribute;
534.45 -import javax.management.AttributeList;
534.46 -import javax.management.AttributeNotFoundException;
534.47 -import javax.management.DynamicMBean;
534.48 -import javax.management.InstanceAlreadyExistsException;
534.49 -import javax.management.InstanceNotFoundException;
534.50 -import javax.management.InvalidAttributeValueException;
534.51 -import javax.management.ListenerNotFoundException;
534.52 -import javax.management.MBeanException;
534.53 -import javax.management.MBeanInfo;
534.54 -import javax.management.MBeanNotificationInfo;
534.55 -import javax.management.MBeanRegistration;
534.56 -import javax.management.MBeanRegistrationException;
534.57 -import javax.management.MBeanServer;
534.58 -import javax.management.MBeanServerDelegate;
534.59 -import javax.management.MBeanServerFactory;
534.60 -import javax.management.MBeanServerNotification;
534.61 -import javax.management.NotCompliantMBeanException;
534.62 -import javax.management.Notification;
534.63 -import javax.management.NotificationBroadcaster;
534.64 -import javax.management.NotificationEmitter;
534.65 -import javax.management.NotificationFilter;
534.66 -import javax.management.NotificationListener;
534.67 -import javax.management.ObjectInstance;
534.68 -import javax.management.ObjectName;
534.69 -import javax.management.ReflectionException;
534.70 -import javax.management.namespace.JMXDomain;
534.71 -import javax.management.namespace.MBeanServerSupport;
534.72 -
534.73 -/**
534.74 - * Test simple creation/registration of namespace.
534.75 - *
534.76 - */
534.77 -public class JMXDomainTest {
534.78 - private static Map<String,Object> emptyEnvMap() {
534.79 - return Collections.emptyMap();
534.80 - }
534.81 -
534.82 -
534.83 - public static class LocalDomainRepository
534.84 - extends MBeanServerSupport {
534.85 - private final MBeanServer server;
534.86 - private final String domain;
534.87 -
534.88 - public class DynamicMBeanProxy implements DynamicMBean {
534.89 -
534.90 - private final MBeanServer server;
534.91 - private final ObjectName name;
534.92 -
534.93 - public DynamicMBeanProxy(MBeanServer s, ObjectName n) {
534.94 - this.server = s;
534.95 - this.name = n;
534.96 - }
534.97 -
534.98 - public Object getAttribute(String attribute)
534.99 - throws AttributeNotFoundException,
534.100 - MBeanException, ReflectionException {
534.101 - try {
534.102 - return server.getAttribute(name, attribute);
534.103 - } catch (RuntimeException x) {
534.104 - throw x;
534.105 - } catch (Exception x) {
534.106 - throw new RuntimeException(x);
534.107 - }
534.108 - }
534.109 -
534.110 - public void setAttribute(Attribute attribute)
534.111 - throws AttributeNotFoundException,
534.112 - InvalidAttributeValueException, MBeanException,
534.113 - ReflectionException {
534.114 - try {
534.115 - server.setAttribute(name, attribute);
534.116 - } catch (RuntimeException x) {
534.117 - throw x;
534.118 - } catch (Exception x) {
534.119 - throw new RuntimeException(x);
534.120 - }
534.121 - }
534.122 -
534.123 - public AttributeList getAttributes(String[] attributes) {
534.124 - try {
534.125 - return server.getAttributes(name, attributes);
534.126 - } catch (RuntimeException x) {
534.127 - throw x;
534.128 - } catch (Exception x) {
534.129 - throw new RuntimeException(x);
534.130 - }
534.131 - }
534.132 -
534.133 - public AttributeList setAttributes(AttributeList attributes) {
534.134 - try {
534.135 - return server.setAttributes(name, attributes);
534.136 - } catch (RuntimeException x) {
534.137 - throw x;
534.138 - } catch (Exception x) {
534.139 - throw new RuntimeException(x);
534.140 - }
534.141 - }
534.142 -
534.143 - public Object invoke(String actionName, Object[] params,
534.144 - String[] signature) throws MBeanException,
534.145 - ReflectionException {
534.146 - try {
534.147 - return server.invoke(name, actionName, params, signature);
534.148 - } catch (RuntimeException x) {
534.149 - throw x;
534.150 - } catch (Exception x) {
534.151 - throw new RuntimeException(x);
534.152 - }
534.153 - }
534.154 -
534.155 - public MBeanInfo getMBeanInfo() {
534.156 - try {
534.157 - return server.getMBeanInfo(name);
534.158 - } catch (RuntimeException x) {
534.159 - throw x;
534.160 - } catch (Exception x) {
534.161 - throw new RuntimeException(x);
534.162 - }
534.163 - }
534.164 - }
534.165 -
534.166 - public LocalDomainRepository(String domain) {
534.167 - this.server = MBeanServerFactory.newMBeanServer();
534.168 - this.domain = domain;
534.169 - }
534.170 -
534.171 - @Override
534.172 - protected Set<ObjectName> getNames() {
534.173 - try {
534.174 - final ObjectName name =
534.175 - ObjectName.getInstance(domain+":*");
534.176 - return server.queryNames(name, null);
534.177 - } catch (RuntimeException x) {
534.178 - throw x;
534.179 - } catch (Exception x) {
534.180 - throw new RuntimeException(x);
534.181 - }
534.182 - }
534.183 -
534.184 - @Override
534.185 - public DynamicMBean getDynamicMBeanFor(ObjectName name)
534.186 - throws InstanceNotFoundException {
534.187 - if (server.isRegistered(name))
534.188 - return new DynamicMBeanProxy(server, name);
534.189 - throw new InstanceNotFoundException(name);
534.190 - }
534.191 -
534.192 -
534.193 - @Override
534.194 - public NotificationEmitter
534.195 - getNotificationEmitterFor(final ObjectName name)
534.196 - throws InstanceNotFoundException {
534.197 - if (server.isInstanceOf(name, NotificationEmitter.class.getName())) {
534.198 - return new NotificationEmitter() {
534.199 -
534.200 - public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException {
534.201 - try {
534.202 - server.removeNotificationListener(name, listener, filter, handback);
534.203 - } catch (InstanceNotFoundException x) {
534.204 - throw new IllegalArgumentException(String.valueOf(name), x);
534.205 - }
534.206 - }
534.207 -
534.208 - public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException {
534.209 - try {
534.210 - server.addNotificationListener(name, listener, filter, handback);
534.211 - } catch (InstanceNotFoundException x) {
534.212 - throw new IllegalArgumentException(String.valueOf(name), x);
534.213 - }
534.214 - }
534.215 -
534.216 - public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
534.217 - try {
534.218 - server.removeNotificationListener(name, listener);
534.219 - } catch (InstanceNotFoundException x) {
534.220 - throw new IllegalArgumentException(String.valueOf(name), x);
534.221 - }
534.222 - }
534.223 -
534.224 - public MBeanNotificationInfo[] getNotificationInfo() {
534.225 - try {
534.226 - return server.getMBeanInfo(name).getNotifications();
534.227 - } catch (Exception x) {
534.228 - throw new IllegalArgumentException(String.valueOf(name), x);
534.229 - }
534.230 - }
534.231 - };
534.232 - }
534.233 - return null;
534.234 - }
534.235 -
534.236 - @Override
534.237 - public ObjectInstance registerMBean(Object object, ObjectName name)
534.238 - throws InstanceAlreadyExistsException,
534.239 - MBeanRegistrationException, NotCompliantMBeanException {
534.240 - return server.registerMBean(object, name);
534.241 - }
534.242 -
534.243 - @Override
534.244 - public void unregisterMBean(ObjectName name)
534.245 - throws InstanceNotFoundException,
534.246 - MBeanRegistrationException {
534.247 - server.unregisterMBean(name);
534.248 - }
534.249 -
534.250 - @Override
534.251 - public ObjectInstance createMBean(String className,
534.252 - ObjectName name, ObjectName loaderName, Object[] params,
534.253 - String[] signature, boolean useCLR)
534.254 - throws ReflectionException, InstanceAlreadyExistsException,
534.255 - MBeanRegistrationException, MBeanException,
534.256 - NotCompliantMBeanException, InstanceNotFoundException {
534.257 - if (useCLR && loaderName == null) {
534.258 - return server.createMBean(className, name, params, signature);
534.259 - }
534.260 - return server.createMBean(className, name, loaderName,
534.261 - params, signature);
534.262 - }
534.263 -
534.264 -
534.265 - }
534.266 -
534.267 - private static MBeanServer newMBeanServer() {
534.268 - return MBeanServerFactory.newMBeanServer();
534.269 - }
534.270 -
534.271 - public static interface ThingMBean {}
534.272 - public static class Thing implements ThingMBean, MBeanRegistration {
534.273 - public ObjectName preRegister(MBeanServer server, ObjectName name)
534.274 - throws Exception {
534.275 - if (name == null) return new ObjectName(":type=Thing");
534.276 - else return name;
534.277 - }
534.278 - public void postRegister(Boolean registrationDone) {
534.279 - }
534.280 -
534.281 - public void preDeregister() throws Exception {
534.282 - }
534.283 - public void postDeregister() {
534.284 - }
534.285 - }
534.286 -
534.287 - /**
534.288 - * Test that it is possible to create a dummy MBean with a null
534.289 - * ObjectName - this is just a sanity check - as there are already
534.290 - * other JMX tests that check that.
534.291 - *
534.292 - * @throws java.lang.Exception
534.293 - */
534.294 - public static void testCreateWithNull() throws Exception {
534.295 - final MBeanServer server = newMBeanServer();
534.296 - final ObjectInstance oi = server.registerMBean(new Thing(),null);
534.297 - server.unregisterMBean(oi.getObjectName());
534.298 - System.out.println("testCreateWithNull PASSED");
534.299 - }
534.300 -
534.301 - public static void testRegisterSimple() throws Exception {
534.302 - final ObjectName name =
534.303 - JMXDomain.getDomainObjectName("gloups");
534.304 - final JMXDomain jmxDomain = new JMXDomain(
534.305 - MBeanServerFactory.newMBeanServer());
534.306 - testRegister("testRegisterSimple: ",name,jmxDomain);
534.307 - }
534.308 -
534.309 - public static void testRegisterPseudoVirtual()
534.310 - throws Exception {
534.311 - final ObjectName name =
534.312 - JMXDomain.getDomainObjectName("gloups");
534.313 - final JMXDomain jmxDomain = new JMXDomain(
534.314 - new LocalDomainRepository("gloups"));
534.315 - testRegister("testRegisterPseudoVirtual: ",name,jmxDomain);
534.316 - }
534.317 -
534.318 - public static void testRegister(final String test,
534.319 - final ObjectName name,
534.320 - final JMXDomain jmxDomain) throws Exception {
534.321 - System.out.println(test+" START");
534.322 - MBeanServer server = newMBeanServer();
534.323 - final ObjectInstance oi =
534.324 - server.registerMBean(jmxDomain,name);
534.325 - System.out.println(test+"Succesfully registered namespace: "+name);
534.326 - if (!server.isRegistered(name))
534.327 - fail(test+name+" is not registered!");
534.328 - if (!server.queryNames(new ObjectName(name.getDomain()+":*"), null).
534.329 - contains(name))
534.330 - fail(test+name+" not in queryNames");
534.331 -
534.332 - final Thing thing = new Thing();
534.333 - final ObjectName thingName = new ObjectName("gloups:type=Thing");
534.334 - server.registerMBean(thing,thingName);
534.335 - if (!server.isRegistered(thingName))
534.336 - fail(test+thingName+" is not registered!");
534.337 - if (!jmxDomain.getSourceServer().isRegistered(thingName))
534.338 - fail(test+thingName+" is not registered in domain!");
534.339 - if (!server.queryNames(new ObjectName(name.getDomain()+":*"), null).
534.340 - contains(thingName))
534.341 - fail(test+thingName+" not in queryNames");
534.342 -
534.343 - server.unregisterMBean(name);
534.344 - if (server.isRegistered(thingName))
534.345 - fail(test+thingName+" is still registered!");
534.346 - if (server.queryNames(new ObjectName(name.getDomain()+":*"), null).
534.347 - contains(thingName))
534.348 - fail(test+thingName+" still in queryNames");
534.349 -
534.350 - server.registerMBean(jmxDomain, name);
534.351 - if (!server.isRegistered(thingName))
534.352 - fail(test+thingName+" is not registered again!");
534.353 -
534.354 - System.out.println(test+" PASSED");
534.355 - }
534.356 -
534.357 - private static MBeanServerNotification pop(
534.358 - BlockingQueue<Notification> queue,
534.359 - String type,
534.360 - ObjectName mbean,
534.361 - String test)
534.362 - throws InterruptedException {
534.363 - final Notification n = queue.poll(1, TimeUnit.SECONDS);
534.364 - if (!(n instanceof MBeanServerNotification))
534.365 - fail(test+"expected MBeanServerNotification, got "+n);
534.366 - final MBeanServerNotification msn = (MBeanServerNotification)n;
534.367 - if (!type.equals(msn.getType()))
534.368 - fail(test+"expected "+type+", got "+msn.getType());
534.369 - if (!mbean.apply(msn.getMBeanName()))
534.370 - fail(test+"expected "+mbean+", got "+msn.getMBeanName());
534.371 - System.out.println(test+" got: "+msn);
534.372 - return msn;
534.373 - }
534.374 - private static MBeanServerNotification popADD(
534.375 - BlockingQueue<Notification> queue,
534.376 - ObjectName mbean,
534.377 - String test)
534.378 - throws InterruptedException {
534.379 - return pop(queue, MBeanServerNotification.REGISTRATION_NOTIFICATION,
534.380 - mbean, test);
534.381 - }
534.382 -
534.383 - private static MBeanServerNotification popREM(
534.384 - BlockingQueue<Notification> queue,
534.385 - ObjectName mbean,
534.386 - String test)
534.387 - throws InterruptedException {
534.388 - return pop(queue, MBeanServerNotification.UNREGISTRATION_NOTIFICATION,
534.389 - mbean, test);
534.390 - }
534.391 -
534.392 -
534.393 - public static void testRegisterNotifSimple() throws Exception {
534.394 - final ObjectName name =
534.395 - JMXDomain.getDomainObjectName("gloups");
534.396 - final JMXDomain jmxDomain = new JMXDomain(
534.397 - MBeanServerFactory.newMBeanServer());
534.398 - testRegisterNotif("testRegisterNotifSimple: ",name,jmxDomain);
534.399 - }
534.400 -
534.401 - public static void testRegisterNotifPseudoVirtual()
534.402 - throws Exception {
534.403 - final ObjectName name =
534.404 - JMXDomain.getDomainObjectName("gloups");
534.405 - final JMXDomain jmxDomain = new JMXDomain(
534.406 - new LocalDomainRepository("gloups"));
534.407 - testRegisterNotif("testRegisterNotifPseudoVirtual: ",name,jmxDomain);
534.408 - }
534.409 -
534.410 - public static void testRegisterNotif(final String test,
534.411 - final ObjectName name,
534.412 - final JMXDomain jmxDomain) throws Exception {
534.413 - System.out.println(test+" START");
534.414 - MBeanServer server = newMBeanServer();
534.415 - final ObjectInstance oi =
534.416 - server.registerMBean(jmxDomain,name);
534.417 - System.out.println(test+"Succesfully registered namespace: "+name);
534.418 - if (!server.isRegistered(name))
534.419 - fail(test+name+" is not registered!");
534.420 -
534.421 - final BlockingQueue<Notification> queue =
534.422 - new ArrayBlockingQueue<Notification>(10);
534.423 -
534.424 - final NotificationListener l = new NotificationListener() {
534.425 -
534.426 - public void handleNotification(Notification notification,
534.427 - Object handback) {
534.428 - try {
534.429 - if (!queue.offer(notification,5,TimeUnit.SECONDS))
534.430 - throw new RuntimeException("timeout exceeded");
534.431 - } catch (Exception x) {
534.432 - fail(test+"failed to handle notif", x);
534.433 - }
534.434 - }
534.435 - };
534.436 -
534.437 - server.addNotificationListener(MBeanServerDelegate.DELEGATE_NAME, l,
534.438 - null, null);
534.439 -
534.440 - final Thing thing = new Thing();
534.441 - final ObjectName thingName = new ObjectName("gloups:type=Thing");
534.442 -
534.443 - server.registerMBean(thing,thingName);
534.444 - if (!jmxDomain.getSourceServer().isRegistered(thingName))
534.445 - fail(test+thingName+" is not registered in domain!");
534.446 - popADD(queue, thingName, test);
534.447 - server.unregisterMBean(thingName);
534.448 - if (jmxDomain.getSourceServer().isRegistered(thingName))
534.449 - fail(test+thingName+" is still registered in domain!");
534.450 - popREM(queue, thingName, test);
534.451 - if (queue.size() != 0)
534.452 - fail(test+queue.size()+" notifs remain in queue "+queue);
534.453 -
534.454 - server.unregisterMBean(name);
534.455 - popREM(queue, name, test);
534.456 -
534.457 - jmxDomain.getSourceServer().registerMBean(thing,thingName);
534.458 - if (server.isRegistered(thingName))
534.459 - fail(test+thingName+" is still registered in domain!");
534.460 - jmxDomain.getSourceServer().unregisterMBean(thingName);
534.461 - if (queue.size() != 0)
534.462 - fail(test+queue.size()+" notifs remain in queue "+queue);
534.463 -
534.464 - server.registerMBean(jmxDomain, name);
534.465 - if (!server.isRegistered(name))
534.466 - fail(test+name+" is not registered again!");
534.467 - popADD(queue, name, test);
534.468 - if (queue.size() != 0)
534.469 - fail(test+queue.size()+" notifs remain in queue "+queue);
534.470 -
534.471 - server.registerMBean(thing,thingName);
534.472 - if (!jmxDomain.getSourceServer().isRegistered(thingName))
534.473 - fail(test+thingName+" is not registered in domain!");
534.474 - popADD(queue, thingName, test);
534.475 - server.unregisterMBean(thingName);
534.476 - if (jmxDomain.getSourceServer().isRegistered(thingName))
534.477 - fail(test+thingName+" is still registered in domain!");
534.478 - popREM(queue, thingName, test);
534.479 - if (queue.size() != 0)
534.480 - fail(test+queue.size()+" notifs remain in queue "+queue);
534.481 -
534.482 - System.out.println(test+" PASSED");
534.483 - }
534.484 -
534.485 -
534.486 -
534.487 - private static void fail(String msg) {
534.488 - raise(new RuntimeException(msg));
534.489 - }
534.490 -
534.491 - private static void fail(String msg, Throwable cause) {
534.492 - raise(new RuntimeException(msg,cause));
534.493 - }
534.494 -
534.495 - private static void raise(RuntimeException x) {
534.496 - lastException = x;
534.497 - exceptionCount++;
534.498 - throw x;
534.499 - }
534.500 -
534.501 - private static volatile Exception lastException = null;
534.502 - private static volatile int exceptionCount = 0;
534.503 -
534.504 - public static void main(String... args) throws Exception {
534.505 - testCreateWithNull();
534.506 -
534.507 - testRegisterSimple();
534.508 - testRegisterNotifSimple();
534.509 -
534.510 - testRegisterPseudoVirtual();
534.511 - testRegisterNotifPseudoVirtual();
534.512 -
534.513 - if (lastException != null)
534.514 - throw lastException;
534.515 - }
534.516 -}
535.1 --- a/test/javax/management/namespace/JMXNamespaceSecurityTest.java Mon Nov 23 10:04:47 2009 +0000
535.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
535.3 @@ -1,274 +0,0 @@
535.4 -/*
535.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
535.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
535.7 - *
535.8 - * This code is free software; you can redistribute it and/or modify it
535.9 - * under the terms of the GNU General Public License version 2 only, as
535.10 - * published by the Free Software Foundation.
535.11 - *
535.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
535.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
535.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
535.15 - * version 2 for more details (a copy is included in the LICENSE file that
535.16 - * accompanied this code).
535.17 - *
535.18 - * You should have received a copy of the GNU General Public License version
535.19 - * 2 along with this work; if not, write to the Free Software Foundation,
535.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
535.21 - *
535.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
535.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
535.24 - * have any questions.
535.25 - */
535.26 -
535.27 -/*
535.28 - *
535.29 - * @test JMXNamespaceSecurityTest.java
535.30 - * @summary General JMXNamespaceSecurityTest test.
535.31 - * @author Daniel Fuchs
535.32 - * @bug 5072476 6299231
535.33 - * @run clean JMXNamespaceViewTest JMXNamespaceSecurityTest Wombat WombatMBean
535.34 - * LazyDomainTest
535.35 - * @run build JMXNamespaceSecurityTest JMXNamespaceViewTest Wombat WombatMBean
535.36 - * LazyDomainTest
535.37 - * @run main/othervm JMXNamespaceSecurityTest namespace.policy
535.38 - */
535.39 -import java.io.File;
535.40 -import java.io.IOException;
535.41 -import java.util.HashMap;
535.42 -import java.util.List;
535.43 -import java.util.Map;
535.44 -import java.util.logging.Logger;
535.45 -import java.lang.management.ManagementFactory;
535.46 -import java.util.ArrayList;
535.47 -import java.util.HashSet;
535.48 -import java.util.Set;
535.49 -import java.util.TreeSet;
535.50 -import javax.management.MBeanServer;
535.51 -import javax.management.MBeanServerFactory;
535.52 -import javax.management.ObjectName;
535.53 -import javax.management.namespace.JMXDomain;
535.54 -import javax.management.namespace.JMXNamespace;
535.55 -import javax.management.namespace.JMXNamespaces;
535.56 -import javax.management.remote.JMXConnectorServer;
535.57 -import javax.management.ClientContext;
535.58 -
535.59 -/**
535.60 - *
535.61 - * @author Sun Microsystems, Inc.
535.62 - */
535.63 -public class JMXNamespaceSecurityTest extends JMXNamespaceViewTest {
535.64 -
535.65 - /**
535.66 - * A logger for this class.
535.67 - **/
535.68 - private static final Logger LOG =
535.69 - Logger.getLogger(JMXNamespaceSecurityTest.class.getName());
535.70 -
535.71 - public static class NamedMBeanServerCreator
535.72 - extends JMXNamespaceViewTest.MBeanServerConfigCreator {
535.73 - public MBeanServer createMBeanServerFor(NamespaceConfig config) {
535.74 - return MBeanServerFactory.
535.75 - createNamedMBeanServer(config.name,config.name);
535.76 - }
535.77 - }
535.78 - /**
535.79 - * Creates a config for a hierarchy of namespaces, mixing local namespaces
535.80 - * and remote namespaces using the given protocol.
535.81 - * @param protocol The protocol that should be used for remote namespaces.
535.82 - * @return A namespace config hierarchy.
535.83 - * @throws java.lang.Exception
535.84 - */
535.85 - public static NamespaceConfig[] makeConfig(String protocol)
535.86 - throws Exception {
535.87 - final NamespaceConfig[] config = {
535.88 - // Top level namespace "top1" (local)
535.89 - config("top1",wombats("wchief","w1","w2","w3"),
535.90 - // top1//local1
535.91 - config("local1",wombats("wchief","ww1","ww2")),
535.92 - // top1//local2
535.93 - config("local2",wombats("wchief","ww4","ww5","ww6"),
535.94 - // top1//local2//local3
535.95 - config("local3",wombats("wchief","www1","www2")),
535.96 - // top1//local2//rmi1
535.97 - config("rmi1",url(protocol),wombats("wchief","www3","www4","www5"))),
535.98 - // top1//rmi2
535.99 - config("rmi2",url(protocol),wombats("wchief","ww7","ww8","ww9"),
535.100 - // top1//rmi2//local4
535.101 - config("local4",wombats("wchief","www6","www7")),
535.102 - // top1//rmi2//rmi3
535.103 - config("rmi3",url(protocol),wombats("wchief","www3","www4","www5"),
535.104 - // top1//rmi2//rmi3//local5
535.105 - config("local5",wombats("wchief","wwww1"))))),
535.106 - // Top level namespace "top2" (local)
535.107 - config("top2",wombats("wchief","w21","w22","w23"),
535.108 - // top2//local21
535.109 - config("local21",wombats("wchief","ww21","ww22")),
535.110 - // top2//rmi22
535.111 - config("rmi22",url(protocol),wombats("wchief","ww27","ww28","ww29"),
535.112 - // top2//rmi22//local24
535.113 - config("local24",wombats("wchief","www26","www27")),
535.114 - // top2//rmi22//rmi23
535.115 - config("rmi23",url(protocol),wombats("wchief","www23","www24","www25"),
535.116 - // top2//rmi22//rmi23//local25
535.117 - config("local25",wombats("wchief","wwww21"))))),
535.118 - // Top level namespace "top3" (remote)
535.119 - config("top3",url(protocol),wombats("wchief","w31","w32","w33"),
535.120 - // top3//local31
535.121 - config("local31",wombats("wchief","ww31","ww32")),
535.122 - // top3//rmi32
535.123 - config("rmi32",url(protocol),wombats("wchief","ww37","ww38","ww39"),
535.124 - // top3//rmi32//local34
535.125 - config("local34",wombats("wchief","www36","www37")),
535.126 - // top3//rmi32//rmi33
535.127 - config("rmi33",url(protocol),wombats("wchief","www33","www34","www35"),
535.128 - // top3//rmi32//local35
535.129 - config("local35",wombats("wchief","wwww31"))))),
535.130 - };
535.131 - return config;
535.132 - }
535.133 -
535.134 - public static void test(MBeanServer server, NamespaceConfig[] namespaces)
535.135 - throws Exception {
535.136 - System.out.println("Launching test...");
535.137 - List<JMXConnectorServer> cslist = load(server,
535.138 - new NamedMBeanServerCreator(), namespaces);
535.139 - Map<String,NamespaceConfig> inputMap =
535.140 - new HashMap<String,NamespaceConfig>();
535.141 -
535.142 - for (NamespaceConfig cfg : namespaces) {
535.143 - fillMap(inputMap,"",cfg);
535.144 - }
535.145 - final MBeanServer platform = ManagementFactory.getPlatformMBeanServer();
535.146 - //if (System.getProperty("jmx.wait")!=null) {
535.147 - /*
535.148 - // if we wanted to lazy load the platform MBeanServer:
535.149 - final LazyDomainTest.MBeanServerLoader loader =
535.150 - new LazyDomainTest.MBeanServerLoader() {
535.151 - public MBeanServer loadMBeanServer() {
535.152 - return ManagementFactory.getPlatformMBeanServer();
535.153 - }
535.154 - };
535.155 - final LazyDomainTest.MBeanServerProxy proxy =
535.156 - new LazyDomainTest.MBeanServerProxy(loader);
535.157 - final LazyDomainTest.LazyDomain domain =
535.158 - new LazyDomainTest.LazyDomain(proxy);
535.159 - server.registerMBean(domain,
535.160 - JMXDomain.getDomainObjectName("java.lang"));
535.161 - */
535.162 - // Mount java.lang MBeans into our private server so that
535.163 - // visualvm can connect.
535.164 - server.registerMBean(
535.165 - new JMXDomain(platform),
535.166 - JMXDomain.getDomainObjectName("java.lang"));
535.167 - //}
535.168 - if (System.getProperty("jmx.wait")!=null) {
535.169 - platform.registerMBean(new JMXNamespace(server),
535.170 - JMXNamespaces.getNamespaceObjectName("test"));
535.171 - }
535.172 -
535.173 - System.setSecurityManager(new SecurityManager());
535.174 -
535.175 - // Some sanity checks... The policy file should allow access
535.176 - // to java.lang MBeans.
535.177 - final ObjectName platnames = new ObjectName("java.lang:*");
535.178 - for (ObjectName o : platform.queryNames(platnames,null)) {
535.179 - server.getMBeanInfo(o);
535.180 - }
535.181 - final Set<ObjectName> lang =
535.182 - new HashSet<ObjectName>(server.queryNames(platnames, null));
535.183 - lang.remove(JMXDomain.getDomainObjectName("java.lang"));
535.184 - if (!lang.equals(platform.
535.185 - queryNames(platnames, null)))
535.186 - throw new Exception("Wrong list of platform names: "+lang);
535.187 - System.out.println("Got all java.lang MBeans: "+lang);
535.188 -
535.189 - // The policy file should allow to see all namespaces.
535.190 - // check this...
535.191 - final List<ObjectName> patterns = new ArrayList<ObjectName>();
535.192 - final Set<String> paths = new TreeSet<String>();
535.193 - final Set<String> uuids = new HashSet<String>();
535.194 - patterns.add(new ObjectName("*//:*"));
535.195 - while (patterns.size()>0) {
535.196 - System.out.println("server.queryNames("+patterns.get(0)+",null)");
535.197 - Set<ObjectName> names = server.queryNames(patterns.remove(0),null);
535.198 - System.out.println("found: "+names);
535.199 -
535.200 - for (ObjectName no : names) {
535.201 - final String uuid = (String) server.getAttribute(no, "UUID");
535.202 - if (uuids.contains(uuid)) {
535.203 - System.out.print("namespace "+no+", uuid="+uuid+
535.204 - " already parsed. Skipping");
535.205 - continue;
535.206 - }
535.207 - uuids.add(uuid);
535.208 - patterns.add(new ObjectName(no.getDomain()+"*//:*"));
535.209 - System.out.println("added pattern: "+
535.210 - new ObjectName(no.getDomain()+"*//:*"));
535.211 - if (no.getDomain().endsWith(ClientContext.NAMESPACE+
535.212 - JMXNamespaces.NAMESPACE_SEPARATOR)) continue;
535.213 - paths.add(no.getDomain().substring(0,
535.214 - no.getDomain().length()-
535.215 - JMXNamespaces.NAMESPACE_SEPARATOR.length()));
535.216 - }
535.217 - }
535.218 - final TreeSet<String> expected = new TreeSet<String>(inputMap.keySet());
535.219 - if (!expected.equals(paths)) {
535.220 - throw new Exception("wrong set of namespaces, expected "+
535.221 - expected+", got "+paths);
535.222 - }
535.223 -
535.224 - System.out.println("Got all namespaces: "+paths);
535.225 -
535.226 - // Check that we can see all wombats.
535.227 - //
535.228 - ObjectName wchief =
535.229 - new ObjectName("top1//rmi2//wombat:name=wchief,type=Wombat");
535.230 - String caption = (String) server.getAttribute(wchief,"Caption");
535.231 - System.out.println("wchief says "+caption);
535.232 - Object mood = server.getAttribute(wchief,"Mood");
535.233 - System.out.println("wchief's mood on a scale of 100 is "+mood);
535.234 -
535.235 - ObjectName wchief2 =
535.236 - new ObjectName("top1//wombat:name=wchief,type=Wombat");
535.237 - String caption2 = (String) server.getAttribute(wchief2,"Caption");
535.238 - System.out.println("wchief2 says "+caption2);
535.239 - try {
535.240 - Object mood2 = server.getAttribute(wchief2,"Mood");
535.241 - System.out.println("wchief2's mood on a scale of 100 is "+mood2);
535.242 - throw new Exception("Expected security exception for "+
535.243 - "getAttribute("+wchief2+", \"Mood\"");
535.244 - } catch (SecurityException x) {
535.245 - System.out.println("wchief2's mood is unavailable: "+x);
535.246 - }
535.247 - try {
535.248 - exportAndWaitIfNeeded(server);
535.249 - } finally {
535.250 - closeAll(cslist);
535.251 - }
535.252 -
535.253 - }
535.254 - /** Creates a new instance of JMXNamespaceTest */
535.255 - public JMXNamespaceSecurityTest() {
535.256 - }
535.257 -
535.258 - public static void main(String[] args) throws Exception {
535.259 - String osName = System.getProperty("os.name");
535.260 - System.out.println("os.name = " + osName);
535.261 - if (!osName.equals("SunOS")) {
535.262 - System.out.println("This test runs on Solaris only.");
535.263 - System.out.println("Bye! Bye!");
535.264 - return;
535.265 - }
535.266 - final String policy = System.getProperty("test.src") +
535.267 - File.separator + args[0];
535.268 - System.out.println("PolicyFile = " + policy);
535.269 - System.setProperty("java.security.policy", policy);
535.270 - if (!new File(System.getProperty("java.security.policy")).canRead())
535.271 - throw new IOException("no such file: "+
535.272 - System.getProperty("java.security.policy"));
535.273 - test(MBeanServerFactory.createNamedMBeanServer("root","root"),
535.274 - makeConfig("rmi"));
535.275 - }
535.276 -
535.277 -}
536.1 --- a/test/javax/management/namespace/JMXNamespaceTest.java Mon Nov 23 10:04:47 2009 +0000
536.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
536.3 @@ -1,511 +0,0 @@
536.4 -/*
536.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
536.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
536.7 - *
536.8 - * This code is free software; you can redistribute it and/or modify it
536.9 - * under the terms of the GNU General Public License version 2 only, as
536.10 - * published by the Free Software Foundation.
536.11 - *
536.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
536.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
536.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
536.15 - * version 2 for more details (a copy is included in the LICENSE file that
536.16 - * accompanied this code).
536.17 - *
536.18 - * You should have received a copy of the GNU General Public License version
536.19 - * 2 along with this work; if not, write to the Free Software Foundation,
536.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
536.21 - *
536.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
536.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
536.24 - * have any questions.
536.25 - */
536.26 -
536.27 -/*
536.28 - *
536.29 - * @test JMXNamespaceTest.java
536.30 - * @summary General JMXNamespace test.
536.31 - * @bug 5072476
536.32 - * @author Daniel Fuchs
536.33 - * @run clean JMXNamespaceTest
536.34 - * Wombat WombatMBean JMXRemoteTargetNamespace
536.35 - * NamespaceController NamespaceControllerMBean
536.36 - * @compile -XDignore.symbol.file=true JMXNamespaceTest.java
536.37 - * Wombat.java WombatMBean.java JMXRemoteTargetNamespace.java
536.38 - * NamespaceController.java NamespaceControllerMBean.java
536.39 - * @run main/othervm JMXNamespaceTest
536.40 - */
536.41 -import java.lang.management.ManagementFactory;
536.42 -import java.lang.management.MemoryMXBean;
536.43 -import java.lang.reflect.InvocationTargetException;
536.44 -import java.lang.reflect.Method;
536.45 -import java.util.Arrays;
536.46 -import java.util.Collections;
536.47 -import java.util.List;
536.48 -import java.util.Map;
536.49 -import java.util.Set;
536.50 -import java.util.logging.Logger;
536.51 -import javax.management.DynamicMBean;
536.52 -import javax.management.InstanceNotFoundException;
536.53 -import javax.management.InvalidAttributeValueException;
536.54 -import javax.management.JMX;
536.55 -import javax.management.MBeanServer;
536.56 -import javax.management.MBeanServerConnection;
536.57 -import javax.management.MBeanServerFactory;
536.58 -import javax.management.NotificationEmitter;
536.59 -import javax.management.ObjectInstance;
536.60 -import javax.management.ObjectName;
536.61 -import javax.management.StandardMBean;
536.62 -import javax.management.namespace.JMXNamespaces;
536.63 -import javax.management.namespace.JMXNamespace;
536.64 -import javax.management.namespace.JMXNamespaceMBean;
536.65 -import javax.management.namespace.JMXRemoteNamespaceMBean;
536.66 -import javax.management.namespace.MBeanServerConnectionWrapper;
536.67 -import javax.management.namespace.MBeanServerSupport;
536.68 -import javax.management.remote.JMXConnector;
536.69 -import javax.management.remote.JMXConnectorFactory;
536.70 -import javax.management.remote.JMXConnectorServer;
536.71 -import javax.management.remote.JMXConnectorServerFactory;
536.72 -import javax.management.remote.JMXServiceURL;
536.73 -
536.74 -/**
536.75 - *
536.76 - * @author Sun Microsystems, Inc.
536.77 - */
536.78 -public class JMXNamespaceTest {
536.79 -
536.80 - /**
536.81 - * A logger for this class.
536.82 - **/
536.83 - private static final Logger LOG =
536.84 - Logger.getLogger(JMXNamespaceTest.class.getName());
536.85 -
536.86 - /** Creates a new instance of JMXNamespaceTest */
536.87 - public JMXNamespaceTest() {
536.88 - }
536.89 -
536.90 - public static class WombatRepository extends MBeanServerSupport {
536.91 - final Wombat wombat;
536.92 - final StandardMBean mbean;
536.93 - final ObjectName wombatName;
536.94 -
536.95 - public WombatRepository(ObjectName wombatName) {
536.96 - try {
536.97 - wombat = new Wombat();
536.98 - mbean = wombat;
536.99 - this.wombatName = wombatName;
536.100 - wombat.preRegister(null,wombatName);
536.101 - } catch (Exception x) {
536.102 - throw new IllegalArgumentException(x);
536.103 - }
536.104 - }
536.105 -
536.106 - @Override
536.107 - public DynamicMBean getDynamicMBeanFor(ObjectName name)
536.108 - throws InstanceNotFoundException {
536.109 - if (wombatName.equals(name)) return mbean;
536.110 - else throw new InstanceNotFoundException(String.valueOf(name));
536.111 - }
536.112 -
536.113 - @Override
536.114 - protected Set<ObjectName> getNames() {
536.115 - final Set<ObjectName> res = Collections.singleton(wombatName);
536.116 - return res;
536.117 - }
536.118 -
536.119 - @Override
536.120 - public NotificationEmitter
536.121 - getNotificationEmitterFor(ObjectName name)
536.122 - throws InstanceNotFoundException {
536.123 - final DynamicMBean mb = getDynamicMBeanFor(name);
536.124 - if (mb instanceof NotificationEmitter)
536.125 - return (NotificationEmitter)mb;
536.126 - return null;
536.127 - }
536.128 - }
536.129 -
536.130 - public static class SimpleTest {
536.131 - public final String descr;
536.132 - private final Class<?> testClass;
536.133 - private final Method method;
536.134 - public SimpleTest(String descr) {
536.135 - this.descr = descr;
536.136 - this.testClass = JMXNamespaceTest.class;
536.137 - try {
536.138 - method = testClass.
536.139 - getDeclaredMethod(descr,SimpleTestConf.class,
536.140 - Object[].class);
536.141 - } catch (NoSuchMethodException x) {
536.142 - throw new IllegalArgumentException(descr+": test not found",
536.143 - x);
536.144 - }
536.145 - }
536.146 -
536.147 - public void run(SimpleTestConf conf, Object... args)
536.148 - throws Exception {
536.149 - try {
536.150 - method.invoke(null,conf,args);
536.151 - } catch (InvocationTargetException x) {
536.152 - final Throwable cause = x.getCause();
536.153 - if (cause instanceof Exception) throw (Exception)cause;
536.154 - if (cause instanceof Error) throw (Error)cause;
536.155 - throw x;
536.156 - }
536.157 - }
536.158 - }
536.159 -
536.160 - public static class SimpleTestConf {
536.161 - public final Wombat wombat;
536.162 - public final StandardMBean mbean;
536.163 - public final String dirname;
536.164 - public final ObjectName handlerName;
536.165 - public final ObjectName wombatNickName;
536.166 - public final ObjectName wombatName;
536.167 - public final JMXNamespace wombatNamespace;
536.168 - public final MBeanServer server;
536.169 - public final WombatMBean proxy;
536.170 - public SimpleTestConf(String[] args) throws Exception {
536.171 - wombat = new Wombat();
536.172 - mbean = wombat;
536.173 - dirname = "wombat";
536.174 - handlerName =
536.175 - new ObjectName(dirname+"//:type=JMXNamespace");
536.176 -
536.177 - wombatNickName =
536.178 - new ObjectName("burrow:type=Wombat");
536.179 -
536.180 - wombatName =
536.181 - new ObjectName(dirname+"//"+wombatNickName);
536.182 -
536.183 - wombatNamespace =
536.184 - new JMXNamespace(
536.185 - new WombatRepository(wombatNickName));
536.186 -
536.187 - server = ManagementFactory.getPlatformMBeanServer();
536.188 - System.out.println(handlerName+" registered="+
536.189 - server.isRegistered(handlerName));
536.190 - server.registerMBean(wombatNamespace,handlerName);
536.191 -
536.192 - try {
536.193 - proxy = JMX.newMBeanProxy(server,wombatName,
536.194 - WombatMBean.class);
536.195 - } catch (Exception x) {
536.196 - server.unregisterMBean(handlerName);
536.197 - throw x;
536.198 - }
536.199 - }
536.200 -
536.201 - public void close() {
536.202 - try {
536.203 - server.unregisterMBean(handlerName);
536.204 - } catch (Exception x) {
536.205 - System.out.println("Failed to close: " + x);
536.206 - x.printStackTrace();
536.207 - }
536.208 - }
536.209 -
536.210 - public void test(SimpleTest test,Object... args)
536.211 - throws Exception {
536.212 - try {
536.213 - test.run(this,args);
536.214 - passed++;
536.215 - } catch (Exception x) {
536.216 - failed++;
536.217 - System.err.println(test.descr+" failed: " + x);
536.218 - x.printStackTrace();
536.219 - }
536.220 - }
536.221 -
536.222 - public volatile int failed = 0;
536.223 - public volatile int passed = 0;
536.224 - }
536.225 -
536.226 - static void checkValue(String name,Object expected, Object returned)
536.227 - throws InvalidAttributeValueException {
536.228 - if (Collections.singletonList(expected).
536.229 - equals(Collections.singletonList(returned))) return;
536.230 -
536.231 - throw new InvalidAttributeValueException("Bad value for "+
536.232 - name+": ["+returned+"] - was expecting ["+expected+"]");
536.233 - }
536.234 -
536.235 - // ---------------------------------------------------------------
536.236 - // SIMPLE TESTS BEGIN HERE
536.237 - // ---------------------------------------------------------------
536.238 -
536.239 - static void getCaptionTest(SimpleTestConf env, Object... args)
536.240 - throws Exception {
536.241 - System.out.println(env.proxy.getCaption());
536.242 - }
536.243 -
536.244 - static void setCaptionTest(SimpleTestConf env, Object... args)
536.245 - throws Exception {
536.246 - env.proxy.setCaption((String)args[0]);
536.247 - final String result = env.proxy.getCaption();
536.248 - System.out.println(result);
536.249 - checkValue("Caption",args[0],result);
536.250 - }
536.251 -
536.252 - static void queryNamesTest1(SimpleTestConf env, Object... args)
536.253 - throws Exception {
536.254 - final ObjectName pat =
536.255 - new ObjectName(env.handlerName.getDomain()+"*:*");
536.256 - final Set<ObjectName> res =
536.257 - env.server.queryNames(pat,null);
536.258 - System.out.println("queryNamesTest1: "+res);
536.259 - checkValue("names",Collections.singleton(env.wombatName),res);
536.260 - }
536.261 -
536.262 - static void queryNamesTest2(SimpleTestConf env, Object... args)
536.263 - throws Exception {
536.264 - final ObjectName pat =
536.265 - new ObjectName("*:"+
536.266 - env.wombatName.getKeyPropertyListString());
536.267 - final Set<ObjectName> res =
536.268 - env.server.queryNames(pat,null);
536.269 - System.out.println("queryNamesTest2: "+res);
536.270 - checkValue("names",Collections.emptySet(),res);
536.271 - }
536.272 -
536.273 - static void getDomainsTest(SimpleTestConf env, Object... args)
536.274 - throws Exception {
536.275 - final List<String> domains =
536.276 - Arrays.asList(env.server.getDomains());
536.277 - System.out.println("getDomainsTest: "+domains);
536.278 - if (domains.contains(env.wombatName.getDomain()))
536.279 - throw new InvalidAttributeValueException("domain: "+
536.280 - env.wombatName.getDomain());
536.281 - if (!domains.contains(env.handlerName.getDomain()))
536.282 - throw new InvalidAttributeValueException("domain not found: "+
536.283 - env.handlerName.getDomain());
536.284 - }
536.285 -
536.286 - // ---------------------------------------------------------------
536.287 - // SIMPLE TESTS END HERE
536.288 - // ---------------------------------------------------------------
536.289 -
536.290 - private static void simpleTest(String[] args) {
536.291 - final SimpleTestConf conf;
536.292 - try {
536.293 - conf = new SimpleTestConf(args);
536.294 - try {
536.295 - conf.test(new SimpleTest("getCaptionTest"));
536.296 - conf.test(new SimpleTest("setCaptionTest"),
536.297 - "I am a new Wombat!");
536.298 - conf.test(new SimpleTest("queryNamesTest1"));
536.299 - conf.test(new SimpleTest("queryNamesTest2"));
536.300 - conf.test(new SimpleTest("getDomainsTest"));
536.301 - } finally {
536.302 - conf.close();
536.303 - }
536.304 - } catch (Exception x) {
536.305 - System.err.println("simpleTest FAILED: " +x);
536.306 - x.printStackTrace();
536.307 - throw new RuntimeException(x);
536.308 - }
536.309 - System.out.println("simpleTest: "+conf.passed+
536.310 - " PASSED, " + conf.failed + " FAILED.");
536.311 - if (conf.failed>0) {
536.312 - System.err.println("simpleTest FAILED ["+conf.failed+"]");
536.313 - throw new RuntimeException("simpleTest FAILED ["+conf.failed+"]");
536.314 - } else {
536.315 - System.err.println("simpleTest PASSED ["+conf.passed+"]");
536.316 - }
536.317 - }
536.318 -
536.319 - public static void recursiveTest(String[] args) {
536.320 - final SimpleTestConf conf;
536.321 - try {
536.322 - conf = new SimpleTestConf(args);
536.323 - try {
536.324 - final JMXServiceURL url =
536.325 - new JMXServiceURL("rmi","localHost",0);
536.326 - final Map<String,Object> empty = Collections.emptyMap();
536.327 - final JMXConnectorServer server =
536.328 - JMXConnectorServerFactory.newJMXConnectorServer(url,
536.329 - empty,conf.server);
536.330 - server.start();
536.331 - final JMXServiceURL address = server.getAddress();
536.332 - final JMXConnector client =
536.333 - JMXConnectorFactory.connect(address,
536.334 - empty);
536.335 - final String[] signature = {
536.336 - JMXServiceURL.class.getName(),
536.337 - Map.class.getName(),
536.338 - };
536.339 - final String[] signature2 = {
536.340 - JMXServiceURL.class.getName(),
536.341 - Map.class.getName(),
536.342 - String.class.getName(),
536.343 - };
536.344 - final Object[] params = {
536.345 - address,
536.346 - null,
536.347 - };
536.348 - final MBeanServerConnection c =
536.349 - client.getMBeanServerConnection();
536.350 - final ObjectName dirName1 =
536.351 - new ObjectName("kanga//:type=JMXNamespace");
536.352 - c.createMBean(JMXRemoteTargetNamespace.class.getName(),
536.353 - dirName1, params,signature);
536.354 - c.invoke(dirName1, "connect", null, null);
536.355 - try {
536.356 - final MemoryMXBean memory =
536.357 - JMX.newMXBeanProxy(c,
536.358 - new ObjectName("kanga//"+
536.359 - ManagementFactory.MEMORY_MXBEAN_NAME),
536.360 - MemoryMXBean.class);
536.361 - System.out.println("HeapMemory #1: "+
536.362 - memory.getHeapMemoryUsage().toString());
536.363 - final MemoryMXBean memory2 =
536.364 - JMX.newMXBeanProxy(c,
536.365 - new ObjectName("kanga//kanga//"+
536.366 - ManagementFactory.MEMORY_MXBEAN_NAME),
536.367 - MemoryMXBean.class);
536.368 - System.out.println("HeapMemory #2: "+
536.369 - memory2.getHeapMemoryUsage().toString());
536.370 - final Object[] params2 = {
536.371 - address,
536.372 - null,
536.373 - "kanga//kanga"
536.374 - // "kanga//kanga//roo//kanga", <= cycle
536.375 - };
536.376 - final ObjectName dirName2 =
536.377 - new ObjectName("kanga//roo//:type=JMXNamespace");
536.378 - c.createMBean(JMXRemoteTargetNamespace.class.getName(),
536.379 - dirName2, params2, signature2);
536.380 - System.out.println(dirName2 + " created!");
536.381 - JMX.newMBeanProxy(c,dirName2,
536.382 - JMXRemoteNamespaceMBean.class).connect();
536.383 - try {
536.384 - final ObjectName wombatName1 =
536.385 - new ObjectName("kanga//roo//"+conf.wombatName);
536.386 - final ObjectName wombatName2 =
536.387 - new ObjectName("kanga//roo//"+wombatName1);
536.388 - final WombatMBean wombat1 =
536.389 - JMX.newMBeanProxy(c,wombatName1,WombatMBean.class);
536.390 - final WombatMBean wombat2 =
536.391 - JMX.newMBeanProxy(c,wombatName2,WombatMBean.class);
536.392 - final String newCaption="I am still the same old wombat";
536.393 - wombat1.setCaption(newCaption);
536.394 - final String caps = conf.proxy.getCaption();
536.395 - System.out.println("Caption: "+caps);
536.396 - checkValue("Caption",newCaption,caps);
536.397 - final String caps1 = wombat1.getCaption();
536.398 - System.out.println("Caption #1: "+caps1);
536.399 - checkValue("Caption #1",newCaption,caps1);
536.400 - final String caps2 = wombat2.getCaption();
536.401 - System.out.println("Caption #2: "+caps2);
536.402 - checkValue("Caption #2",newCaption,caps2);
536.403 - final ObjectInstance instance =
536.404 - NamespaceController.createInstance(conf.server);
536.405 - final NamespaceControllerMBean controller =
536.406 - JMX.newMBeanProxy(conf.server,instance.getObjectName(),
536.407 - NamespaceControllerMBean.class);
536.408 - final String[] dirs = controller.findNamespaces();
536.409 - System.out.println("directories: " +
536.410 - Arrays.asList(dirs));
536.411 - final int depth = 4;
536.412 - final String[] dirs2 = controller.findNamespaces(null,null,depth);
536.413 - System.out.println("directories[depth="+depth+"]: " +
536.414 - Arrays.asList(dirs2));
536.415 - for (String dir : dirs2) {
536.416 - if (dir.endsWith(JMXNamespaces.NAMESPACE_SEPARATOR))
536.417 - dir = dir.substring(0,dir.length()-
536.418 - JMXNamespaces.NAMESPACE_SEPARATOR.length());
536.419 - if (dir.split(JMXNamespaces.NAMESPACE_SEPARATOR).length
536.420 - > (depth+1)) {
536.421 - throw new RuntimeException(dir+": depth exceeds "+depth);
536.422 - }
536.423 - final ObjectName handlerName =
536.424 - JMXNamespaces.getNamespaceObjectName(dir);
536.425 - final JMXNamespaceMBean handler =
536.426 - JMX.newMBeanProxy(conf.server,handlerName,
536.427 - JMXNamespaceMBean.class);
536.428 - try {
536.429 - System.err.println("Directory "+dir+" domains: "+
536.430 - Arrays.asList(handler.getDomains()));
536.431 - System.err.println("Directory "+dir+" default domain: "+
536.432 - handler.getDefaultDomain());
536.433 - System.err.println("Directory "+dir+" MBean count: "+
536.434 - handler.getMBeanCount());
536.435 - } catch(Exception x) {
536.436 - System.err.println("get info failed for " +
536.437 - dir +", "+handlerName+": "+x);
536.438 - x.getCause().printStackTrace();
536.439 - throw x;
536.440 - }
536.441 - }
536.442 -
536.443 - } finally {
536.444 - c.unregisterMBean(dirName2);
536.445 - }
536.446 - } finally {
536.447 - c.unregisterMBean(dirName1);
536.448 - client.close();
536.449 - server.stop();
536.450 - }
536.451 - } finally {
536.452 - conf.close();
536.453 - }
536.454 - System.err.println("recursiveTest PASSED");
536.455 - } catch (Exception x) {
536.456 - System.err.println("recursiveTest FAILED: " +x);
536.457 - x.printStackTrace();
536.458 - throw new RuntimeException(x);
536.459 - }
536.460 - }
536.461 -
536.462 - public static void verySimpleTest(String[] args) {
536.463 - System.err.println("verySimpleTest: starting");
536.464 - try {
536.465 - final MBeanServer srv = MBeanServerFactory.createMBeanServer();
536.466 - srv.registerMBean(new JMXNamespace(
536.467 - JMXNamespaces.narrowToNamespace(srv, "foo")),
536.468 - JMXNamespaces.getNamespaceObjectName("foo"));
536.469 - throw new Exception("Excpected IllegalArgumentException not raised.");
536.470 - } catch (IllegalArgumentException x) {
536.471 - System.err.println("verySimpleTest: got expected exception: "+x);
536.472 - } catch (Exception x) {
536.473 - System.err.println("verySimpleTest FAILED: " +x);
536.474 - x.printStackTrace();
536.475 - throw new RuntimeException(x);
536.476 - }
536.477 - System.err.println("verySimpleTest: PASSED");
536.478 - }
536.479 -
536.480 - public static void verySimpleTest2(String[] args) {
536.481 - System.err.println("verySimpleTest2: starting");
536.482 - try {
536.483 - final MBeanServer srv = MBeanServerFactory.createMBeanServer();
536.484 - final JMXConnectorServer cs = JMXConnectorServerFactory.
536.485 - newJMXConnectorServer(new JMXServiceURL("rmi",null,0),
536.486 - null, srv);
536.487 - cs.start();
536.488 - final JMXConnector cc = JMXConnectorFactory.connect(cs.getAddress());
536.489 -
536.490 - srv.registerMBean(new JMXNamespace(
536.491 - new MBeanServerConnectionWrapper(
536.492 - JMXNamespaces.narrowToNamespace(
536.493 - cc.getMBeanServerConnection(),
536.494 - "foo"))),
536.495 - JMXNamespaces.getNamespaceObjectName("foo"));
536.496 - throw new Exception("Excpected IllegalArgumentException not raised.");
536.497 - } catch (IllegalArgumentException x) {
536.498 - System.err.println("verySimpleTest2: got expected exception: "+x);
536.499 - } catch (Exception x) {
536.500 - System.err.println("verySimpleTest2 FAILED: " +x);
536.501 - x.printStackTrace();
536.502 - throw new RuntimeException(x);
536.503 - }
536.504 - System.err.println("verySimpleTest2: PASSED");
536.505 - }
536.506 -
536.507 - public static void main(String[] args) {
536.508 - simpleTest(args);
536.509 - recursiveTest(args);
536.510 - verySimpleTest(args);
536.511 - verySimpleTest2(args);
536.512 - }
536.513 -
536.514 -}
537.1 --- a/test/javax/management/namespace/JMXNamespaceViewTest.java Mon Nov 23 10:04:47 2009 +0000
537.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
537.3 @@ -1,546 +0,0 @@
537.4 -/*
537.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
537.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
537.7 - *
537.8 - * This code is free software; you can redistribute it and/or modify it
537.9 - * under the terms of the GNU General Public License version 2 only, as
537.10 - * published by the Free Software Foundation.
537.11 - *
537.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
537.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
537.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
537.15 - * version 2 for more details (a copy is included in the LICENSE file that
537.16 - * accompanied this code).
537.17 - *
537.18 - * You should have received a copy of the GNU General Public License version
537.19 - * 2 along with this work; if not, write to the Free Software Foundation,
537.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
537.21 - *
537.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
537.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
537.24 - * have any questions.
537.25 - */
537.26 -/*
537.27 - *
537.28 - * @test JMXNamespaceViewTest.java
537.29 - * @summary Test the JMXNamespaceView class.
537.30 - * @bug 5072476
537.31 - * @author Daniel Fuchs
537.32 - * @run clean JMXNamespaceViewTest Wombat WombatMBean
537.33 - * @run build JMXNamespaceViewTest Wombat WombatMBean
537.34 - * @run main JMXNamespaceViewTest
537.35 - */
537.36 -
537.37 -
537.38 -import java.lang.management.ManagementFactory;
537.39 -import java.net.ServerSocket;
537.40 -import java.rmi.registry.LocateRegistry;
537.41 -import java.util.ArrayList;
537.42 -import java.util.Arrays;
537.43 -import java.util.HashMap;
537.44 -import java.util.HashSet;
537.45 -import java.util.List;
537.46 -import java.util.Map;
537.47 -import java.util.Set;
537.48 -import javax.management.ClientContext;
537.49 -import javax.management.JMException;
537.50 -import javax.management.MBeanRegistration;
537.51 -import javax.management.MBeanServer;
537.52 -import javax.management.MBeanServerFactory;
537.53 -import javax.management.ObjectInstance;
537.54 -import javax.management.ObjectName;
537.55 -import javax.management.namespace.JMXNamespace;
537.56 -import javax.management.namespace.JMXNamespaceView;
537.57 -import javax.management.namespace.JMXNamespaces;
537.58 -import javax.management.namespace.JMXRemoteNamespace;
537.59 -import javax.management.remote.JMXConnectorServer;
537.60 -import javax.management.remote.JMXConnectorServerFactory;
537.61 -import javax.management.remote.JMXServiceURL;
537.62 -
537.63 -/**
537.64 - * A simple test to test the JMXNamespaceViewTest...
537.65 - * @author dfuchs
537.66 - */
537.67 -public class JMXNamespaceViewTest {
537.68 -
537.69 - /**
537.70 - * Describe the configuration of a namespace
537.71 - */
537.72 - public static class NamespaceConfig {
537.73 - /** name of the namespace - no // allowed **/
537.74 - public String name;
537.75 - /**
537.76 - * JMXServiceURL through which the namespace is exported, if it
537.77 - * is a remote namespace. {@code null} if the namespace is local.
537.78 - * This is an inpur URL - eg: new JMXServiceURL("rmi",null,0).toString()
537.79 - * is acceptable here.
537.80 - */
537.81 - public String jmxurl;
537.82 - /**
537.83 - * Values of the name= key for each WombatMBean contained in the
537.84 - * namespace.
537.85 - */
537.86 - public String[] wombats;
537.87 - /** list of child namespace **/
537.88 - public NamespaceConfig[] children;
537.89 - }
537.90 -
537.91 - /**
537.92 - * Creates a NamespaceConfig record for a local namespace.
537.93 - * @param name name of the namespace
537.94 - * @param wombats names of WombatMBean it should contain.
537.95 - * @return a NamespaceConfig.
537.96 - */
537.97 - public static NamespaceConfig config(String name, String[] wombats) {
537.98 - return config(name,null,wombats);
537.99 - }
537.100 -
537.101 - /**
537.102 - * Creates a NamespaceConfig record for a remote namespace.
537.103 - * @param name name of the namespace
537.104 - * @param jmxurl input JMXServiceURL for creating the JMXConnectorServer
537.105 - * @param wombats names of WombatMBean it should contain.
537.106 - * @return a NamespaceConfig.
537.107 - */
537.108 - public static NamespaceConfig config(String name, String jmxurl,
537.109 - String[] wombats) {
537.110 - return config(name,jmxurl,wombats,(NamespaceConfig[])null);
537.111 - }
537.112 -
537.113 - /**
537.114 - * Creates a NamespaceConfig record for a local namespace.
537.115 - * @param name name of the namespace
537.116 - * @param wombats names of WombatMBean it should contain.
537.117 - * @param children list of sub namespaces.
537.118 - * @return a NamespaceConfig.
537.119 - */
537.120 - public static NamespaceConfig config(String name, String[] wombats,
537.121 - NamespaceConfig... children) {
537.122 - return config(name,null,wombats,children);
537.123 - }
537.124 -
537.125 - /**
537.126 - * Creates a NamespaceConfig record for a remote namespace.
537.127 - * @param name name of the namespace
537.128 - * @param jmxurl input JMXServiceURL for creating the JMXConnectorServer
537.129 - * @param wombats names of WombatMBean it should contain.
537.130 - * @param children list of sub namespaces.
537.131 - * @return a NamespaceConfig.
537.132 - */
537.133 - static NamespaceConfig config(String name, String jmxurl, String[] wombats,
537.134 - NamespaceConfig... children) {
537.135 - final NamespaceConfig cfg = new NamespaceConfig();
537.136 - cfg.name=name; cfg.jmxurl=jmxurl; cfg.wombats=wombats;
537.137 - cfg.children=children;
537.138 - return cfg;
537.139 - }
537.140 -
537.141 - /**
537.142 - * Returns the given names. This is a utility method to ease code
537.143 - * reading.
537.144 - * @param names names of Wombat MBeans.
537.145 - * @return the given names.
537.146 - */
537.147 - static String[] wombats(String... names) {
537.148 - return names;
537.149 - }
537.150 -
537.151 - /**
537.152 - * Creates a JMXServiceURL string for the given protocol.
537.153 - * This is also a utility method to ease code reading.
537.154 - * @param protocol The protocol name (e.g. "rmi")
537.155 - * @return A JMXServiceURL string.
537.156 - * @throws Exception if creation of the JMXServiceURL fails.
537.157 - */
537.158 - static String url(String protocol) throws Exception {
537.159 - return new JMXServiceURL(protocol,null,0).toString();
537.160 - }
537.161 -
537.162 - /**
537.163 - * Creates a config for a hierarchy of namespaces, mixing local namespaces
537.164 - * and remote namespaces using the given protocol.
537.165 - * @param protocol The protocol that should be used for remote namespaces.
537.166 - * @return A namespace config hierarchy.
537.167 - * @throws java.lang.Exception
537.168 - */
537.169 - public static NamespaceConfig[] makeConfig(String protocol)
537.170 - throws Exception {
537.171 - final NamespaceConfig[] config = {
537.172 - // Top level namespace "top1" (local)
537.173 - config("top1",wombats("wchief","w1","w2","w3"),
537.174 - // top1//local1
537.175 - config("local1",wombats("wchief","ww1","ww2")),
537.176 - // top1//local2
537.177 - config("local2",wombats("wchief","ww4","ww5","ww6"),
537.178 - // top1//local2//local3
537.179 - config("local3",wombats("wchief","www1","www2")),
537.180 - // top1//local2//rmi1
537.181 - config("rmi1",url(protocol),wombats("wchief","www3","www4","www5"))),
537.182 - // top1//rmi2
537.183 - config("rmi2",url(protocol),wombats("wchief","ww7","ww8","ww9"),
537.184 - // top1//rmi2//local4
537.185 - config("local4",wombats("wchief","www6","www7")),
537.186 - // top1//rmi2//rmi3
537.187 - config("rmi3",url(protocol),wombats("wchief","www3","www4","www5"),
537.188 - // top1//rmi2//rmi3//local5
537.189 - config("local5",wombats("wchief","wwww1"))))),
537.190 - // Top level namespace "top2" (local)
537.191 - config("top2",wombats("wchief","w21","w22","w23"),
537.192 - // top2//local21
537.193 - config("local21",wombats("wchief","ww21","ww22")),
537.194 - // top2//rmi22
537.195 - config("rmi22",url(protocol),wombats("wchief","ww27","ww28","ww29"),
537.196 - // top2//rmi22//local24
537.197 - config("local24",wombats("wchief","www26","www27")),
537.198 - // top2//rmi22//rmi23
537.199 - config("rmi23",url(protocol),wombats("wchief","www23","www24","www25"),
537.200 - // top2//rmi22//rmi23//local25
537.201 - config("local25",wombats("wchief","wwww21"))))),
537.202 - // Top level namespace "top3" (remote)
537.203 - config("top3",url(protocol),wombats("wchief","w31","w32","w33"),
537.204 - // top3//local31
537.205 - config("local31",wombats("wchief","ww31","ww32")),
537.206 - // top3//rmi32
537.207 - config("rmi32",url(protocol),wombats("wchief","ww37","ww38","ww39"),
537.208 - // top3//rmi32//local34
537.209 - config("local34",wombats("wchief","www36","www37")),
537.210 - // top3//rmi32//rmi33
537.211 - config("rmi33",url(protocol),wombats("wchief","www33","www34","www35"),
537.212 - // top3//rmi32//local35
537.213 - config("local35",wombats("wchief","wwww31"))))),
537.214 - };
537.215 - return config;
537.216 - }
537.217 -
537.218 - /**
537.219 - * Close all connector servers in the list.
537.220 - * @param cslist List of connector servers to close.
537.221 - */
537.222 - public static void closeAll(List<JMXConnectorServer> cslist) {
537.223 - for (JMXConnectorServer cs : cslist) {
537.224 - try {
537.225 - cs.stop();
537.226 - } catch (Exception xx) {
537.227 - System.err.println("Failed to stop connector: " + xx);
537.228 - }
537.229 - }
537.230 - }
537.231 -
537.232 - public static class MBeanServerConfigCreator {
537.233 - public MBeanServer createMBeanServerFor(NamespaceConfig config) {
537.234 - return MBeanServerFactory.newMBeanServer();
537.235 - }
537.236 - }
537.237 -
537.238 - /**
537.239 - * Load the given namespace configuration inside the given MBeanServer.
537.240 - * Return a list of connector servers created in the process.
537.241 - * @param server The MBeanServer in which the namespaces must
537.242 - * be created.
537.243 - * @param namespaces The list of namespaces to create.
537.244 - * @return a list of started connector servers.
537.245 - * @throws java.lang.Exception failed to create the specified namespaces.
537.246 - */
537.247 - public static List<JMXConnectorServer> load(MBeanServer server,
537.248 - MBeanServerConfigCreator factory,
537.249 - NamespaceConfig... namespaces) throws Exception {
537.250 - final List<JMXConnectorServer> cslist =
537.251 - new ArrayList<JMXConnectorServer>();
537.252 - try {
537.253 - final ObjectName creator =
537.254 - new ObjectName("jmx.creator:type=JMXNamespaceCreator");
537.255 - if (System.getProperty("jmx.wait")!=null
537.256 - && !server.isRegistered(creator)) {
537.257 - server.registerMBean(new JMXNamespaceCreator(),creator);
537.258 - }
537.259 - for (NamespaceConfig cfg : namespaces) {
537.260 - final MBeanServer srv = factory.createMBeanServerFor(cfg);
537.261 - if (System.getProperty("jmx.wait")!=null
537.262 - && !srv.isRegistered(creator)) {
537.263 - srv.registerMBean(new JMXNamespaceCreator(),creator);
537.264 - }
537.265 - if (cfg.wombats != null) {
537.266 - for (String w : cfg.wombats) {
537.267 - final ObjectName n =
537.268 - new ObjectName("wombat:type=Wombat,name=" + w);
537.269 - final WombatMBean ww = new Wombat();
537.270 - srv.registerMBean(ww, n);
537.271 - }
537.272 - }
537.273 - if (cfg.children != null) {
537.274 - cslist.addAll(load(srv, factory, cfg.children));
537.275 - }
537.276 - JMXNamespace nm;
537.277 - if (cfg.jmxurl == null) {
537.278 - nm = new JMXNamespace(srv);
537.279 - } else {
537.280 - JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(new JMXServiceURL(cfg.jmxurl),
537.281 - null, srv);
537.282 - srv.registerMBean(cs,
537.283 - new ObjectName("jmx.remote:type=JMXConnectorServer"));
537.284 - cs.start();
537.285 - cslist.add(cs);
537.286 - nm = JMXRemoteNamespace.
537.287 - newJMXRemoteNamespace(cs.getAddress(),
537.288 - null);
537.289 - }
537.290 - server.registerMBean(nm,
537.291 - JMXNamespaces.getNamespaceObjectName(cfg.name));
537.292 - if (nm instanceof JMXRemoteNamespace) {
537.293 - server.invoke(
537.294 - JMXNamespaces.getNamespaceObjectName(cfg.name),
537.295 - "connect", null, null);
537.296 - }
537.297 - }
537.298 - } catch (Exception x) {
537.299 - closeAll(cslist);
537.300 - throw x;
537.301 - }
537.302 - return cslist;
537.303 - }
537.304 -
537.305 - /**
537.306 - * Add an entry {@code <path,NamespaceConfig>} in the map for the given
537.307 - * namespace and its subnamespaces.
537.308 - * @param map A {@code Map<path,NamespaceConfig>}.
537.309 - * @param parent The path of the parent workspace.
537.310 - * @param cfg The NamespaceConfig hierarchy to index in the map.
537.311 - */
537.312 - public static void fillMap(Map<String,NamespaceConfig> map, String parent,
537.313 - NamespaceConfig cfg) {
537.314 -
537.315 - final String where;
537.316 - if (parent == null || parent.equals(""))
537.317 - where=cfg.name;
537.318 - else
537.319 - where=parent+JMXNamespaces.NAMESPACE_SEPARATOR+cfg.name;
537.320 - map.put(where,cfg);
537.321 - if (cfg.children==null) return;
537.322 - for(NamespaceConfig child:cfg.children) {
537.323 - fillMap(map,where,child);
537.324 - }
537.325 - }
537.326 -
537.327 - /**
537.328 - * Compare a list of namespace names obtained from JMXNamespaceView.list()
537.329 - * with the expected clildren list of the corresponding NamespaceConfig.
537.330 - * @param list A list of namespace names
537.331 - * @param children A list of NamespaceConfig correspondng to expected
537.332 - * namespace.
537.333 - * @param fail If true and the comparison yields false, throws an
537.334 - * exception instead of simply returning false.
537.335 - * @return true if OK, false if NOK.
537.336 - */
537.337 - private static boolean compare(String[] list, NamespaceConfig[] children,
537.338 - boolean fail) {
537.339 - final List<String> found = new ArrayList<String>(Arrays.asList(list));
537.340 - if (found.contains(ClientContext.NAMESPACE))
537.341 - found.remove(ClientContext.NAMESPACE);
537.342 -
537.343 - if (children == null && found.size()==0) return true;
537.344 - if (children == null && fail == false) return false;
537.345 - if (children == null) throw new RuntimeException(
537.346 - "No child expected. Found "+Arrays.toString(list));
537.347 - final Set<String> names = new HashSet<String>();
537.348 - for (NamespaceConfig cfg : children) {
537.349 - names.add(cfg.name);
537.350 - if (found.contains(cfg.name)) continue;
537.351 - if (!fail) return false;
537.352 - throw new RuntimeException(cfg.name+" not found in "+
537.353 - found);
537.354 - }
537.355 - found.removeAll(names);
537.356 - if (found.size()==0) return true;
537.357 - if (fail==false) return false;
537.358 - throw new RuntimeException("found additional namespaces: "+
537.359 - found);
537.360 - }
537.361 -
537.362 - /**
537.363 - * Compares the result of queryNames(null,null) with a set of expected
537.364 - * wombats.
537.365 - * @param where The path of the namespace that was queried.
537.366 - * @param list The set of ObjectNames found.
537.367 - * @param wombats The expected list of wombats.
537.368 - * @param fail If true and the comparison yields false, throws an
537.369 - * exception instead of simply returning false.
537.370 - * @return true if OK, false if NOK.
537.371 - * @throws java.lang.Exception something went wrong.
537.372 - */
537.373 - private static boolean compare(String where,
537.374 - Set<ObjectName>list, String[] wombats,
537.375 - boolean fail) throws Exception {
537.376 - final Set<ObjectName> found = new HashSet<ObjectName>();
537.377 - final Set<ObjectName> expected = new HashSet<ObjectName>();
537.378 - for (ObjectName n : list) {
537.379 - if ("Wombat".equals(n.getKeyProperty("type")))
537.380 - found.add(n);
537.381 - }
537.382 - for(String w : wombats) {
537.383 - final ObjectName n =
537.384 - new ObjectName("wombat:type=Wombat,name=" + w);
537.385 - expected.add(n);
537.386 - if (found.contains(n)) continue;
537.387 - if (fail == false) return false;
537.388 - throw new RuntimeException(where+
537.389 - ": Wombat "+w+" not found in "+found);
537.390 - }
537.391 - found.removeAll(expected);
537.392 - if (found.size()==0) {
537.393 - System.out.println(where+": found all expected: "+expected);
537.394 - return true;
537.395 - }
537.396 - if (fail==false) return false;
537.397 - throw new RuntimeException(where+": found additional MBeans: "+
537.398 - found);
537.399 - }
537.400 -
537.401 - /**
537.402 - * A generic test to test JMXNamespaceView over a namespace configuration.
537.403 - * @param server The MBeanServer in which to load the namespace
537.404 - * config.
537.405 - * @param namespaces The namespace config to run the test over...
537.406 - * @throws java.lang.Exception
537.407 - */
537.408 - public static void doTest(MBeanServer server, NamespaceConfig... namespaces)
537.409 - throws Exception {
537.410 - List<JMXConnectorServer> cslist = load(server,
537.411 - new MBeanServerConfigCreator(), namespaces);
537.412 - Map<String,NamespaceConfig> inputMap =
537.413 - new HashMap<String,NamespaceConfig>();
537.414 -
537.415 - for (NamespaceConfig cfg : namespaces) {
537.416 - fillMap(inputMap,"",cfg);
537.417 - }
537.418 - try {
537.419 - final JMXNamespaceView root = new JMXNamespaceView(server);
537.420 - List<JMXNamespaceView> vlist = new ArrayList<JMXNamespaceView>();
537.421 - vlist.add(root);
537.422 -
537.423 - while (!vlist.isEmpty()) {
537.424 - JMXNamespaceView v = vlist.remove(0);
537.425 - final String where = v.isRoot()?"root":v.where();
537.426 - System.out.println(where+": "+
537.427 - v.getMBeanServerConnection().queryNames(null,null));
537.428 - for (String ns : v.list()) {
537.429 - final JMXNamespaceView down = v.down(ns);
537.430 - vlist.add(down);
537.431 - if (!down.where().equals(v.isRoot()?ns:where+
537.432 - JMXNamespaces.NAMESPACE_SEPARATOR+ns)) {
537.433 - throw new RuntimeException("path of "+down.where()+
537.434 - " should be "+(v.isRoot()?ns:where+
537.435 - JMXNamespaces.NAMESPACE_SEPARATOR+ns));
537.436 - }
537.437 - if (down.up().equals(v)) continue;
537.438 - throw new RuntimeException("parent of "+down.where()+
537.439 - " should be "+where);
537.440 - }
537.441 - final NamespaceConfig[] children;
537.442 - final NamespaceConfig cfg;
537.443 - if (v.isRoot()) {
537.444 - children=namespaces;
537.445 - cfg = null;
537.446 - } else {
537.447 - cfg = inputMap.get(where);
537.448 - children = cfg==null?null:cfg.children;
537.449 - }
537.450 - compare(v.list(),children,true);
537.451 - if (!v.isRoot()) {
537.452 - if (where.endsWith(ClientContext.NAMESPACE)) {
537.453 - System.out.println(where+": skipping queryNames analysis");
537.454 - continue;
537.455 - }
537.456 - //System.out.println(where+": cfg is: "+cfg);
537.457 - compare(where,v.getMBeanServerConnection().
537.458 - queryNames(null, null),cfg.wombats,true);
537.459 - }
537.460 - }
537.461 -
537.462 - exportAndWaitIfNeeded(server);
537.463 - } finally {
537.464 - closeAll(cslist);
537.465 - }
537.466 - }
537.467 -
537.468 - public static interface JMXNamespaceCreatorMBean {
537.469 - public ObjectInstance createLocalNamespace(String namespace)
537.470 - throws JMException ;
537.471 - public void removeLocalNamespace(String namespace)
537.472 - throws JMException;
537.473 - }
537.474 -
537.475 - public static class JMXNamespaceCreator
537.476 - implements MBeanRegistration,
537.477 - JMXNamespaceCreatorMBean {
537.478 -
537.479 - private volatile MBeanServer mbeanServer;
537.480 -
537.481 - public ObjectInstance createLocalNamespace(String namespace)
537.482 - throws JMException {
537.483 - return mbeanServer.registerMBean(
537.484 - new JMXNamespace(MBeanServerFactory.newMBeanServer()),
537.485 - JMXNamespaces.getNamespaceObjectName(namespace));
537.486 - }
537.487 -
537.488 - public void removeLocalNamespace(String namespace)
537.489 - throws JMException {
537.490 - mbeanServer.unregisterMBean(
537.491 - JMXNamespaces.getNamespaceObjectName(namespace));
537.492 - }
537.493 -
537.494 - public ObjectName preRegister(MBeanServer server, ObjectName name)
537.495 - throws Exception {
537.496 - mbeanServer = server;
537.497 - return name;
537.498 - }
537.499 -
537.500 - public void postRegister(Boolean registrationDone) {
537.501 - }
537.502 -
537.503 - public void preDeregister() throws Exception {
537.504 - }
537.505 -
537.506 - public void postDeregister() {
537.507 - }
537.508 -
537.509 - }
537.510 -
537.511 - public static void exportAndWaitIfNeeded(MBeanServer server)
537.512 - throws Exception {
537.513 - if (System.getProperty("jmx.wait")!=null) {
537.514 - final int port = getPortFor("rmi");
537.515 - LocateRegistry.createRegistry(port);
537.516 - final JMXServiceURL url =
537.517 - new JMXServiceURL("rmi",null,port,
537.518 - "/jndi/rmi://localhost:"+port+"/jmxrmi");
537.519 - final JMXConnectorServer cs =
537.520 - JMXConnectorServerFactory.
537.521 - newJMXConnectorServer(url, null, server);
537.522 - cs.start();
537.523 - try {
537.524 - System.out.println("RMI Server waiting at: "+cs.getAddress());
537.525 - System.in.read();
537.526 - } finally {
537.527 - cs.stop();
537.528 - }
537.529 - }
537.530 - }
537.531 -
537.532 - public static int getPortFor(String protocol) throws Exception {
537.533 - final int aport =
537.534 - Integer.valueOf(System.getProperty("jmx."+protocol+".port","0"));
537.535 - if (aport > 0) return aport;
537.536 - final ServerSocket s = new ServerSocket(0);
537.537 - try {
537.538 - final int port = s.getLocalPort();
537.539 - return port;
537.540 - } finally {
537.541 - s.close();
537.542 - }
537.543 - }
537.544 -
537.545 - public static void main(String[] args) throws Exception {
537.546 - doTest(ManagementFactory.getPlatformMBeanServer(),makeConfig("rmi"));
537.547 - }
537.548 -
537.549 -}
538.1 --- a/test/javax/management/namespace/JMXNamespacesTest.java Mon Nov 23 10:04:47 2009 +0000
538.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
538.3 @@ -1,648 +0,0 @@
538.4 -/*
538.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
538.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
538.7 - *
538.8 - * This code is free software; you can redistribute it and/or modify it
538.9 - * under the terms of the GNU General Public License version 2 only, as
538.10 - * published by the Free Software Foundation.
538.11 - *
538.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
538.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
538.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
538.15 - * version 2 for more details (a copy is included in the LICENSE file that
538.16 - * accompanied this code).
538.17 - *
538.18 - * You should have received a copy of the GNU General Public License version
538.19 - * 2 along with this work; if not, write to the Free Software Foundation,
538.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
538.21 - *
538.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
538.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
538.24 - * have any questions.
538.25 - */
538.26 -/*
538.27 - * @test JMXNamespacesTest.java
538.28 - * @summary Test the static method that rewrite ObjectNames in JMXNamespacesTest
538.29 - * @author Daniel Fuchs
538.30 - * @bug 5072476
538.31 - * @run clean JMXNamespacesTest
538.32 - * @compile -XDignore.symbol.file=true JMXNamespacesTest.java
538.33 - * @run main JMXNamespacesTest
538.34 - */
538.35 -
538.36 -import com.sun.jmx.namespace.ObjectNameRouter;
538.37 -import java.io.Serializable;
538.38 -import java.util.Arrays;
538.39 -import java.util.logging.Logger;
538.40 -import javax.management.MalformedObjectNameException;
538.41 -import javax.management.ObjectName;
538.42 -import javax.management.namespace.JMXNamespaces;
538.43 -
538.44 -/**
538.45 - * Class JMXNamespacesTest
538.46 - * @author Sun Microsystems, 2005 - All rights reserved.
538.47 - */
538.48 -public class JMXNamespacesTest {
538.49 -
538.50 - /**
538.51 - * A logger for this class.
538.52 - **/
538.53 - private static final Logger LOG =
538.54 - Logger.getLogger(JMXNamespacesTest.class.getName());
538.55 -
538.56 - /** Creates a new instance of JMXNamespacesTest */
538.57 - public JMXNamespacesTest() {
538.58 - }
538.59 -
538.60 - public static class CustomObject implements Serializable {
538.61 - ObjectName toto;
538.62 - String titi;
538.63 - CustomObject(String toto, String titi) {
538.64 - try {
538.65 - this.toto = new ObjectName(toto);
538.66 - } catch (MalformedObjectNameException m) {
538.67 - throw new IllegalArgumentException(m);
538.68 - }
538.69 - this.titi = titi;
538.70 - }
538.71 - private Object[] data() {
538.72 - return new Object[] {toto, titi};
538.73 - }
538.74 - @Override
538.75 - public boolean equals(Object other) {
538.76 - if (! (other instanceof CustomObject)) return false;
538.77 - return Arrays.deepEquals(data(),((CustomObject)other).data());
538.78 - }
538.79 - @Override
538.80 - public int hashCode() {
538.81 - return Arrays.deepHashCode(data());
538.82 - }
538.83 - }
538.84 -
538.85 - public static CustomObject obj(String toto, String titi) {
538.86 - return new CustomObject(toto,titi);
538.87 - }
538.88 -
538.89 - private static String failure;
538.90 -
538.91 - public static void testDeepRewrite() throws Exception {
538.92 - failure = null;
538.93 - String s1 = "x//y//d:k=v";
538.94 - String s2 = "v//w//x//y//d:k=v";
538.95 - String p1 = "v//w";
538.96 - String p3 = "a//b";
538.97 -
538.98 - System.out.println("inserting "+p1);
538.99 - final CustomObject foo1 =
538.100 - JMXNamespaces.deepReplaceHeadNamespace(obj(s1,s1),"",p1);
538.101 - assertEquals(foo1.toto.toString(),p1+"//"+s1);
538.102 - assertEquals(foo1.titi,s1);
538.103 -
538.104 - System.out.println("removing "+p1);
538.105 - final CustomObject foo2 =
538.106 - JMXNamespaces.deepReplaceHeadNamespace(obj(s2,s2),p1,"");
538.107 - assertEquals(foo2.toto.toString(),s1);
538.108 - assertEquals(foo2.titi,s2);
538.109 -
538.110 - System.out.println("removing "+p1);
538.111 - final CustomObject foo3 =
538.112 - JMXNamespaces.deepReplaceHeadNamespace(obj(p1+"//"+s2,s2),p1,"");
538.113 - assertEquals(foo3.toto.toString(),s2);
538.114 - assertEquals(foo3.titi,s2);
538.115 -
538.116 - System.out.println("replacing "+p1+" with "+p3);
538.117 - final CustomObject foo4 =
538.118 - JMXNamespaces.deepReplaceHeadNamespace(obj(s2,s2),p1,p3);
538.119 - assertEquals(foo4.toto.toString(),p3+"//"+s1);
538.120 - assertEquals(foo4.titi,s2);
538.121 -
538.122 - System.out.println("replacing "+p1+" with "+p1);
538.123 - final CustomObject foo5 =
538.124 - JMXNamespaces.deepReplaceHeadNamespace(obj(s2,s2),p1,p1);
538.125 - assertEquals(foo5.toto.toString(),s2);
538.126 - assertEquals(foo5.titi,s2);
538.127 -
538.128 - System.out.println("removing x//y in "+s2);
538.129 - try {
538.130 - final CustomObject foo7 =
538.131 - JMXNamespaces.deepReplaceHeadNamespace(obj(s2,s2),"x//y","");
538.132 - failed("Remove x//y in "+s2+" should have failed!");
538.133 - } catch (IllegalArgumentException x) {
538.134 - System.out.println("Received expected exception: "+x);
538.135 - }
538.136 -
538.137 - System.out.println("replacing x//y with "+p3+" in "+s2);
538.138 - try {
538.139 - final CustomObject foo7 =
538.140 - JMXNamespaces.deepReplaceHeadNamespace(obj(s2,s2),"x//y",p3);
538.141 - failed("Replace x//y in "+s2+" should have failed!");
538.142 - } catch (IllegalArgumentException x) {
538.143 - System.out.println("Received expected exception: "+x);
538.144 - }
538.145 -
538.146 - if (failure != null) throw new Exception(failure);
538.147 - }
538.148 -
538.149 - private static String[][] wildcards = {
538.150 - { "", "*:*" },
538.151 - { "//", "//*:*" },
538.152 - { "foo", "foo//*:*" },
538.153 - { "//foo", "//foo//*:*" },
538.154 - { "////foo", "//foo//*:*" },
538.155 - { "foo//", "foo//*:*" },
538.156 - { "foo////", "foo//*:*" },
538.157 - { "//foo//", "//foo//*:*" },
538.158 - { "////foo//", "//foo//*:*" },
538.159 - { "////foo////", "//foo//*:*" },
538.160 - { "foo//bar", "foo//bar//*:*" },
538.161 - { "//foo//bar", "//foo//bar//*:*" },
538.162 - { "////foo//bar", "//foo//bar//*:*" },
538.163 - { "foo//bar//", "foo//bar//*:*" },
538.164 - { "foo//bar////", "foo//bar//*:*" },
538.165 - { "//foo//bar//", "//foo//bar//*:*" },
538.166 - { "////foo//bar//", "//foo//bar//*:*" },
538.167 - { "////foo//bar////", "//foo//bar//*:*" },
538.168 - { "foo////bar", "foo//bar//*:*" },
538.169 - { "//foo////bar", "//foo//bar//*:*" },
538.170 - { "////foo////bar", "//foo//bar//*:*" },
538.171 - { "foo////bar//", "foo//bar//*:*" },
538.172 - { "foo////bar////", "foo//bar//*:*" },
538.173 - { "//foo////bar//", "//foo//bar//*:*" },
538.174 - { "////foo////bar//", "//foo//bar//*:*" },
538.175 - { "////foo////bar////", "//foo//bar//*:*" },
538.176 - { "fo/o", "fo/o//*:*" },
538.177 - { "//f/oo", "//f/oo//*:*" },
538.178 - { "////f/o/o", "//f/o/o//*:*" },
538.179 - { "fo/o//", "fo/o//*:*" },
538.180 - { "f/oo////", "f/oo//*:*" },
538.181 - { "//fo/o//", "//fo/o//*:*" },
538.182 - { "////f/oo//", "//f/oo//*:*" },
538.183 - { "////f/o/o////", "//f/o/o//*:*" },
538.184 - { "foo//b/a/r", "foo//b/a/r//*:*" },
538.185 - { "//fo/o//bar", "//fo/o//bar//*:*" },
538.186 - { "////foo//b/ar", "//foo//b/ar//*:*" },
538.187 - { "foo//ba/r//", "foo//ba/r//*:*" },
538.188 - { "f/oo//bar////", "f/oo//bar//*:*" },
538.189 - { "//f/o/o//bar//", "//f/o/o//bar//*:*" },
538.190 - { "////foo//b/a/r//", "//foo//b/a/r//*:*" },
538.191 - { "////f/o/o//b/a/r////", "//f/o/o//b/a/r//*:*" },
538.192 - { "foo////ba/r", "foo//ba/r//*:*" },
538.193 - { "//foo////b/ar", "//foo//b/ar//*:*" },
538.194 - { "////f/oo////bar", "//f/oo//bar//*:*" },
538.195 - { "fo/o////bar//", "fo/o//bar//*:*" },
538.196 - { "foo////ba/r////", "foo//ba/r//*:*" },
538.197 - { "//fo/o////ba/r//", "//fo/o//ba/r//*:*" },
538.198 - { "////f/oo////b/ar//", "//f/oo//b/ar//*:*" },
538.199 - { "////f/o/o////b/a/r////", "//f/o/o//b/a/r//*:*" },
538.200 - };
538.201 - private final static String[] badguys = {
538.202 - null,
538.203 - "/", "/*:*",
538.204 - "///", "///*:*" ,
538.205 - "/foo", "/foo//*:*",
538.206 - "//foo/", "//foo///*:*" ,
538.207 - "/////foo", "///foo//*:*",
538.208 - "/foo//", "/foo//*:*",
538.209 - "foo/////", "foo///*:*",
538.210 - "///foo//", "///foo//*:*",
538.211 - "////foo///", "//foo///*:*" ,
538.212 - "/////foo/////", "///foo///*:*",
538.213 - "/foo//bar", "/foo//bar//*:*",
538.214 - "//foo///bar", "//foo///bar//*:*",
538.215 - "/////foo////bar/", "///foo//bar///*:*",
538.216 - "foo///bar//", "foo//bar///*:*",
538.217 - "foo//bar/////", "foo///bar//*:*",
538.218 - "///foo//bar//", "//foo///bar//*:*" ,
538.219 - };
538.220 - public static void testWildcard() throws Exception {
538.221 - int i = 0;
538.222 - for (String[] pair : wildcards) {
538.223 - i++;
538.224 - final String msg = "testWildcard[good,"+i+"] "+Arrays.asList(pair)+": ";
538.225 - assertEquals(msg, new ObjectName(pair[1]),
538.226 - JMXNamespaces.getWildcardFor(pair[0]));
538.227 - }
538.228 - i=0;
538.229 - for (String bad : badguys) {
538.230 - i++;
538.231 - try {
538.232 - JMXNamespaces.getWildcardFor(bad);
538.233 - failed("testWildcard[bad,"+i+"] "+bad+" incorrectly accepted. " +
538.234 - "IllegalArgumentException was expected");
538.235 - } catch (IllegalArgumentException x) {
538.236 - // OK
538.237 - }
538.238 - }
538.239 - if (failure != null) throw new Exception(failure);
538.240 - }
538.241 -
538.242 - private static String[][] goodinsert = {
538.243 - {"","d:k=v","d:k=v"},
538.244 - {"","//d:k=v","//d:k=v"},
538.245 - {"//","d:k=v","//d:k=v"},
538.246 - {"//","//d:k=v","//d:k=v"},
538.247 - {"//","a//d:k=v","//a//d:k=v"},
538.248 - {"//","//a//d:k=v","//a//d:k=v"},
538.249 - {"//","////a////d:k=v","//a//d:k=v"},
538.250 - {"//b","////a////d:k=v","//b//a//d:k=v"},
538.251 - {"b","////a////d:k=v","b//a//d:k=v"},
538.252 - {"b","d:k=v","b//d:k=v"},
538.253 - {"b//","d:k=v","b//d:k=v"},
538.254 - {"//b//","d:k=v","//b//d:k=v"},
538.255 - {"//b","////a////d:k=v","//b//a//d:k=v"},
538.256 - {"b//c","////a////d:k=v","b//c//a//d:k=v"},
538.257 - {"b//c","d:k=v","b//c//d:k=v"},
538.258 - {"b//c//","d:k=v","b//c//d:k=v"},
538.259 - {"//b//c//","d:k=v","//b//c//d:k=v"},
538.260 - {"","/d:k=v","/d:k=v"},
538.261 - {"","///d:k=v","///d:k=v"},
538.262 - {"//","/d:k=v","///d:k=v"},
538.263 - {"//","///d:k=v","///d:k=v"},
538.264 - {"//","a///d:k=v","//a///d:k=v"},
538.265 - {"//","//a///d:k=v","//a///d:k=v"},
538.266 - {"//","////a////d/:k=v","//a//d/:k=v"},
538.267 - {"//b","////a/////d:k=v","//b//a///d:k=v"},
538.268 - {"b","////a////d/:k=v","b//a//d/:k=v"},
538.269 - {"b","/d:k=v","b///d:k=v"},
538.270 - {"b//","/d:k=v","b///d:k=v"},
538.271 - {"//b//","/d:k=v","//b///d:k=v"},
538.272 - {"//b","////a/////d:k=v","//b//a///d:k=v"},
538.273 - {"b//c","////a/////d:k=v","b//c//a///d:k=v"},
538.274 - {"b//c","/d:k=v","b//c///d:k=v"},
538.275 - {"b//c//","/d:k=v","b//c///d:k=v"},
538.276 - {"//b//c//","d/:k=v","//b//c//d/:k=v"},
538.277 - };
538.278 -
538.279 - private static String[][] badinsert = {
538.280 - {"/","d:k=v"},
538.281 - {"/","//d:k=v"},
538.282 - {"///","d:k=v"},
538.283 - {"///","//d:k=v"},
538.284 - {"///","/a//d:k=v"},
538.285 - {"///","///a//d:k=v"},
538.286 - {"///","/////a////d:k=v"},
538.287 - {"//b","/////a////d:k=v"},
538.288 - {"b/","////a////d:k=v"},
538.289 - {"b/","d:k=v"},
538.290 - {"b///","d:k=v"},
538.291 - {"//b///","d:k=v"},
538.292 - {"//b/","////a////d:k=v"},
538.293 - {"b///c","////a////d:k=v"},
538.294 - {"b//c/","d:k=v"},
538.295 - {"b///c//","d:k=v"},
538.296 - {"//b///c//","d:k=v"},
538.297 -
538.298 - };
538.299 -
538.300 - public static void testInsertPath() throws Exception {
538.301 - int i = 0;
538.302 - for (String[] pair : goodinsert) {
538.303 - i++;
538.304 - final String msg = "testInsertPath[good,"+i+"] "+Arrays.asList(pair)+": ";
538.305 - assertEquals(msg,new ObjectName(pair[2]),
538.306 - JMXNamespaces.insertPath(pair[0],
538.307 - new ObjectName(pair[1])));
538.308 - }
538.309 - i=0;
538.310 - for (String[] bad : badinsert) {
538.311 - i++;
538.312 - try {
538.313 - JMXNamespaces.insertPath(bad[0],
538.314 - new ObjectName(bad[1]));
538.315 - failed("testInsertPath[bad,"+i+"] "+
538.316 - Arrays.asList(bad)+" incorrectly accepted. " +
538.317 - "IllegalArgumentException was expected");
538.318 - } catch (IllegalArgumentException x) {
538.319 - // OK
538.320 - }
538.321 - }
538.322 - if (failure != null) throw new Exception(failure);
538.323 - }
538.324 -
538.325 - private static String[][] testpath = {
538.326 - {"/a/a/:k=v",""},
538.327 - {"/:k=v",""},
538.328 - {"bli:k=v",""},
538.329 - {"///a/a/:k=v",""},
538.330 - {"///:k=v",""},
538.331 - {"//bli:k=v",""},
538.332 - {"/////a/a/:k=v",""},
538.333 - {"/////:k=v",""},
538.334 - {"////bli:k=v",""},
538.335 - {"y///a/a/:k=v","y"},
538.336 - {"y///:k=v","y"},
538.337 - {"y//bli:k=v","y"},
538.338 - {"y/////a/a/:k=v","y"},
538.339 - {"y/////:k=v","y"},
538.340 - {"y////bli:k=v","y"},
538.341 - {"//y///a/a/:k=v","y"},
538.342 - {"//y///:k=v","y"},
538.343 - {"//y//bli:k=v","y"},
538.344 - {"//y/////a/a/:k=v","y"},
538.345 - {"//y/////:k=v","y"},
538.346 - {"//y////bli:k=v","y"},
538.347 - {"////y///a/a/:k=v","y"},
538.348 - {"////y///:k=v","y"},
538.349 - {"////y//bli:k=v","y"},
538.350 - {"////y/////a/a/:k=v","y"},
538.351 - {"////y/////:k=v","y"},
538.352 - {"////y////bli:k=v","y"},
538.353 -
538.354 - {"z//y///a/a/:k=v","z//y"},
538.355 - {"z//y///:k=v","z//y"},
538.356 - {"z//y//bli:k=v","z//y"},
538.357 - {"z//y/////a/a/:k=v","z//y"},
538.358 - {"z//y/////:k=v","z//y"},
538.359 - {"z//y////bli:k=v","z//y"},
538.360 - {"//z//y///a/a/:k=v","z//y"},
538.361 - {"//z//y///:k=v","z//y"},
538.362 - {"//z//y//bli:k=v","z//y"},
538.363 - {"//z//y/////a/a/:k=v","z//y"},
538.364 - {"//z//y/////:k=v","z//y"},
538.365 - {"//z//y////bli:k=v","z//y"},
538.366 - {"z////y///a/a/:k=v","z//y"},
538.367 - {"z////y///:k=v","z//y"},
538.368 - {"z////y//bli:k=v","z//y"},
538.369 - {"z////y/////a/a/:k=v","z//y"},
538.370 - {"z////y/////:k=v","z//y"},
538.371 - {"z////y////bli:k=v","z//y"},
538.372 - {"//z////y///a/a/:k=v","z//y"},
538.373 - {"//z////y///:k=v","z//y"},
538.374 - {"//z////y//bli:k=v","z//y"},
538.375 - {"//z////y/////a/a/:k=v","z//y"},
538.376 - {"//z////y/////:k=v","z//y"},
538.377 - {"//z////y////bli:k=v","z//y"},
538.378 - {"////z////y///a/a/:k=v","z//y"},
538.379 - {"////z////y///:k=v","z//y"},
538.380 - {"////z////y//bli:k=v","z//y"},
538.381 - {"////z////y/////a/a/:k=v","z//y"},
538.382 - {"////z////y/////:k=v","z//y"},
538.383 - {"////z////y////bli:k=v","z//y"},
538.384 -
538.385 - };
538.386 -
538.387 - public static void testGetNormalizedPath() throws Exception {
538.388 - int i = 0;
538.389 - for (String[] pair : testpath) {
538.390 - i++;
538.391 - final String msg = "testGetNormalizedPath["+i+"] "+Arrays.asList(pair)+": ";
538.392 - assertEquals(msg,pair[1],
538.393 - JMXNamespaces.getContainingNamespace(new ObjectName(pair[0])));
538.394 - }
538.395 - if (failure != null) throw new Exception(failure);
538.396 - }
538.397 -
538.398 - private static String[][] testdomain = {
538.399 - {"/a/a/","/a/a/"},
538.400 - {"/","/"},
538.401 - {"bli","bli"},
538.402 - {"///a/a/","///a/a/"},
538.403 - {"///","///"},
538.404 - {"//bli","//bli"},
538.405 - {"/////a/a/","///a/a/"},
538.406 - {"/////","///"},
538.407 - {"////bli","//bli"},
538.408 - {"y///a/a/","y///a/a/"},
538.409 - {"y///","y///"},
538.410 - {"y//bli","y//bli"},
538.411 - {"y/////a/a/","y///a/a/"},
538.412 - {"y/////","y///"},
538.413 - {"y////bli","y//bli"},
538.414 - {"//y///a/a/","//y///a/a/"},
538.415 - {"//y///","//y///"},
538.416 - {"//y//bli","//y//bli"},
538.417 - {"//y/////a/a/","//y///a/a/"},
538.418 - {"//y/////","//y///"},
538.419 - {"//y////bli","//y//bli"},
538.420 - {"////y///a/a/","//y///a/a/"},
538.421 - {"////y///","//y///"},
538.422 - {"////y//bli","//y//bli"},
538.423 - {"////y/////a/a/","//y///a/a/"},
538.424 - {"////y/////","//y///"},
538.425 - {"////y////bli","//y//bli"},
538.426 -
538.427 - {"z//y///a/a/","z//y///a/a/"},
538.428 - {"z//y///","z//y///"},
538.429 - {"z//y//bli","z//y//bli"},
538.430 - {"z//y/////a/a/","z//y///a/a/"},
538.431 - {"z//y/////","z//y///"},
538.432 - {"z//y////bli","z//y//bli"},
538.433 - {"//z//y///a/a/","//z//y///a/a/"},
538.434 - {"//z//y///","//z//y///"},
538.435 - {"//z//y//bli","//z//y//bli"},
538.436 - {"//z//y/////a/a/","//z//y///a/a/"},
538.437 - {"//z//y/////","//z//y///"},
538.438 - {"//z//y////bli","//z//y//bli"},
538.439 - {"z////y///a/a/","z//y///a/a/"},
538.440 - {"z////y///","z//y///"},
538.441 - {"z////y//bli","z//y//bli"},
538.442 - {"z////y/////a/a/","z//y///a/a/"},
538.443 - {"z////y/////","z//y///"},
538.444 - {"z////y////bli","z//y//bli"},
538.445 - {"//z////y///a/a/","//z//y///a/a/"},
538.446 - {"//z////y///","//z//y///"},
538.447 - {"//z////y//bli","//z//y//bli"},
538.448 - {"//z////y/////a/a/","//z//y///a/a/"},
538.449 - {"//z////y/////","//z//y///"},
538.450 - {"//z////y////bli","//z//y//bli"},
538.451 - {"////z////y///a/a/","//z//y///a/a/"},
538.452 - {"////z////y///","//z//y///"},
538.453 - {"////z////y//bli","//z//y//bli"},
538.454 - {"////z////y/////a/a/","//z//y///a/a/"},
538.455 - {"////z////y/////","//z//y///"},
538.456 - {"////z////y////bli","//z//y//bli"},
538.457 -
538.458 - {"bli//","bli//"},
538.459 - {"//bli//","//bli//"},
538.460 - {"////bli//","//bli//"},
538.461 - {"y////","y//"},
538.462 - {"y//bli//","y//bli//"},
538.463 - {"y////","y//"},
538.464 - {"y////bli//","y//bli//"},
538.465 - {"//y////","//y//"},
538.466 - {"//y//bli//","//y//bli//"},
538.467 - {"//y//////","//y//"},
538.468 - {"//y////bli//","//y//bli//"},
538.469 - {"////y////","//y//"},
538.470 - {"////y//bli////","//y//bli//"},
538.471 - {"////y//////","//y//"},
538.472 - {"////y////bli////","//y//bli//"},
538.473 - {"z//y////","z//y//"},
538.474 - {"z//y//bli//","z//y//bli//"},
538.475 - {"z//y//////","z//y//"},
538.476 - {"z//y////bli//","z//y//bli//"},
538.477 - {"//z//y////","//z//y//"},
538.478 - {"//z//y//bli//","//z//y//bli//"},
538.479 - {"//z//y//////","//z//y//"},
538.480 - {"//z//y////bli//","//z//y//bli//"},
538.481 - {"z////y////","z//y//"},
538.482 - {"z////y//bli//","z//y//bli//"},
538.483 - {"z////y//////","z//y//"},
538.484 - {"z////y////bli//","z//y//bli//"},
538.485 - {"//z////y////","//z//y//"},
538.486 - {"//z////y//bli//","//z//y//bli//"},
538.487 - {"//z////y//////","//z//y//"},
538.488 - {"//z////y////bli//","//z//y//bli//"},
538.489 - {"////z////y////","//z//y//"},
538.490 - {"////z////y//bli//","//z//y//bli//"},
538.491 - {"////z////y//////","//z//y//"},
538.492 - {"////z////y////bli//","//z//y//bli//"},
538.493 -
538.494 - };
538.495 - private static String[][] testnolead = {
538.496 - {"/a/a/","/a/a/"},
538.497 - {"/","/"},
538.498 - {"bli","bli"},
538.499 - {"///a/a/","/a/a/"},
538.500 - {"///","/"},
538.501 - {"//bli","bli"},
538.502 - {"/////a/a/","/a/a/"},
538.503 - {"/////","/"},
538.504 - {"////bli","bli"},
538.505 - {"y///a/a/","y///a/a/"},
538.506 - {"y///","y///"},
538.507 - {"y//bli","y//bli"},
538.508 - {"y/////a/a/","y///a/a/"},
538.509 - {"y/////","y///"},
538.510 - {"y////bli","y//bli"},
538.511 - {"//y///a/a/","y///a/a/"},
538.512 - {"//y///","y///"},
538.513 - {"//y//bli","y//bli"},
538.514 - {"//y/////a/a/","y///a/a/"},
538.515 - {"//y/////","y///"},
538.516 - {"//y////bli","y//bli"},
538.517 - {"////y///a/a/","y///a/a/"},
538.518 - {"////y///","y///"},
538.519 - {"////y//bli","y//bli"},
538.520 - {"////y/////a/a/","y///a/a/"},
538.521 - {"////y/////","y///"},
538.522 - {"////y////bli","y//bli"},
538.523 -
538.524 - {"z//y///a/a/","z//y///a/a/"},
538.525 - {"z//y///","z//y///"},
538.526 - {"z//y//bli","z//y//bli"},
538.527 - {"z//y/////a/a/","z//y///a/a/"},
538.528 - {"z//y/////","z//y///"},
538.529 - {"z//y////bli","z//y//bli"},
538.530 - {"//z//y///a/a/","z//y///a/a/"},
538.531 - {"//z//y///","z//y///"},
538.532 - {"//z//y//bli","z//y//bli"},
538.533 - {"//z//y/////a/a/","z//y///a/a/"},
538.534 - {"//z//y/////","z//y///"},
538.535 - {"//z//y////bli","z//y//bli"},
538.536 - {"z////y///a/a/","z//y///a/a/"},
538.537 - {"z////y///","z//y///"},
538.538 - {"z////y//bli","z//y//bli"},
538.539 - {"z////y/////a/a/","z//y///a/a/"},
538.540 - {"z////y/////","z//y///"},
538.541 - {"z////y////bli","z//y//bli"},
538.542 - {"//z////y///a/a/","z//y///a/a/"},
538.543 - {"//z////y///","z//y///"},
538.544 - {"//z////y//bli","z//y//bli"},
538.545 - {"//z////y/////a/a/","z//y///a/a/"},
538.546 - {"//z////y/////","z//y///"},
538.547 - {"//z////y////bli","z//y//bli"},
538.548 - {"////z////y///a/a/","z//y///a/a/"},
538.549 - {"////z////y///","z//y///"},
538.550 - {"////z////y//bli","z//y//bli"},
538.551 - {"////z////y/////a/a/","z//y///a/a/"},
538.552 - {"////z////y/////","z//y///"},
538.553 - {"////z////y////bli","z//y//bli"},
538.554 -
538.555 - {"bli//","bli//"},
538.556 - {"//bli//","bli//"},
538.557 - {"////bli//","bli//"},
538.558 - {"y////","y//"},
538.559 - {"y//bli//","y//bli//"},
538.560 - {"y////","y//"},
538.561 - {"y////bli//","y//bli//"},
538.562 - {"//y////","y//"},
538.563 - {"//y//bli//","y//bli//"},
538.564 - {"//y//////","y//"},
538.565 - {"//y////bli//","y//bli//"},
538.566 - {"////y////","y//"},
538.567 - {"////y//bli////","y//bli//"},
538.568 - {"////y//////","y//"},
538.569 - {"////y////bli////","y//bli//"},
538.570 - {"z//y////","z//y//"},
538.571 - {"z//y//bli//","z//y//bli//"},
538.572 - {"z//y//////","z//y//"},
538.573 - {"z//y////bli//","z//y//bli//"},
538.574 - {"//z//y////","z//y//"},
538.575 - {"//z//y//bli//","z//y//bli//"},
538.576 - {"//z//y//////","z//y//"},
538.577 - {"//z//y////bli//","z//y//bli//"},
538.578 - {"z////y////","z//y//"},
538.579 - {"z////y//bli//","z//y//bli//"},
538.580 - {"z////y//////","z//y//"},
538.581 - {"z////y////bli//","z//y//bli//"},
538.582 - {"//z////y////","z//y//"},
538.583 - {"//z////y//bli//","z//y//bli//"},
538.584 - {"//z////y//////","z//y//"},
538.585 - {"//z////y////bli//","z//y//bli//"},
538.586 - {"////z////y////","z//y//"},
538.587 - {"////z////y//bli//","z//y//bli//"},
538.588 - {"////z////y//////","z//y//"},
538.589 - {"////z////y////bli//","z//y//bli//"},
538.590 -
538.591 - };
538.592 -
538.593 - public static void testNormalizeDomain() throws Exception {
538.594 - int i = 0;
538.595 - for (String[] pair : testdomain) {
538.596 - i++;
538.597 - final String msg = "testNormalizeDomain["+i+", false] "+Arrays.asList(pair)+": ";
538.598 - assertEquals(msg,pair[1],
538.599 - ObjectNameRouter.normalizeDomain(pair[0],false));
538.600 - }
538.601 - if (failure != null) throw new Exception(failure);
538.602 - i = 0;
538.603 - for (String[] pair : testnolead) {
538.604 - i++;
538.605 - final String msg = "testNormalizeDomain["+i+", true] "+Arrays.asList(pair)+": ";
538.606 - assertEquals(msg,pair[1],
538.607 - ObjectNameRouter.normalizeDomain(pair[0],true));
538.608 - }
538.609 - if (failure != null) throw new Exception(failure);
538.610 - }
538.611 -
538.612 - public static void main(String[] args) throws Exception {
538.613 - testDeepRewrite();
538.614 - testNormalizeDomain();
538.615 - testInsertPath();
538.616 - testWildcard();
538.617 - testGetNormalizedPath();
538.618 - }
538.619 -
538.620 - private static void assertEquals(Object x, Object y) {
538.621 - assertEquals("",x,y);
538.622 - }
538.623 -
538.624 - private static void assertEquals(String msg, Object x, Object y) {
538.625 - if (msg == null) msg="";
538.626 - if (!equal(x, y))
538.627 - failed(msg+"expected " + string(x) + "; got " + string(y));
538.628 - }
538.629 -
538.630 - private static boolean equal(Object x, Object y) {
538.631 - if (x == y)
538.632 - return true;
538.633 - if (x == null || y == null)
538.634 - return false;
538.635 - if (x.getClass().isArray())
538.636 - return Arrays.deepEquals(new Object[] {x}, new Object[] {y});
538.637 - return x.equals(y);
538.638 - }
538.639 -
538.640 - private static String string(Object x) {
538.641 - String s = Arrays.deepToString(new Object[] {x});
538.642 - return s.substring(1, s.length() - 1);
538.643 - }
538.644 -
538.645 -
538.646 - private static void failed(String why) {
538.647 - failure = why;
538.648 - new Throwable("FAILED: " + why).printStackTrace(System.out);
538.649 - }
538.650 -
538.651 -}
539.1 --- a/test/javax/management/namespace/JMXRemoteNamespaceTest.java Mon Nov 23 10:04:47 2009 +0000
539.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
539.3 @@ -1,190 +0,0 @@
539.4 -/*
539.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
539.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
539.7 - *
539.8 - * This code is free software; you can redistribute it and/or modify it
539.9 - * under the terms of the GNU General Public License version 2 only, as
539.10 - * published by the Free Software Foundation.
539.11 - *
539.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
539.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
539.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
539.15 - * version 2 for more details (a copy is included in the LICENSE file that
539.16 - * accompanied this code).
539.17 - *
539.18 - * You should have received a copy of the GNU General Public License version
539.19 - * 2 along with this work; if not, write to the Free Software Foundation,
539.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
539.21 - *
539.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
539.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
539.24 - * have any questions.
539.25 - */
539.26 -/*
539.27 - *
539.28 - * @test JMXRemoteNamespaceTest.java
539.29 - * @summary Basic tests on a JMXRemoteNamespace.
539.30 - * @author Daniel Fuchs
539.31 - * @bug 5072476
539.32 - * @run clean JMXRemoteNamespaceTest Wombat WombatMBean
539.33 - * @run build JMXRemoteNamespaceTest Wombat WombatMBean
539.34 - * @run main JMXRemoteNamespaceTest
539.35 - */
539.36 -
539.37 -import javax.management.JMX;
539.38 -import javax.management.Notification;
539.39 -import javax.management.ObjectName;
539.40 -import javax.management.namespace.JMXNamespaces;
539.41 -import javax.management.MBeanServer;
539.42 -import javax.management.MBeanServerFactory;
539.43 -import javax.management.NotificationListener;
539.44 -import javax.management.namespace.JMXRemoteNamespace;
539.45 -import javax.management.remote.JMXConnectorServer;
539.46 -import javax.management.remote.JMXConnectorServerFactory;
539.47 -import javax.management.remote.JMXServiceURL;
539.48 -import java.util.List;
539.49 -import java.util.ArrayList;
539.50 -import java.util.Collections;
539.51 -import java.io.IOException;
539.52 -import javax.management.AttributeChangeNotification;
539.53 -
539.54 -/**
539.55 - * Test simple creation/registration of namespace.
539.56 - *
539.57 - */
539.58 -public class JMXRemoteNamespaceTest {
539.59 -
539.60 - static class MyConnect implements NotificationListener {
539.61 - private final JMXRemoteNamespace my;
539.62 - private final List<Notification> list;
539.63 - private volatile int connectCount=0;
539.64 - private int closeCount=0;
539.65 - private final ObjectName myname;
539.66 - public MyConnect(JMXRemoteNamespace my, ObjectName myname) {
539.67 - this.my=my;
539.68 - this.myname = myname;
539.69 - list = Collections.synchronizedList(new ArrayList<Notification>());
539.70 - my.addNotificationListener(this, null, null);
539.71 - }
539.72 -
539.73 - public synchronized void connect() throws IOException {
539.74 - my.connect();
539.75 - if (!my.isConnected())
539.76 - throw new IOException(myname+" should be connected");
539.77 - connectCount++;
539.78 - }
539.79 -
539.80 - public void close() throws IOException {
539.81 - my.close();
539.82 - if (my.isConnected())
539.83 - throw new IOException(myname+" shouldn't be connected");
539.84 - closeCount++;
539.85 - }
539.86 -
539.87 - public synchronized int getConnectCount() {
539.88 - return connectCount;
539.89 - }
539.90 - public synchronized int getClosedCount() {
539.91 - return closeCount;
539.92 - }
539.93 -
539.94 - public synchronized void handleNotification(Notification notification,
539.95 - Object handback) {
539.96 - list.add(notification);
539.97 - }
539.98 -
539.99 - public synchronized void checkNotifs(int externalConnect,
539.100 - int externalClosed) throws Exception {
539.101 - System.err.println("Connected: "+connectCount+" time"+
539.102 - ((connectCount>1)?"s":""));
539.103 - System.err.println("Closed: "+closeCount+" time"+
539.104 - ((closeCount>1)?"s":""));
539.105 - System.err.println("Received:");
539.106 - int cl=0;
539.107 - int co=0;
539.108 - for (Notification n : list) {
539.109 - System.err.println("\t"+n);
539.110 - if (!(n instanceof AttributeChangeNotification))
539.111 - throw new Exception("Unexpected notif: "+n.getClass());
539.112 - final AttributeChangeNotification acn =
539.113 - (AttributeChangeNotification)n;
539.114 - if (((Boolean)acn.getNewValue()).booleanValue())
539.115 - co++;
539.116 - else cl++;
539.117 - if ((((Boolean)acn.getNewValue()).booleanValue())
539.118 - == (((Boolean)acn.getOldValue()).booleanValue())) {
539.119 - throw new Exception("Bad values: old=new");
539.120 - }
539.121 - }
539.122 - if (! (list.size()==(closeCount+connectCount+
539.123 - externalClosed+externalConnect))) {
539.124 - throw new Exception("Bad notif count - got "+list.size());
539.125 - }
539.126 - if (cl!=(closeCount+externalClosed)) {
539.127 - throw new Exception("Bad count of close notif: expected "
539.128 - +(closeCount+externalClosed)+", got"+cl);
539.129 - }
539.130 - if (co!=(connectCount+externalConnect)) {
539.131 - throw new Exception("Bad count of connect notif: expected "
539.132 - +(connectCount+externalConnect)+", got"+co);
539.133 - }
539.134 - }
539.135 - }
539.136 -
539.137 - public static void testConnectClose() throws Exception {
539.138 - final MBeanServer myServer = MBeanServerFactory.newMBeanServer();
539.139 - final JMXConnectorServer myRMI =
539.140 - JMXConnectorServerFactory.newJMXConnectorServer(
539.141 - new JMXServiceURL("rmi",null,0), null, myServer);
539.142 - myRMI.start();
539.143 - try {
539.144 - final JMXRemoteNamespace my =
539.145 - JMXRemoteNamespace.newJMXRemoteNamespace(
539.146 - myRMI.getAddress(),null);
539.147 - final MBeanServer s = MBeanServerFactory.newMBeanServer();
539.148 - final ObjectName myname = JMXNamespaces.getNamespaceObjectName("my");
539.149 - final ObjectName wname = ObjectName.getInstance("backyard:type=Wombat");
539.150 - myServer.registerMBean(new Wombat(),wname);
539.151 - final MyConnect myc = new MyConnect(my,myname);
539.152 - myc.connect();
539.153 - myc.close();
539.154 - myc.connect();
539.155 - s.registerMBean(my,myname);
539.156 - myc.close();
539.157 - myc.connect();
539.158 - if (!s.queryNames(new ObjectName("my//b*:*"),null).contains(
539.159 - JMXNamespaces.insertPath("my", wname))) {
539.160 - throw new RuntimeException("1: Wombat not found: "+wname);
539.161 - }
539.162 - myc.close();
539.163 - myc.connect();
539.164 - final MBeanServer cd = JMXNamespaces.narrowToNamespace(s, "my");
539.165 - if (!cd.queryNames(new ObjectName("b*:*"),null).contains(wname)) {
539.166 - throw new RuntimeException("2: Wombat not found: "+wname);
539.167 - }
539.168 - myc.close();
539.169 - myc.connect();
539.170 - System.out.println("Found a Wombat in my backyard.");
539.171 -
539.172 - final String deepThoughts = "I want to leave this backyard!";
539.173 - final WombatMBean w = JMX.newMBeanProxy(cd, wname, WombatMBean.class);
539.174 - w.setCaption(deepThoughts);
539.175 - if (!deepThoughts.equals(w.getCaption()))
539.176 - throw new RuntimeException("4: Wombat is not thinking right: "+
539.177 - w.getCaption());
539.178 - s.unregisterMBean(myname);
539.179 - if (my.isConnected())
539.180 - throw new Exception(myname+" shouldn't be connected");
539.181 - myc.connect();
539.182 - myc.close();
539.183 - myc.checkNotifs(0,1);
539.184 - } finally {
539.185 - myRMI.stop();
539.186 - }
539.187 -
539.188 - }
539.189 -
539.190 - public static void main(String... args) throws Exception {
539.191 - testConnectClose();
539.192 - }
539.193 -}
540.1 --- a/test/javax/management/namespace/JMXRemoteTargetNamespace.java Mon Nov 23 10:04:47 2009 +0000
540.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
540.3 @@ -1,216 +0,0 @@
540.4 -/*
540.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
540.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
540.7 - *
540.8 - * This code is free software; you can redistribute it and/or modify it
540.9 - * under the terms of the GNU General Public License version 2 only, as
540.10 - * published by the Free Software Foundation. Sun designates this
540.11 - * particular file as subject to the "Classpath" exception as provided
540.12 - * by Sun in the LICENSE file that accompanied this code.
540.13 - *
540.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
540.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
540.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
540.17 - * version 2 for more details (a copy is included in the LICENSE file that
540.18 - * accompanied this code).
540.19 - *
540.20 - * You should have received a copy of the GNU General Public License version
540.21 - * 2 along with this work; if not, write to the Free Software Foundation,
540.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
540.23 - *
540.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
540.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
540.26 - * have any questions.
540.27 - */
540.28 -
540.29 -
540.30 -import java.io.IOException;
540.31 -import java.util.Map;
540.32 -import java.util.logging.Logger;
540.33 -
540.34 -import javax.management.InstanceAlreadyExistsException;
540.35 -import javax.management.MBeanException;
540.36 -import javax.management.MBeanRegistrationException;
540.37 -import javax.management.MBeanServerConnection;
540.38 -import javax.management.NotCompliantMBeanException;
540.39 -import javax.management.ObjectInstance;
540.40 -import javax.management.ObjectName;
540.41 -import javax.management.ReflectionException;
540.42 -import javax.management.event.EventClient;
540.43 -import javax.management.namespace.JMXNamespace;
540.44 -import javax.management.namespace.JMXNamespaces;
540.45 -import javax.management.namespace.JMXRemoteNamespace;
540.46 -import javax.management.namespace.JMXRemoteNamespaceMBean;
540.47 -import javax.management.remote.JMXConnector;
540.48 -import javax.management.remote.JMXServiceURL;
540.49 -
540.50 -// These options originally in the draft of javax/management/namespaces
540.51 -// but we decided to retire them - since they could be implemented
540.52 -// by subclasses. The JMXRemoteTargetNamespace is such a subclass.
540.53 -//
540.54 -public class JMXRemoteTargetNamespace extends JMXRemoteNamespace {
540.55 -
540.56 - /**
540.57 - * A logger for this class.
540.58 - **/
540.59 - private static final Logger LOG =
540.60 - Logger.getLogger(JMXRemoteTargetNamespace.class.getName());
540.61 - public static final String CREATE_EVENT_CLIENT =
540.62 - "jmx.test.create.event.client";
540.63 -
540.64 - private final String sourceNamespace;
540.65 - private final boolean createEventClient;
540.66 -
540.67 - public JMXRemoteTargetNamespace(JMXServiceURL sourceURL,
540.68 - Map<String,?> optionsMap) {
540.69 - this(sourceURL,optionsMap,null);
540.70 - }
540.71 -
540.72 - public JMXRemoteTargetNamespace(JMXServiceURL sourceURL,
540.73 - Map<String,?> optionsMap, String sourceNamespace) {
540.74 - super(sourceURL, optionsMap);
540.75 - this.sourceNamespace = sourceNamespace;
540.76 - this.createEventClient = createEventClient(optionsMap);
540.77 - }
540.78 -
540.79 - private boolean createEventClient(Map<String,?> options) {
540.80 - if (options == null) return false;
540.81 - final Object createValue = options.get(CREATE_EVENT_CLIENT);
540.82 - if (createValue == null) return false;
540.83 - if (createValue instanceof Boolean)
540.84 - return ((Boolean)createValue).booleanValue();
540.85 - if (createValue instanceof String)
540.86 - return Boolean.valueOf((String)createValue);
540.87 - throw new IllegalArgumentException("Bad type for value of property " +
540.88 - CREATE_EVENT_CLIENT+": "+createValue.getClass().getName());
540.89 - }
540.90 -
540.91 - @Override
540.92 - protected MBeanServerConnection getMBeanServerConnection(JMXConnector jmxc)
540.93 - throws IOException {
540.94 - MBeanServerConnection mbsc = super.getMBeanServerConnection(jmxc);
540.95 - if (sourceNamespace != null && sourceNamespace.length() > 0)
540.96 - mbsc = JMXNamespaces.narrowToNamespace(mbsc, sourceNamespace);
540.97 - if (createEventClient)
540.98 - mbsc = EventClient.getEventClientConnection(mbsc);
540.99 - return mbsc;
540.100 - }
540.101 -
540.102 -
540.103 - /**
540.104 - * Creates a target name space to mirror a remote source name space in
540.105 - * the target server.
540.106 - * @param targetServer A connection to the target MBean server in which
540.107 - * the new name space should be created.
540.108 - * @param targetPath the name space to create in the target server. Note
540.109 - * that if the target name space is a path - that is if
540.110 - * {@code targetPath} contains '//', then the parent name space
540.111 - * must be pre-existing in the target server. Attempting to create
540.112 - * {code targetPath="a//b//c"} in {@code targetServer}
540.113 - * will fail if name space {@code "a//b"} doesn't already exists
540.114 - * in {@code targetServer}.
540.115 - * @param sourceURL a JMX service URL that can be used to connect to the
540.116 - * source MBean server.
540.117 - * @param options the set of options to use when creating the
540.118 - * {@link #JMXRemoteNamespace JMXRemoteNamespace} that will
540.119 - * handle the new name space.
540.120 - * @return An {@code ObjectInstance} representing the
540.121 - * {@link JMXRemoteNamespaceMBean} which handles the
540.122 - * new name space.
540.123 - *
540.124 - **/
540.125 - public static ObjectInstance createNamespace(
540.126 - MBeanServerConnection targetServer,
540.127 - String targetPath,
540.128 - JMXServiceURL sourceURL,
540.129 - Map<String,?> options)
540.130 - throws IOException, InstanceAlreadyExistsException,
540.131 - MBeanRegistrationException, MBeanException {
540.132 - final ObjectName name =
540.133 - JMXNamespaces.getNamespaceObjectName(targetPath);
540.134 - return createInstance(targetServer, name, sourceURL, options, null);
540.135 - }
540.136 -
540.137 - /**
540.138 - * Creates a target name space to mirror a remote source name space in
540.139 - * the target server.
540.140 - * @param targetServer A connection to the target MBean server in which
540.141 - * the new name space should be created.
540.142 - * @param targetPath the name space to create in the target server. Note
540.143 - * that if the target name space is a path - that is if
540.144 - * {@code targetPath} contains '//', then the parent name space
540.145 - * must be pre-existing in the target server. Attempting to create
540.146 - * {code targetPath="a//b//c"} in {@code targetServer}
540.147 - * will fail if name space {@code "a//b"} doesn't already exists
540.148 - * in {@code targetServer}.
540.149 - * @param sourceURL a JMX service URL that can be used to connect to the
540.150 - * source MBean server.
540.151 - * @param sourcePath the source namespace path insode the source server.
540.152 - * @param options the set of options to use when creating the
540.153 - * {@link #JMXRemoteNamespace JMXRemoteNamespace} that will
540.154 - * handle the new name space.
540.155 - * @return An {@code ObjectInstance} representing the
540.156 - * {@link JMXRemoteNamespaceMBean} which handles the
540.157 - * new name space.
540.158 - *
540.159 - **/
540.160 - public static ObjectInstance createNamespace(
540.161 - MBeanServerConnection targetServer,
540.162 - String targetPath,
540.163 - JMXServiceURL sourceURL,
540.164 - Map<String,?> options,
540.165 - String sourcePath)
540.166 - throws IOException, InstanceAlreadyExistsException,
540.167 - MBeanRegistrationException, MBeanException {
540.168 - final ObjectName name =
540.169 - JMXNamespaces.getNamespaceObjectName(targetPath);
540.170 - return createInstance(targetServer, name, sourceURL, options, sourcePath);
540.171 - }
540.172 -
540.173 - /**
540.174 - * Creates and registers a {@link JMXRemoteNamespaceMBean} in a target
540.175 - * server, to mirror a remote source name space.
540.176 - *
540.177 - * @param server A connection to the target MBean server in which
540.178 - * the new name space should be created.
540.179 - * @param handlerName the name of the JMXRemoteNamespace to create.
540.180 - * This must be a compliant name space handler name as returned
540.181 - * by {@link
540.182 - * JMXNamespaces#getNamespaceObjectName JMXNamespaces.getNamespaceObjectName}.
540.183 - * @param sourceURL a JMX service URL that can be used to connect to the
540.184 - * source MBean server.
540.185 - * @param sourcePath the path inside the source server
540.186 - * @param options the set of options to use when creating the
540.187 - * {@link #JMXRemoteNamespace JMXRemoteNamespace} that will
540.188 - * handle the new name space.
540.189 - * @return An {@code ObjectInstance} representing the new
540.190 - * {@link JMXRemoteNamespaceMBean} created.
540.191 - * @see #createNamespace createNamespace
540.192 - */
540.193 - static ObjectInstance createInstance(MBeanServerConnection server,
540.194 - ObjectName handlerName,
540.195 - JMXServiceURL sourceURL, Map<String,?> options,
540.196 - String sourcePath)
540.197 - throws IOException, InstanceAlreadyExistsException,
540.198 - MBeanRegistrationException, MBeanException {
540.199 - try {
540.200 - final String[] signature = {
540.201 - JMXServiceURL.class.getName(),
540.202 - Map.class.getName(),
540.203 - String.class.getName()
540.204 - };
540.205 - final Object[] params = {
540.206 - sourceURL,options,sourcePath
540.207 - };
540.208 - final ObjectInstance instance =
540.209 - server.createMBean(JMXRemoteTargetNamespace.class.getName(),
540.210 - handlerName,params,signature);
540.211 - return instance;
540.212 - } catch (NotCompliantMBeanException ex) {
540.213 - throw new RuntimeException("unexpected exception: " + ex, ex);
540.214 - } catch (ReflectionException ex) {
540.215 - throw new RuntimeException("unexpected exception: " + ex, ex);
540.216 - }
540.217 - }
540.218 -
540.219 -}
541.1 --- a/test/javax/management/namespace/LazyDomainTest.java Mon Nov 23 10:04:47 2009 +0000
541.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
541.3 @@ -1,790 +0,0 @@
541.4 -/*
541.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
541.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
541.7 - *
541.8 - * This code is free software; you can redistribute it and/or modify it
541.9 - * under the terms of the GNU General Public License version 2 only, as
541.10 - * published by the Free Software Foundation.
541.11 - *
541.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
541.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
541.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
541.15 - * version 2 for more details (a copy is included in the LICENSE file that
541.16 - * accompanied this code).
541.17 - *
541.18 - * You should have received a copy of the GNU General Public License version
541.19 - * 2 along with this work; if not, write to the Free Software Foundation,
541.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
541.21 - *
541.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
541.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
541.24 - * have any questions.
541.25 - */
541.26 -/*
541.27 - *
541.28 - * @test LazyDomainTest.java
541.29 - * @bug 5072476
541.30 - * @summary Basic test for Lazy Domains.
541.31 - * @author Daniel Fuchs
541.32 - * @run clean LazyDomainTest Wombat WombatMBean
541.33 - * @run build LazyDomainTest Wombat WombatMBean
541.34 - * @run main LazyDomainTest
541.35 - */
541.36 -
541.37 -
541.38 -import java.lang.management.ClassLoadingMXBean;
541.39 -import java.lang.management.ManagementFactory;
541.40 -import java.lang.reflect.InvocationHandler;
541.41 -import java.lang.reflect.InvocationTargetException;
541.42 -import java.lang.reflect.Method;
541.43 -import java.lang.reflect.Proxy;
541.44 -import java.util.Arrays;
541.45 -import java.util.Collections;
541.46 -import java.util.HashMap;
541.47 -import java.util.HashSet;
541.48 -import java.util.concurrent.ArrayBlockingQueue;
541.49 -import java.util.concurrent.BlockingQueue;
541.50 -import java.util.concurrent.TimeUnit;
541.51 -import java.util.Map;
541.52 -import java.util.Set;
541.53 -import javax.management.JMX;
541.54 -import javax.management.ListenerNotFoundException;
541.55 -import javax.management.MBeanServer;
541.56 -import javax.management.MBeanServerBuilder;
541.57 -import javax.management.MBeanServerDelegate;
541.58 -import javax.management.MBeanServerFactory;
541.59 -import javax.management.MBeanServerNotification;
541.60 -import javax.management.Notification;
541.61 -import javax.management.NotificationFilter;
541.62 -import javax.management.NotificationListener;
541.63 -import javax.management.ObjectName;
541.64 -import javax.management.namespace.JMXDomain;
541.65 -import javax.management.remote.MBeanServerForwarder;
541.66 -
541.67 -/**
541.68 - * Test simple creation/registration of namespace.
541.69 - *
541.70 - */
541.71 -public class LazyDomainTest {
541.72 - private static Map<String,Object> emptyEnvMap() {
541.73 - return Collections.emptyMap();
541.74 - }
541.75 -
541.76 -
541.77 - public static interface MBeanServerLoader {
541.78 - public MBeanServer loadMBeanServer();
541.79 - }
541.80 -
541.81 -
541.82 - public static class MBeanServerProxy implements InvocationHandler {
541.83 -
541.84 - private final static Map<Method,Method> localMap;
541.85 - static {
541.86 - localMap = new HashMap<Method, Method>();
541.87 - for (Method m : MBeanServerForwarder.class.getDeclaredMethods()) {
541.88 - try {
541.89 - final Method loc = MBeanServerProxy.class.
541.90 - getMethod(m.getName(), m.getParameterTypes());
541.91 - localMap.put(m, loc);
541.92 - } catch (Exception x) {
541.93 - // not defined...
541.94 - }
541.95 - }
541.96 - try {
541.97 - localMap.put(MBeanServer.class.
541.98 - getMethod("getMBeanCount", (Class[]) null),
541.99 - MBeanServerProxy.class.
541.100 - getMethod("getMBeanCount", (Class[]) null));
541.101 - } catch (NoSuchMethodException x) {
541.102 - // OK.
541.103 - }
541.104 - }
541.105 -
541.106 - private final MBeanServerLoader loader;
541.107 - private MBeanServer server;
541.108 - private final Set<LazyDomain> domains;
541.109 -
541.110 - public MBeanServerProxy(MBeanServerLoader loader) {
541.111 - if (loader == null)
541.112 - throw new IllegalArgumentException("null loader");
541.113 - this.loader = loader;
541.114 - this.server = null;
541.115 - domains = new HashSet<LazyDomain>();
541.116 - }
541.117 -
541.118 -
541.119 - public Object invoke(Object proxy, Method method, Object[] args)
541.120 - throws Throwable {
541.121 - if (method.getDeclaringClass().equals(Object.class)) {
541.122 - return invokeMethod(this,method,args);
541.123 - }
541.124 - final Method local = localMap.get(method);
541.125 - if (local != null) {
541.126 - return invokeMethod(this,local,args);
541.127 - }
541.128 - if (method.getDeclaringClass().equals(MBeanServer.class)) {
541.129 - return invokeMethod(getMBeanServer(),method,args);
541.130 - }
541.131 - throw new NoSuchMethodException(method.getName());
541.132 - }
541.133 -
541.134 - private Object invokeMethod(Object on, Method method, Object[] args)
541.135 - throws Throwable {
541.136 - try {
541.137 - return method.invoke(on, args);
541.138 - } catch (InvocationTargetException ex) {
541.139 - throw ex.getTargetException();
541.140 - }
541.141 - }
541.142 -
541.143 - public synchronized MBeanServer getMBeanServer() {
541.144 - if (server == null) setMBeanServer(loader.loadMBeanServer());
541.145 - return server;
541.146 - }
541.147 -
541.148 - public synchronized void setMBeanServer(MBeanServer mbs) {
541.149 - this.server = mbs;
541.150 - if (mbs != null) {
541.151 - for (LazyDomain dom : domains) dom.loaded();
541.152 - domains.clear();
541.153 - }
541.154 - }
541.155 -
541.156 - public synchronized boolean isLoaded() {
541.157 - return server != null;
541.158 - }
541.159 -
541.160 - public synchronized void add(LazyDomain dom) {
541.161 - if (isLoaded()) dom.loaded();
541.162 - else domains.add(dom);
541.163 - }
541.164 -
541.165 - public synchronized boolean remove(LazyDomain dom) {
541.166 - return domains.remove(dom);
541.167 - }
541.168 -
541.169 - public Integer getMBeanCount() {
541.170 - if (isLoaded()) return server.getMBeanCount();
541.171 - else return Integer.valueOf(0);
541.172 - }
541.173 - }
541.174 -
541.175 - public static class LazyDomain extends JMXDomain {
541.176 - public static MBeanServer makeProxyFor(MBeanServerProxy proxy) {
541.177 - return (MBeanServer)
541.178 - Proxy.newProxyInstance(LazyDomain.class.getClassLoader(),
541.179 - new Class[] {MBeanServer.class, MBeanServerForwarder.class},
541.180 - proxy);
541.181 - }
541.182 -
541.183 - private final MBeanServerProxy proxy;
541.184 - private volatile NotificationListener listener;
541.185 - private volatile NotificationFilter filter;
541.186 -
541.187 - public LazyDomain(MBeanServerProxy proxy) {
541.188 - super(makeProxyFor(proxy));
541.189 - this.proxy = proxy;
541.190 - }
541.191 -
541.192 - @Override
541.193 - public Integer getMBeanCount() {
541.194 - if (proxy.isLoaded())
541.195 - return super.getMBeanCount();
541.196 - return 0;
541.197 - }
541.198 -
541.199 -
541.200 - @Override
541.201 - public synchronized void addMBeanServerNotificationListener(
541.202 - NotificationListener listener,
541.203 - NotificationFilter filter) {
541.204 - if (proxy.isLoaded()) {
541.205 - super.addMBeanServerNotificationListener(listener, filter);
541.206 - } else {
541.207 - this.listener = listener;
541.208 - this.filter = filter;
541.209 - proxy.add(this);
541.210 - }
541.211 - }
541.212 -
541.213 - @Override
541.214 - public synchronized void removeMBeanServerNotificationListener(
541.215 - NotificationListener listener)
541.216 - throws ListenerNotFoundException {
541.217 - if (this.listener != listener)
541.218 - throw new ListenerNotFoundException();
541.219 - this.listener = null;
541.220 - this.filter = null;
541.221 - if (proxy.isLoaded())
541.222 - super.removeMBeanServerNotificationListener(listener);
541.223 - proxy.remove(this);
541.224 - }
541.225 -
541.226 - public synchronized void loaded() {
541.227 - if (listener != null)
541.228 - addMBeanServerNotificationListener(listener, filter);
541.229 - }
541.230 -
541.231 - }
541.232 -
541.233 - /**
541.234 - * This is a use case for e.g GlassFish: the LazyStarterDomain MBean
541.235 - * is a place holder that will unregister itself and autoload a set
541.236 - * of MBeans in place of its own domain when that domain is
541.237 - * accessed.
541.238 - * This is an abstract class, where the only abstract method
541.239 - * is loadMBeans(MBeanServer).
541.240 - * Subclasses should implement that method to register whatever MBeans
541.241 - * in the domain previously held by that LazyStarterDomain object.
541.242 - * In other words: the LazyStarterDomain MBean is 'replaced' by the
541.243 - * MBeans loaded by loadMBeans();
541.244 - */
541.245 - public static abstract class LazyStarterDomain extends LazyDomain {
541.246 -
541.247 - /**
541.248 - * This is a loader that will unregister the JMXDomain that
541.249 - * created it, and register a bunch of MBeans in its place
541.250 - * by calling LazyStarterDomain.loadMBeans
541.251 - *
541.252 - * That one gave me "la migraine".
541.253 - */
541.254 - private static class HalfGrainLoader implements MBeanServerLoader {
541.255 - private volatile LazyStarterDomain domain;
541.256 - public MBeanServer loadMBeanServer() {
541.257 - if (domain == null)
541.258 - throw new IllegalStateException(
541.259 - "JMXDomain MBean not registered!");
541.260 - final MBeanServer server = domain.getMBeanServer();
541.261 - final ObjectName domainName = domain.getObjectName();
541.262 - try {
541.263 - server.unregisterMBean(domainName);
541.264 - } catch (Exception x) {
541.265 - throw new IllegalStateException("Can't unregister " +
541.266 - "JMXDomain: "+x,x);
541.267 - }
541.268 - domain.loadMBeans(server,domainName.getDomain());
541.269 - return server;
541.270 - }
541.271 - public void setDomain(LazyStarterDomain domain) {
541.272 - this.domain = domain;
541.273 - }
541.274 - }
541.275 -
541.276 - /**
541.277 - * This is an MBeanServerProxy which create a loader for the
541.278 - * LazyStarterDomain MBean.
541.279 - */
541.280 - private static class DomainStarter extends MBeanServerProxy {
541.281 -
541.282 - public DomainStarter() {
541.283 - this(new HalfGrainLoader());
541.284 - }
541.285 -
541.286 - private final HalfGrainLoader loader;
541.287 - private DomainStarter(HalfGrainLoader loader) {
541.288 - super(loader);
541.289 - this.loader = loader;
541.290 - }
541.291 -
541.292 - public void setDomain(LazyStarterDomain domain) {
541.293 - loader.setDomain(domain);
541.294 - }
541.295 - }
541.296 -
541.297 - /**
541.298 - * A new LazyStarterDomain. When the domain monitored by this
541.299 - * MBean is accessed, this MBean will unregister itself and call
541.300 - * the abstract loadMBeans(MBeanServer) method.
541.301 - * Subclasses need only to implement loadMBeans().
541.302 - */
541.303 - public LazyStarterDomain() {
541.304 - this(new DomainStarter());
541.305 - }
541.306 -
541.307 - private LazyStarterDomain(DomainStarter starter) {
541.308 - super(starter);
541.309 - starter.setDomain(this);
541.310 - }
541.311 -
541.312 - // Contrarily to its LazyDomain superclass, this LazyDomain
541.313 - // doesn't wrapp another MBeanServer: it simply registers a bunch
541.314 - // of MBeans in its own MBeanServer.
541.315 - // Thus, there's no notifications to forward.
541.316 - //
541.317 - @Override
541.318 - public void addMBeanServerNotificationListener(
541.319 - NotificationListener listener, NotificationFilter filter) {
541.320 - // nothing to do.
541.321 - }
541.322 -
541.323 - // Contrarily to its LazyDomain superclass, this LazyDomain
541.324 - // doesn't wrapp another MBeanServer: it simply registers a bunch
541.325 - // of MBeans in its own MBeanServer.
541.326 - // Thus, there's no notifications to forward.
541.327 - //
541.328 - @Override
541.329 - public void removeMBeanServerNotificationListener(
541.330 - NotificationListener listener) throws ListenerNotFoundException {
541.331 - // nothing to do
541.332 - }
541.333 -
541.334 - // If this domain is registered, it contains no MBean.
541.335 - // If it is not registered, then it no longer contain any MBean.
541.336 - // The MBeanCount is thus always 0.
541.337 - @Override
541.338 - public Integer getMBeanCount() {
541.339 - return 0;
541.340 - }
541.341 -
541.342 - /**
541.343 - * Called when the domain is first accessed.
541.344 - * {@code server} is the server in which this MBean was registered.
541.345 - * A subclass must override this method in order to register
541.346 - * the MBeans that should be contained in domain.
541.347 - *
541.348 - * @param server the server in which to load the MBeans.
541.349 - * @param domain the domain in which the MBeans should be registered.
541.350 - */
541.351 - protected abstract void loadMBeans(MBeanServer server, String domain);
541.352 -
541.353 -
541.354 - }
541.355 -
541.356 - private static MBeanServerNotification pop(
541.357 - BlockingQueue<Notification> queue,
541.358 - String type,
541.359 - ObjectName mbean,
541.360 - String test)
541.361 - throws InterruptedException {
541.362 - final Notification n = queue.poll(1, TimeUnit.SECONDS);
541.363 - if (!(n instanceof MBeanServerNotification))
541.364 - fail(test+"expected MBeanServerNotification, got "+n);
541.365 - final MBeanServerNotification msn = (MBeanServerNotification)n;
541.366 - if (!type.equals(msn.getType()))
541.367 - fail(test+"expected "+type+", got "+msn.getType());
541.368 - if (!mbean.apply(msn.getMBeanName()))
541.369 - fail(test+"expected "+mbean+", got "+msn.getMBeanName());
541.370 - System.out.println(test+" got: "+msn);
541.371 - return msn;
541.372 - }
541.373 - private static MBeanServerNotification popADD(
541.374 - BlockingQueue<Notification> queue,
541.375 - ObjectName mbean,
541.376 - String test)
541.377 - throws InterruptedException {
541.378 - return pop(queue, MBeanServerNotification.REGISTRATION_NOTIFICATION,
541.379 - mbean, test);
541.380 - }
541.381 -
541.382 - private static MBeanServerNotification popREM(
541.383 - BlockingQueue<Notification> queue,
541.384 - ObjectName mbean,
541.385 - String test)
541.386 - throws InterruptedException {
541.387 - return pop(queue, MBeanServerNotification.UNREGISTRATION_NOTIFICATION,
541.388 - mbean, test);
541.389 - }
541.390 -
541.391 -
541.392 - private static void fail(String msg) {
541.393 - raise(new RuntimeException(msg));
541.394 - }
541.395 -
541.396 - private static void fail(String msg, Throwable cause) {
541.397 - raise(new RuntimeException(msg,cause));
541.398 - }
541.399 -
541.400 - private static void raise(RuntimeException x) {
541.401 - lastException = x;
541.402 - exceptionCount++;
541.403 - throw x;
541.404 - }
541.405 -
541.406 - private static volatile Exception lastException = null;
541.407 - private static volatile int exceptionCount = 0;
541.408 -
541.409 - // ZZZ need to add a test case with several LazyDomains, and
541.410 - // need to test that nothing is loaded until the lazy domains
541.411 - // are accessed...
541.412 - //
541.413 -
541.414 - private static void registerWombats(MBeanServer server, String domain,
541.415 - int count) {
541.416 - try {
541.417 - for (int i=0;i<count;i++) {
541.418 - final ObjectName name =
541.419 - new ObjectName(domain+":type=Wombat,name=wombat#"+i);
541.420 - server.createMBean("Wombat", name);
541.421 - }
541.422 - } catch (RuntimeException x) {
541.423 - throw x;
541.424 - } catch(Exception x) {
541.425 - throw new RuntimeException(x.toString(),x);
541.426 - }
541.427 - }
541.428 -
541.429 - public static void checkSize(String test, MBeanServer server, int size) {
541.430 - System.out.println("We have now "+server.getMBeanCount()+
541.431 - " MBeans in "+Arrays.toString(server.getDomains()));
541.432 - if (server.getMBeanCount() != size)
541.433 - fail(test+"Expected "+size+
541.434 - " MBeans, found " + server.getMBeanCount());
541.435 - }
541.436 -
541.437 - private static MBeanServer newMBeanServer() {
541.438 - return MBeanServerFactory.newMBeanServer();
541.439 - }
541.440 -
541.441 - public static void lazyTest() throws Exception {
541.442 - final String test = "lazyTest: ";
541.443 - System.out.println("" +
541.444 - "\nThis test checks that it is possible to perform lazy loading" +
541.445 - "\nof MBeans in a given domain by using a JMXDomain subclass" +
541.446 - "\nfor that domain.");
541.447 -
541.448 - System.out.println(test + " START");
541.449 -
541.450 - // The "global" MBeanServer...
541.451 - final MBeanServer server = newMBeanServer();
541.452 -
541.453 - // An MBeanServer proxy which makes it possible to `lazy load'
541.454 - // the platform MBeanServer domains inside the global MBeanServer.
541.455 - //
541.456 - final MBeanServerProxy platform =
541.457 - new MBeanServerProxy(new MBeanServerLoader() {
541.458 -
541.459 - public MBeanServer loadMBeanServer() {
541.460 - return ManagementFactory.getPlatformMBeanServer();
541.461 - }
541.462 - });
541.463 -
541.464 -
541.465 - // The list of domain from the platform MBeanServer that will be
541.466 - // lazily loaded in the global MBeanServer
541.467 - //
541.468 - final String[] platformDomains = {
541.469 - "java.lang", "com.sun.management",
541.470 - "java.util.logging", "java.nio"
541.471 - };
541.472 -
541.473 - // We create a second MBeanServer, in which we will store some
541.474 - // custom MBeans. We will use this server to perform lazy loading
541.475 - // of two domains: custom.awomb and custom.bwomb.
541.476 - //
541.477 - // We use an MBeanServerBuilder here so that the MBeans registered
541.478 - // in our custom domain see all the MBeans in the global MBeanServer.
541.479 - // We do this by saying that the 'outer' MBeanServer is our global
541.480 - // servers. This means that the MBeans registered in the global
541.481 - // MBeanServer will see the MBeans from custom.awomb and custom.bwomb,
541.482 - // and the MBeans from custom.awomb and custom.bwomb will also see
541.483 - // the MBeans from the global MBeanServer, including those from
541.484 - // the platform domains.
541.485 - //
541.486 - final MBeanServerBuilder builder = new MBeanServerBuilder();
541.487 - final MBeanServerDelegate delegate = builder.newMBeanServerDelegate();
541.488 - final MBeanServer custom = builder.newMBeanServer("custom",
541.489 - server, delegate);
541.490 -
541.491 - // Number of MBean that we will put in each of the custom domain.
541.492 - //
541.493 - final int customCount = 10;
541.494 -
541.495 - // We use one MBeanServer proxy for each of the custom domains.
541.496 - // This makes it possible to load custom.awomb independently of
541.497 - // custom.bwomb.
541.498 - //
541.499 - // Here, the logic of the loader is to register MBeans in the loaded
541.500 - // domain as soon as the domain is loaded.
541.501 - //
541.502 - final MBeanServerProxy customa =
541.503 - new MBeanServerProxy(new MBeanServerLoader() {
541.504 - // A loader to register awomb MBeans in the custom MBeanServer.
541.505 - public MBeanServer loadMBeanServer() {
541.506 - registerWombats(custom, "custom.awomb", customCount);
541.507 - return custom;
541.508 - }
541.509 - });
541.510 - final MBeanServerProxy customb =
541.511 - new MBeanServerProxy(new MBeanServerLoader() {
541.512 - // A loader to register bwomb MBeans in the custom MBeanServer.
541.513 - public MBeanServer loadMBeanServer() {
541.514 - registerWombats(custom, "custom.bwomb", customCount);
541.515 - return custom;
541.516 - }
541.517 - });
541.518 -
541.519 - // A notification queue.
541.520 - final BlockingQueue<Notification> queue =
541.521 - new ArrayBlockingQueue<Notification>(100);
541.522 -
541.523 - // A listener that puts notifs in the queue.
541.524 - final NotificationListener l = new NotificationListener() {
541.525 -
541.526 - public void handleNotification(Notification notification,
541.527 - Object handback) {
541.528 - try {
541.529 - if (!queue.offer(notification, 5, TimeUnit.SECONDS)) {
541.530 - throw new RuntimeException("timeout exceeded");
541.531 - }
541.532 - } catch (Exception x) {
541.533 - fail(test + "failed to handle notif", x);
541.534 - }
541.535 - }
541.536 - };
541.537 -
541.538 - // Create a LazyDomain for each of the platform domain.
541.539 - // All platform domain share the same MBeanServer proxy, which means
541.540 - // that loading one domain will also load all the others.
541.541 - //
541.542 - Map<String,LazyDomain> domainsMap = new HashMap<String,LazyDomain>();
541.543 - for (String dom : platformDomains) {
541.544 - domainsMap.put(dom, new LazyDomain(platform));
541.545 - }
541.546 - domainsMap.put("custom.awomb", new LazyDomain(customa));
541.547 - domainsMap.put("custom.bwomb", new LazyDomain(customb));
541.548 -
541.549 - for (Map.Entry<String,LazyDomain> e : domainsMap.entrySet()) {
541.550 - server.registerMBean(e.getValue(),
541.551 - JMXDomain.getDomainObjectName(e.getKey()));
541.552 - }
541.553 -
541.554 - // check that lazy MBeans are not there...
541.555 - checkSize(test,server,domainsMap.size()+1);
541.556 -
541.557 - System.out.println(test+" registering listener with delegate.");
541.558 - server.addNotificationListener(MBeanServerDelegate.DELEGATE_NAME, l,
541.559 - null, null);
541.560 -
541.561 - // check that lazy MBeans are not there...
541.562 - checkSize(test,server,domainsMap.size()+1);
541.563 -
541.564 - // force loading of custom.awomb.
541.565 - final ObjectName awombat = new ObjectName(
541.566 - "custom.awomb:type=Wombat,name=wombat#"+customCount/2);
541.567 - if (!server.isRegistered(awombat))
541.568 - fail(test+"Expected "+awombat+" to be reggistered!");
541.569 -
541.570 - final int oldCount = domainsMap.size()+1+customCount;
541.571 - checkSize(test,server,oldCount);
541.572 -
541.573 - if (queue.peek() != null)
541.574 - fail(test+"Received unexpected notifications: "+queue);
541.575 -
541.576 -
541.577 - System.out.println(test+"creating a proxy for ClassLoadingMXBean.");
541.578 - final ClassLoadingMXBean cl =
541.579 - JMX.newMXBeanProxy(server,
541.580 - new ObjectName(ManagementFactory.CLASS_LOADING_MXBEAN_NAME),
541.581 - ClassLoadingMXBean.class);
541.582 -
541.583 - checkSize(test,server,oldCount);
541.584 -
541.585 - System.out.println(test+"Loaded classes: "+cl.getLoadedClassCount());
541.586 -
541.587 - final int newCount = server.getMBeanCount();
541.588 - if (newCount < oldCount+6)
541.589 - fail(test+"Expected at least "+(oldCount+6)+
541.590 - " MBeans. Found "+newCount);
541.591 -
541.592 - final ObjectName jwombat = new ObjectName("java.lang:type=Wombat");
541.593 - server.createMBean("Wombat", jwombat);
541.594 - System.out.println(test+"Created "+jwombat);
541.595 - checkSize(test,server,newCount+1);
541.596 -
541.597 - popADD(queue, jwombat, test);
541.598 - if (queue.peek() != null)
541.599 - fail(test+"Received unexpected notifications: "+queue);
541.600 -
541.601 -
541.602 - int platcount = 0;
541.603 - for (String dom : platformDomains) {
541.604 - final Set<ObjectName> found =
541.605 - server.queryNames(new ObjectName(dom+":*"),null);
541.606 - final int jcount = found.size();
541.607 - System.out.println(test+"Found "+jcount+" MBeans in "+dom+
541.608 - ": "+found);
541.609 - checkSize(test,server,newCount+1);
541.610 - platcount += (jcount-1);
541.611 - }
541.612 - checkSize(test,server,oldCount+platcount);
541.613 -
541.614 - final ObjectName owombat = new ObjectName("custom:type=Wombat");
541.615 - server.createMBean("Wombat", owombat);
541.616 - System.out.println(test+"Created "+owombat);
541.617 - checkSize(test,server,newCount+2);
541.618 - popADD(queue, owombat, test);
541.619 - if (queue.peek() != null)
541.620 - fail(test+"Received unexpected notifications: "+queue);
541.621 -
541.622 - final Set<ObjectName> jwombatView = (Set<ObjectName>)
541.623 - server.invoke(jwombat, "listMatching", new Object[] {null},
541.624 - new String[] {ObjectName.class.getName()});
541.625 - System.out.println(test+jwombat+" sees: "+jwombatView);
541.626 - checkSize(test, server, newCount+2);
541.627 - if (jwombatView.size() != (platcount+1))
541.628 - fail(test+jwombat+" sees "+jwombatView.size()+" MBeans - should" +
541.629 - " have seen "+(platcount+1));
541.630 -
541.631 - final Set<ObjectName> platformMBeans =
541.632 - ManagementFactory.getPlatformMBeanServer().
541.633 - queryNames(null, null);
541.634 - if (!platformMBeans.equals(jwombatView))
541.635 - fail(test+jwombat+" should have seen "+platformMBeans);
541.636 -
541.637 - // check that awombat triggers loading of bwombats
541.638 - final Set<ObjectName> awombatView = (Set<ObjectName>)
541.639 - server.invoke(awombat, "listMatching", new Object[] {null},
541.640 - new String[] {ObjectName.class.getName()});
541.641 - System.out.println(test+awombat+" sees: "+awombatView);
541.642 - final int totalCount = newCount+2+customCount;
541.643 - checkSize(test, server, totalCount);
541.644 - if (awombatView.size() != totalCount)
541.645 - fail(test+jwombat+" sees "+jwombatView.size()+" MBeans - should" +
541.646 - " have seen "+totalCount);
541.647 -
541.648 - final Set<ObjectName> allMBeans = server.
541.649 - queryNames(null, null);
541.650 - if (!allMBeans.equals(awombatView))
541.651 - fail(test+awombat+" should have seen "+allMBeans);
541.652 -
541.653 - System.out.println(test + " PASSED");
541.654 -
541.655 - }
541.656 -
541.657 -
541.658 - public static void lazyStarterTest() throws Exception {
541.659 - final String test = "lazyStarterTest: ";
541.660 - System.out.println("" +
541.661 - "\nThis test checks that it is possible to perform lazy loading" +
541.662 - "\nof MBeans in a given domain by using a transient JMXDomain" +
541.663 - "\nsubclass for that domain. ");
541.664 -
541.665 - System.out.println(test + " START");
541.666 -
541.667 - // The "global" MBeanServer...
541.668 - final MBeanServer platform =
541.669 - ManagementFactory.getPlatformMBeanServer();
541.670 -
541.671 - // A notification queue.
541.672 - final BlockingQueue<Notification> queue =
541.673 - new ArrayBlockingQueue<Notification>(100);
541.674 -
541.675 - // A listener that puts notifs in the queue.
541.676 - final NotificationListener l = new NotificationListener() {
541.677 -
541.678 - public void handleNotification(Notification notification,
541.679 - Object handback) {
541.680 - try {
541.681 - if (!queue.offer(notification, 5, TimeUnit.SECONDS)) {
541.682 - throw new RuntimeException("timeout exceeded");
541.683 - }
541.684 - } catch (Exception x) {
541.685 - fail(test + "failed to handle notif", x);
541.686 - }
541.687 - }
541.688 - };
541.689 -
541.690 - System.out.println(test+" registering listener with delegate.");
541.691 - platform.addNotificationListener(MBeanServerDelegate.DELEGATE_NAME, l,
541.692 - null, null);
541.693 -
541.694 - final String ld1 = "lazy1";
541.695 - final String ld2 = "lazy2";
541.696 - final int wCount = 5;
541.697 - final LazyStarterDomain lazy1 = new LazyStarterDomain() {
541.698 - @Override
541.699 - protected void loadMBeans(MBeanServer server, String domain) {
541.700 - registerWombats(server, ld1, wCount);
541.701 - }
541.702 - };
541.703 - final LazyStarterDomain lazy2 = new LazyStarterDomain() {
541.704 - @Override
541.705 - protected void loadMBeans(MBeanServer server, String domain) {
541.706 - registerWombats(server, ld2, wCount);
541.707 - }
541.708 - };
541.709 - final ObjectName lo1 = JMXDomain.getDomainObjectName(ld1);
541.710 - final ObjectName lo2 = JMXDomain.getDomainObjectName(ld2);
541.711 -
541.712 - final int initial = platform.getMBeanCount();
541.713 -
541.714 - platform.registerMBean(lazy1, lo1);
541.715 - System.out.println(test+"registered "+lo1);
541.716 - checkSize(test, platform, initial+1);
541.717 - popADD(queue, lo1, test);
541.718 -
541.719 - platform.registerMBean(lazy2, lo2);
541.720 - System.out.println(test+"registered "+lo2);
541.721 - checkSize(test, platform, initial+2);
541.722 - popADD(queue, lo2, test);
541.723 -
541.724 -
541.725 - final ObjectName awombat = new ObjectName(
541.726 - ld1+":type=Wombat,name=wombat#"+wCount/2);
541.727 - if (!platform.isRegistered(awombat))
541.728 - fail(test+"Expected "+awombat+" to be reggistered!");
541.729 - checkSize(test,platform,initial+wCount+1);
541.730 - popREM(queue, lo1, test);
541.731 - final ObjectName pat1 =
541.732 - new ObjectName(ld1+":type=Wombat,name=wombat#*");
541.733 - for (int i=0;i<wCount;i++) {
541.734 - popADD(queue,pat1,test);
541.735 - }
541.736 - System.out.println(test+"Found: "+
541.737 - platform.queryNames(pat1,null));
541.738 - checkSize(test,platform,initial+wCount+1);
541.739 -
541.740 - final Set<ObjectName> all = platform.queryNames(null, null);
541.741 - popREM(queue, lo2, test);
541.742 - System.out.println(test+"Now found: "+all);
541.743 - checkSize(test,platform,initial+wCount+wCount);
541.744 - final ObjectName pat2 =
541.745 - new ObjectName(ld2+":type=Wombat,name=wombat#*");
541.746 - for (int i=0;i<wCount;i++) {
541.747 - popADD(queue,pat2,test);
541.748 - }
541.749 -
541.750 - System.out.println(test+"check concurrent modification " +
541.751 - "of the DomainDispatcher.");
541.752 - System.out.println(test+"This will fail if the DomainDispatcher" +
541.753 - " doesn't allow concurrent modifications.");
541.754 - final HashMap<String,LazyStarterDomain> testConcurrent =
541.755 - new HashMap<String,LazyStarterDomain>();
541.756 - for (int i=0;i<(100/wCount);i++) {
541.757 - final String ld = "concurrent.lazy"+i;
541.758 - final LazyStarterDomain lazy = new LazyStarterDomain() {
541.759 - @Override
541.760 - protected void loadMBeans(MBeanServer server, String domain) {
541.761 - registerWombats(server, ld, wCount-1);
541.762 - }
541.763 - };
541.764 - testConcurrent.put(ld, lazy);
541.765 - final ObjectName lo = JMXDomain.getDomainObjectName(ld);
541.766 - platform.registerMBean(lazy, lo);
541.767 - popADD(queue, lo, test);
541.768 - }
541.769 -
541.770 - System.out.println(test+"Big autoload: "+
541.771 - platform.queryNames(null,null));
541.772 - System.out.println(test+"Big after load: "+
541.773 - platform.queryNames(null,null));
541.774 - if (!platform.queryNames(JMXDomain.getDomainObjectName("*"), null).
541.775 - isEmpty()) {
541.776 - fail(test+" some domains are still here: "+
541.777 - platform.queryNames(
541.778 - JMXDomain.getDomainObjectName("*"), null));
541.779 - }
541.780 - queue.clear();
541.781 - System.out.println(test+"PASSED: The DomainDispatcher appears to be " +
541.782 - "resilient to concurrent modifications.");
541.783 - }
541.784 -
541.785 - public static void main(String... args) throws Exception {
541.786 -
541.787 - lazyTest();
541.788 - lazyStarterTest();
541.789 -
541.790 - if (lastException != null)
541.791 - throw lastException;
541.792 - }
541.793 -}
542.1 --- a/test/javax/management/namespace/LeadingSeparatorsTest.java Mon Nov 23 10:04:47 2009 +0000
542.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
542.3 @@ -1,238 +0,0 @@
542.4 -/*
542.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
542.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
542.7 - *
542.8 - * This code is free software; you can redistribute it and/or modify it
542.9 - * under the terms of the GNU General Public License version 2 only, as
542.10 - * published by the Free Software Foundation.
542.11 - *
542.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
542.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
542.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
542.15 - * version 2 for more details (a copy is included in the LICENSE file that
542.16 - * accompanied this code).
542.17 - *
542.18 - * You should have received a copy of the GNU General Public License version
542.19 - * 2 along with this work; if not, write to the Free Software Foundation,
542.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
542.21 - *
542.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
542.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
542.24 - * have any questions.
542.25 - */
542.26 -/*
542.27 - * @test LeadingSeparatorsTest.java
542.28 - * @summary Test that the semantics of a leading // in ObjectName is respected.
542.29 - * @author Daniel Fuchs
542.30 - * @bug 5072476 6768935
542.31 - * @run clean LeadingSeparatorsTest Wombat WombatMBean
542.32 - * @compile -XDignore.symbol.file=true LeadingSeparatorsTest.java
542.33 - * @run build LeadingSeparatorsTest Wombat WombatMBean
542.34 - * @run main LeadingSeparatorsTest
542.35 - */
542.36 -
542.37 -import java.lang.management.ManagementFactory;
542.38 -import java.util.Arrays;
542.39 -import java.util.Set;
542.40 -import java.util.HashSet;
542.41 -import java.util.logging.Logger;
542.42 -import javax.management.InstanceNotFoundException;
542.43 -import javax.management.MBeanServer;
542.44 -import javax.management.MBeanServerFactory;
542.45 -import javax.management.NotCompliantMBeanException;
542.46 -import javax.management.ObjectName;
542.47 -import javax.management.namespace.JMXNamespaces;
542.48 -import javax.management.namespace.JMXRemoteNamespace;
542.49 -import javax.management.namespace.JMXNamespace;
542.50 -import javax.management.remote.JMXConnectorServer;
542.51 -import javax.management.remote.JMXConnectorServerFactory;
542.52 -import javax.management.remote.JMXServiceURL;
542.53 -
542.54 -/**
542.55 - * Class LeadingSeparatorsTest
542.56 - * @author Sun Microsystems, 2005 - All rights reserved.
542.57 - */
542.58 -public class LeadingSeparatorsTest {
542.59 -
542.60 - /**
542.61 - * A logger for this class.
542.62 - **/
542.63 - private static final Logger LOG =
542.64 - Logger.getLogger(LeadingSeparatorsTest.class.getName());
542.65 -
542.66 - /** Creates a new instance of NullObjectNameTest */
542.67 - public LeadingSeparatorsTest() {
542.68 - }
542.69 -
542.70 - public static interface MyWombatMBean extends WombatMBean {
542.71 - public Set<ObjectName> untrue(ObjectName pat) throws Exception;
542.72 - }
542.73 - public static class MyWombat
542.74 - extends Wombat implements MyWombatMBean {
542.75 - public MyWombat() throws NotCompliantMBeanException {
542.76 - super(MyWombatMBean.class);
542.77 - }
542.78 -
542.79 - public Set<ObjectName> untrue(ObjectName pat) throws Exception {
542.80 - final Set<ObjectName> res=listMatching(pat.withDomain("*"));
542.81 - final Set<ObjectName> untrue = new HashSet<ObjectName>();
542.82 - for (ObjectName a:res) {
542.83 - untrue.add(a.withDomain(pat.getDomain()+"//"+a.getDomain()));
542.84 - }
542.85 - return untrue;
542.86 - }
542.87 - }
542.88 -
542.89 - static String failure=null;
542.90 -
542.91 - public static void testRegister() throws Exception {
542.92 - final MBeanServer top = ManagementFactory.getPlatformMBeanServer();
542.93 - final MBeanServer sub = MBeanServerFactory.createMBeanServer();
542.94 - final JMXServiceURL url = new JMXServiceURL("rmi",null,0);
542.95 - final JMXConnectorServer srv =
542.96 - JMXConnectorServerFactory.newJMXConnectorServer(url,null,sub);
542.97 - srv.start();
542.98 -
542.99 - try {
542.100 -
542.101 - // Create a namespace rmi// that points to 'sub' and flows through
542.102 - // a JMXRemoteNamespace connected to 'srv'
542.103 - // The namespace rmi// will accept createMBean, but not registerMBean.
542.104 - //
542.105 - final JMXRemoteNamespace rmiHandler = JMXRemoteNamespace.
542.106 - newJMXRemoteNamespace(srv.getAddress(),null);
542.107 - top.registerMBean(rmiHandler,
542.108 - JMXNamespaces.getNamespaceObjectName("rmi"));
542.109 - top.invoke(JMXNamespaces.getNamespaceObjectName("rmi"),
542.110 - "connect", null, null);
542.111 -
542.112 - // Create a namespace direct// that points to 'sub' and flows
542.113 - // through a direct reference to 'sub'.
542.114 - // The namespace direct// will accept createMBean, and registerMBean.
542.115 - //
542.116 - final JMXNamespace directHandler = new JMXNamespace(sub);
542.117 - top.registerMBean(directHandler,
542.118 - JMXNamespaces.getNamespaceObjectName("direct"));
542.119 -
542.120 - final ObjectName n1 = new ObjectName("//direct//w:type=Wombat");
542.121 - final ObjectName n2 = new ObjectName("direct//w:type=Wombat");
542.122 - final ObjectName n3 = new ObjectName("//rmi//w:type=Wombat");
542.123 - final ObjectName n4 = new ObjectName("rmi//w:type=Wombat");
542.124 -
542.125 - // register wombat using an object name with a leading //
542.126 - final Object obj = new MyWombat();
542.127 - // check that returned object name doesn't have the leading //
542.128 - assertEquals(n2,top.registerMBean(obj, n2).getObjectName());
542.129 - System.out.println(n1+" registered");
542.130 -
542.131 - // check that the registered Wombat can be accessed with all its
542.132 - // names.
542.133 - System.out.println(n2+" mood is: "+top.getAttribute(n2, "Mood"));
542.134 - try {
542.135 - System.out.println(n1+" mood is: "+top.getAttribute(n1, "Mood"));
542.136 - throw new Exception("Excepected exception not thrown for "+n1);
542.137 - } catch (InstanceNotFoundException x) {
542.138 - System.out.println("OK: "+x);
542.139 - }
542.140 - System.out.println(n4+" mood is: "+top.getAttribute(n4, "Mood"));
542.141 - try {
542.142 - System.out.println(n3+" mood is: "+top.getAttribute(n3, "Mood"));
542.143 - throw new Exception("Excepected exception not thrown for "+n3);
542.144 - } catch (InstanceNotFoundException x) {
542.145 - System.out.println("OK: "+x);
542.146 - }
542.147 -
542.148 - // call listMatching. The result should not contain any prefix.
542.149 - final Set<ObjectName> res = (Set<ObjectName>)
542.150 - top.invoke(n4, "listMatching",
542.151 - // remove rmi// from rmi//*:*
542.152 - JMXNamespaces.deepReplaceHeadNamespace(
542.153 - new Object[] {ObjectName.WILDCARD.withDomain("rmi//*")},
542.154 - "rmi", ""), new String[] {ObjectName.class.getName()});
542.155 -
542.156 - // add rmi// prefix to all names in res.
542.157 - final Set<ObjectName> res1 =
542.158 - JMXNamespaces.deepReplaceHeadNamespace(res, "", "rmi");
542.159 - System.out.println("got: "+res1);
542.160 -
542.161 - // compute expected result
542.162 - final Set<ObjectName> res2 = sub.queryNames(null,null);
542.163 - final Set<ObjectName> res3 = new HashSet<ObjectName>();
542.164 - for (ObjectName o:res2) {
542.165 - res3.add(o.withDomain("rmi//"+o.getDomain()));
542.166 - }
542.167 - System.out.println("expected: "+res3);
542.168 - assertEquals(res1, res3);
542.169 -
542.170 - // invoke "untrue(//niark//niark:*)"
542.171 - // should return a set were all ObjectNames begin with
542.172 - // //niark//niark//
542.173 - //
542.174 - final Set<ObjectName> res4 = (Set<ObjectName>)
542.175 - top.invoke(n4, "untrue",
542.176 - // remove niark//niark : should remove nothing since
542.177 - // our ObjectName begins with a leading //
542.178 - JMXNamespaces.deepReplaceHeadNamespace(
542.179 - new Object[] {
542.180 - ObjectName.WILDCARD.withDomain("//niark//niark")},
542.181 - "niark//niark", ""),
542.182 - new String[] {ObjectName.class.getName()});
542.183 - System.out.println("got: "+res4);
542.184 -
542.185 - // add rmi// should add nothing since the returned names have a
542.186 - // leading //
542.187 - //
542.188 - final Set<ObjectName> res5 =
542.189 - JMXNamespaces.deepReplaceHeadNamespace(res4, "", "rmi");
542.190 - System.out.println("got#2: "+res5);
542.191 -
542.192 - // compute expected result
542.193 - final Set<ObjectName> res6 = new HashSet<ObjectName>();
542.194 - for (ObjectName o:res2) {
542.195 - res6.add(o.withDomain("//niark//niark//"+o.getDomain()));
542.196 - }
542.197 - System.out.println("expected: "+res6);
542.198 -
542.199 - // both res4 and res5 should be equals to the expected result.
542.200 - assertEquals(res4, res6);
542.201 - assertEquals(res5, res6);
542.202 -
542.203 - } finally {
542.204 - srv.stop();
542.205 - }
542.206 -
542.207 - if (failure != null)
542.208 - throw new Exception(failure);
542.209 -
542.210 -
542.211 - }
542.212 - private static void assertEquals(Object x, Object y) {
542.213 - if (!equal(x, y))
542.214 - failed("expected " + string(x) + "; got " + string(y));
542.215 - }
542.216 -
542.217 - private static boolean equal(Object x, Object y) {
542.218 - if (x == y)
542.219 - return true;
542.220 - if (x == null || y == null)
542.221 - return false;
542.222 - if (x.getClass().isArray())
542.223 - return Arrays.deepEquals(new Object[] {x}, new Object[] {y});
542.224 - return x.equals(y);
542.225 - }
542.226 -
542.227 - private static String string(Object x) {
542.228 - String s = Arrays.deepToString(new Object[] {x});
542.229 - return s.substring(1, s.length() - 1);
542.230 - }
542.231 -
542.232 -
542.233 - private static void failed(String why) {
542.234 - failure = why;
542.235 - new Throwable("FAILED: " + why).printStackTrace(System.out);
542.236 - }
542.237 -
542.238 - public static void main(String[] args) throws Exception {
542.239 - testRegister();
542.240 - }
542.241 -}
543.1 --- a/test/javax/management/namespace/MXBeanRefTest.java Mon Nov 23 10:04:47 2009 +0000
543.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
543.3 @@ -1,181 +0,0 @@
543.4 -/*
543.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
543.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
543.7 - *
543.8 - * This code is free software; you can redistribute it and/or modify it
543.9 - * under the terms of the GNU General Public License version 2 only, as
543.10 - * published by the Free Software Foundation.
543.11 - *
543.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
543.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
543.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
543.15 - * version 2 for more details (a copy is included in the LICENSE file that
543.16 - * accompanied this code).
543.17 - *
543.18 - * You should have received a copy of the GNU General Public License version
543.19 - * 2 along with this work; if not, write to the Free Software Foundation,
543.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
543.21 - *
543.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
543.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
543.24 - * have any questions.
543.25 - */
543.26 -/*
543.27 - * @test MXBeanRefTest.java
543.28 - * @bug 5072476
543.29 - * @summary Test that MXBean proxy references work correctly in the presence
543.30 - * of namespaces.
543.31 - * @author Eamonn Mcmanus
543.32 - */
543.33 -
543.34 -/**
543.35 - * The idea is that we will create a hierarchy like this:
543.36 - * a//
543.37 - * X
543.38 - * b//
543.39 - * Y
543.40 - * Z
543.41 - * and we will use MXBean references so we have links like this:
543.42 - * a//
543.43 - * X----+
543.44 - * b// |
543.45 - * /
543.46 - * Y
543.47 - * \
543.48 - * /
543.49 - * Z
543.50 - * In other words, X.getY() will return a proxy for Y, which the MXBean
543.51 - * framework will map to b//Y. A proxy for a//X should then map this
543.52 - * into a proxy for a//b//Y. That's easy. But then if we call getZ()
543.53 - * on this proxy, the MXBean framework will return just Z, and the proxy
543.54 - * must map that into a proxy for a//b//Z.
543.55 - */
543.56 -
543.57 -import java.lang.management.ManagementFactory;
543.58 -import java.lang.reflect.InvocationHandler;
543.59 -import java.lang.reflect.Proxy;
543.60 -import java.lang.reflect.UndeclaredThrowableException;
543.61 -import javax.management.JMX;
543.62 -import javax.management.MBeanServer;
543.63 -import javax.management.MBeanServerConnection;
543.64 -import javax.management.MBeanServerFactory;
543.65 -import javax.management.MBeanServerInvocationHandler;
543.66 -import javax.management.ObjectName;
543.67 -import javax.management.namespace.JMXNamespace;
543.68 -import javax.management.namespace.JMXNamespaces;
543.69 -import javax.management.openmbean.OpenDataException;
543.70 -
543.71 -public class MXBeanRefTest {
543.72 -
543.73 - public static interface ZMXBean {
543.74 - public void success();
543.75 - }
543.76 - public static class ZImpl implements ZMXBean {
543.77 - public void success() {}
543.78 - }
543.79 -
543.80 - public static interface YMXBean {
543.81 - public ZMXBean getZ();
543.82 - public void setZ(ZMXBean z);
543.83 - }
543.84 - public static class YImpl implements YMXBean {
543.85 - private ZMXBean z;
543.86 -
543.87 - public YImpl(ZMXBean z) {
543.88 - this.z = z;
543.89 - }
543.90 -
543.91 - public ZMXBean getZ() {
543.92 - return z;
543.93 - }
543.94 -
543.95 - public void setZ(ZMXBean z) {
543.96 - this.z = z;
543.97 - }
543.98 - }
543.99 -
543.100 - public static interface XMXBean {
543.101 - public YMXBean getY();
543.102 - }
543.103 - public static class XImpl implements XMXBean {
543.104 - private final YMXBean yProxy;
543.105 -
543.106 - public XImpl(YMXBean yProxy) {
543.107 - this.yProxy = yProxy;
543.108 - }
543.109 -
543.110 - public YMXBean getY() {
543.111 - return yProxy;
543.112 - }
543.113 - }
543.114 -
543.115 - public static void main(String[] args) throws Exception {
543.116 - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
543.117 -
543.118 - // Set up namespace hierarchy a//b//
543.119 - MBeanServer ambs = MBeanServerFactory.newMBeanServer();
543.120 - MBeanServer bmbs = MBeanServerFactory.newMBeanServer();
543.121 - JMXNamespace bHandler = new JMXNamespace(bmbs);
543.122 - ObjectName bHandlerName = JMXNamespaces.getNamespaceObjectName("b");
543.123 - System.out.println(bHandlerName);
543.124 - ambs.registerMBean(bHandler, bHandlerName);
543.125 - JMXNamespace aHandler = new JMXNamespace(ambs);
543.126 - ObjectName aHandlerName = JMXNamespaces.getNamespaceObjectName("a");
543.127 - mbs.registerMBean(aHandler, aHandlerName);
543.128 -
543.129 - ZMXBean z = new ZImpl();
543.130 - ObjectName zName = new ObjectName("foo:type=Z");
543.131 - bmbs.registerMBean(z, zName);
543.132 -
543.133 - YMXBean y = new YImpl(z);
543.134 - ObjectName yName = new ObjectName("foo:type=Y");
543.135 - bmbs.registerMBean(y, yName);
543.136 -
543.137 - ObjectName yNameInA = new ObjectName("b//" + yName);
543.138 - System.out.println("MBeanInfo for Y as seen from a//:");
543.139 - System.out.println(ambs.getMBeanInfo(yNameInA));
543.140 - YMXBean yProxyInA = JMX.newMXBeanProxy(ambs, yNameInA, YMXBean.class);
543.141 - XMXBean x = new XImpl(yProxyInA);
543.142 - ObjectName xName = new ObjectName("foo:type=X");
543.143 - ambs.registerMBean(x, xName);
543.144 -
543.145 - ObjectName xNameFromTop = new ObjectName("a//" + xName);
543.146 - XMXBean xProxy = JMX.newMXBeanProxy(mbs, xNameFromTop, XMXBean.class);
543.147 - System.out.println("Name of X Proxy: " + proxyName(xProxy));
543.148 - YMXBean yProxy = xProxy.getY();
543.149 - System.out.println("Name of Y Proxy: " + proxyName(yProxy));
543.150 - ZMXBean zProxy = yProxy.getZ();
543.151 - System.out.println("Name of Z Proxy: " + proxyName(zProxy));
543.152 -
543.153 - System.out.println("Operation through Z proxy...");
543.154 - zProxy.success();
543.155 -
543.156 - System.out.println("Changing Y's ref to Z...");
543.157 - yProxy.setZ(zProxy);
543.158 - zProxy = yProxy.getZ();
543.159 - System.out.println("Name of Z Proxy now: " + proxyName(zProxy));
543.160 - System.out.println("Operation through Z proxy again...");
543.161 - zProxy.success();
543.162 -
543.163 - System.out.println("Changing Y's ref to a bogus one...");
543.164 - ZMXBean zProxyBad = JMX.newMXBeanProxy(mbs, zName, ZMXBean.class);
543.165 - try {
543.166 - yProxy.setZ(zProxyBad);
543.167 - } catch (UndeclaredThrowableException e) {
543.168 - Throwable cause = e.getCause();
543.169 - if (cause instanceof OpenDataException) {
543.170 - System.out.println("...correctly got UndeclaredThrowableException");
543.171 - System.out.println("...wrapping: " + cause);
543.172 - } else
543.173 - throw new Exception("FAILED: wrong exception: " + cause);
543.174 - }
543.175 -
543.176 - System.out.println("Test passed");
543.177 - }
543.178 -
543.179 - private static ObjectName proxyName(Object proxy) {
543.180 - InvocationHandler ih = Proxy.getInvocationHandler(proxy);
543.181 - MBeanServerInvocationHandler mbsih = (MBeanServerInvocationHandler) ih;
543.182 - return mbsih.getObjectName();
543.183 - }
543.184 -}
544.1 --- a/test/javax/management/namespace/NamespaceController.java Mon Nov 23 10:04:47 2009 +0000
544.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
544.3 @@ -1,405 +0,0 @@
544.4 -/*
544.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
544.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
544.7 - *
544.8 - * This code is free software; you can redistribute it and/or modify it
544.9 - * under the terms of the GNU General Public License version 2 only, as
544.10 - * published by the Free Software Foundation. Sun designates this
544.11 - * particular file as subject to the "Classpath" exception as provided
544.12 - * by Sun in the LICENSE file that accompanied this code.
544.13 - *
544.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
544.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
544.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
544.17 - * version 2 for more details (a copy is included in the LICENSE file that
544.18 - * accompanied this code).
544.19 - *
544.20 - * You should have received a copy of the GNU General Public License version
544.21 - * 2 along with this work; if not, write to the Free Software Foundation,
544.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
544.23 - *
544.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
544.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
544.26 - * have any questions.
544.27 - */
544.28 -
544.29 -import com.sun.jmx.namespace.ObjectNameRouter;
544.30 -import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR;
544.31 -
544.32 -import java.io.IOException;
544.33 -import java.util.Arrays;
544.34 -import java.util.Map;
544.35 -import java.util.Set;
544.36 -import java.util.TreeSet;
544.37 -import java.util.logging.Level;
544.38 -import java.util.logging.Logger;
544.39 -
544.40 -import javax.management.InstanceAlreadyExistsException;
544.41 -import javax.management.InstanceNotFoundException;
544.42 -import javax.management.JMX;
544.43 -import javax.management.ListenerNotFoundException;
544.44 -import javax.management.MBeanException;
544.45 -import javax.management.MBeanNotificationInfo;
544.46 -import javax.management.MBeanRegistration;
544.47 -import javax.management.MBeanRegistrationException;
544.48 -import javax.management.MBeanServer;
544.49 -import javax.management.MBeanServerConnection;
544.50 -import javax.management.MalformedObjectNameException;
544.51 -import javax.management.NotCompliantMBeanException;
544.52 -import javax.management.Notification;
544.53 -import javax.management.NotificationBroadcasterSupport;
544.54 -import javax.management.NotificationEmitter;
544.55 -import javax.management.NotificationFilter;
544.56 -import javax.management.NotificationListener;
544.57 -import javax.management.ObjectInstance;
544.58 -import javax.management.ObjectName;
544.59 -import javax.management.ReflectionException;
544.60 -import javax.management.namespace.JMXNamespace;
544.61 -import javax.management.namespace.JMXNamespaces;
544.62 -import javax.management.namespace.JMXRemoteNamespaceMBean;
544.63 -import javax.management.remote.JMXServiceURL;
544.64 -
544.65 -/**
544.66 - * The {@code NamespaceController} MBean makes it possible to easily
544.67 - * create mount points ({@linkplain JMXNamespace JMXNamespaces}) in an
544.68 - * {@code MBeanServer}.
544.69 - * There is at most one instance of NamespaceController in an
544.70 - * MBeanServer - which can be created using the {@link #createInstance
544.71 - * createInstance} method. The {@code NamespaceController} MBean will
544.72 - * make it possible to remotely create name spaces by mounting remote
544.73 - * MBeanServers into the MBeanServer in which it was registered.
544.74 - */
544.75 -// This API was originally in the draft of javax/management/namespaces
544.76 -// but we decided to retire it. Rather than removing all the associated
544.77 -// tests I have moved the API to the test hierarchy - so it is now used as
544.78 -// an additional (though somewhat complex) test case...
544.79 -//
544.80 -public class NamespaceController implements NamespaceControllerMBean,
544.81 - NotificationEmitter, MBeanRegistration {
544.82 -
544.83 - /**
544.84 - * A logger for this class.
544.85 - **/
544.86 - private static final Logger LOG =
544.87 - Logger.getLogger(NamespaceController.class.getName());
544.88 -
544.89 - private static long seqNumber=0;
544.90 -
544.91 - private final NotificationBroadcasterSupport broadcaster =
544.92 - new NotificationBroadcasterSupport();
544.93 -
544.94 - private volatile MBeanServer mbeanServer = null;
544.95 -
544.96 - private volatile ObjectName objectName = null;
544.97 -
544.98 - //was: NamespaceController.class.getPackage().getName()
544.99 - public static final String NAMESPACE_CONTROLLER_DOMAIN = "jmx.ns";
544.100 -
544.101 - /**
544.102 - * Creates a new NamespaceController.
544.103 - * Using {@link #createInstance} should be preferred.
544.104 - **/
544.105 - public NamespaceController() {
544.106 - this(null);
544.107 - }
544.108 -
544.109 - public NamespaceController(MBeanServer mbeanServer) {
544.110 - this.mbeanServer = mbeanServer;
544.111 - }
544.112 -
544.113 - /*
544.114 - * MBeanNotification support
544.115 - * You shouldn't update these methods
544.116 - */
544.117 - public final void addNotificationListener(NotificationListener listener,
544.118 - NotificationFilter filter, Object handback) {
544.119 - broadcaster.addNotificationListener(listener, filter, handback);
544.120 - }
544.121 -
544.122 - public MBeanNotificationInfo[] getNotificationInfo() {
544.123 - return new MBeanNotificationInfo[] {
544.124 - };
544.125 - }
544.126 -
544.127 - public final void removeNotificationListener(NotificationListener listener)
544.128 - throws ListenerNotFoundException {
544.129 - broadcaster.removeNotificationListener(listener);
544.130 - }
544.131 -
544.132 - public final void removeNotificationListener(NotificationListener listener,
544.133 - NotificationFilter filter, Object handback)
544.134 - throws ListenerNotFoundException {
544.135 - broadcaster.removeNotificationListener(listener, filter, handback);
544.136 - }
544.137 -
544.138 - public static synchronized long getNextSeqNumber() {
544.139 - return seqNumber++;
544.140 - }
544.141 -
544.142 - protected final void sendNotification(Notification n) {
544.143 - if (n.getSequenceNumber()<=0)
544.144 - n.setSequenceNumber(getNextSeqNumber());
544.145 - if (n.getSource()==null)
544.146 - n.setSource(objectName);
544.147 - broadcaster.sendNotification(n);
544.148 - }
544.149 -
544.150 - /**
544.151 - * The ObjectName with which this MBean was registered.
544.152 - * <p>Unless changed by subclasses, this is
544.153 - * {@code
544.154 - * "javax.management.namespace:type="+this.getClass().getSimpleName()}.
544.155 - * @return this MBean's ObjectName, or null if this MBean was never
544.156 - * registered.
544.157 - **/
544.158 - public final ObjectName getObjectName() {
544.159 - return objectName;
544.160 - }
544.161 -
544.162 - /**
544.163 - * The MBeanServer served by this NamespaceController.
544.164 - * @return the MBeanServer served by this NamespaceController.
544.165 - **/
544.166 - public final MBeanServer getMBeanServer() {
544.167 - return mbeanServer;
544.168 - }
544.169 -
544.170 - /**
544.171 - * Allows the MBean to perform any operations it needs before being
544.172 - * registered in the MBean server. If the name of the MBean is not
544.173 - * specified, the MBean can provide a name for its registration. If
544.174 - * any exception is raised, the MBean will not be registered in the
544.175 - * MBean server. Subclasses which override {@code preRegister}
544.176 - * must call {@code super.preRegister(name,server)};
544.177 - * @param server The MBean server in which the MBean will be registered.
544.178 - * @param name The object name of the MBean.
544.179 - * The name must be either {@code null} - or equal to that
544.180 - * described by {@link #getObjectName}.
544.181 - * @return The name under which the MBean is to be registered.
544.182 - * This will be the name described by {@link #getObjectName}.
544.183 - * @throws MalformedObjectNameException if the supplied name does not
544.184 - * meet expected requirements.
544.185 - */
544.186 - public ObjectName preRegister(MBeanServer server, ObjectName name)
544.187 - throws MalformedObjectNameException {
544.188 - objectName = name;
544.189 - final ObjectName single =
544.190 - ObjectName.getInstance(NAMESPACE_CONTROLLER_DOMAIN+
544.191 - ":type="+this.getClass().getSimpleName());
544.192 - if (name!=null && !single.equals(name))
544.193 - throw new MalformedObjectNameException(name.toString());
544.194 - if (mbeanServer == null) mbeanServer = server;
544.195 - return single;
544.196 - }
544.197 -
544.198 - /**
544.199 - * Allows the MBean to perform any operations needed after having
544.200 - * been registered in the MBean server or after the registration has
544.201 - * failed.
544.202 - * @param registrationDone Indicates whether or not the MBean has been
544.203 - * successfully registered in the MBean server. The value false means
544.204 - * that the registration has failed.
544.205 - */
544.206 - public void postRegister(Boolean registrationDone) {
544.207 - //TODO postRegister implementation;
544.208 - }
544.209 -
544.210 - /**
544.211 - * Allows the MBean to perform any operations it needs before being
544.212 - * unregistered by the MBean server.
544.213 - * @throws Exception This exception will be caught by the MBean server and
544.214 - * re-thrown as an MBeanRegistrationException.
544.215 - */
544.216 - public void preDeregister() throws Exception {
544.217 - //TODO preDeregister implementation;
544.218 - }
544.219 -
544.220 - /**
544.221 - * Allows the MBean to perform any operations needed after having been
544.222 - * unregistered in the MBean server.
544.223 - */
544.224 - public void postDeregister() {
544.225 - //TODO postDeregister implementation;
544.226 - }
544.227 -
544.228 - public String mount(JMXServiceURL url,
544.229 - String targetPath,
544.230 - Map<String,Object> optionsMap)
544.231 - throws IOException {
544.232 - return mount(url, targetPath, "", optionsMap);
544.233 - }
544.234 -
544.235 - // see NamespaceControllerMBean
544.236 - public String mount(JMXServiceURL url,
544.237 - String targetPath,
544.238 - String sourcePath,
544.239 - Map<String,Object> optionsMap)
544.240 - throws IOException {
544.241 -
544.242 - // TODO: handle description.
544.243 - final String dirName =
544.244 - JMXNamespaces.normalizeNamespaceName(targetPath);
544.245 -
544.246 - try {
544.247 - final ObjectInstance moi =
544.248 - JMXRemoteTargetNamespace.createNamespace(mbeanServer,
544.249 - dirName,url,optionsMap,
544.250 - JMXNamespaces.normalizeNamespaceName(sourcePath)
544.251 - );
544.252 - final ObjectName nsMBean = moi.getObjectName();
544.253 - try {
544.254 - mbeanServer.invoke(nsMBean, "connect", null,null);
544.255 - } catch (Throwable t) {
544.256 - mbeanServer.unregisterMBean(nsMBean);
544.257 - throw t;
544.258 - }
544.259 - return getMountPointID(nsMBean);
544.260 - } catch (InstanceAlreadyExistsException x) {
544.261 - throw new IllegalArgumentException(targetPath,x);
544.262 - } catch (IOException x) {
544.263 - throw x;
544.264 - } catch (Throwable x) {
544.265 - if (x instanceof Error) throw (Error)x;
544.266 - Throwable cause = x.getCause();
544.267 - if (cause instanceof IOException)
544.268 - throw ((IOException)cause);
544.269 - if (cause == null) cause = x;
544.270 -
544.271 - final IOException io =
544.272 - new IOException("connect failed: "+cause);
544.273 - io.initCause(cause);
544.274 - throw io;
544.275 - }
544.276 - }
544.277 -
544.278 - private String getMountPointID(ObjectName dirName) {
544.279 - return dirName.toString();
544.280 - }
544.281 -
544.282 - private ObjectName getHandlerName(String mountPointID) {
544.283 - try {
544.284 - final ObjectName tryit = ObjectName.getInstance(mountPointID);
544.285 - final ObjectName formatted =
544.286 - JMXNamespaces.getNamespaceObjectName(tryit.getDomain());
544.287 - if (!formatted.equals(tryit))
544.288 - throw new IllegalArgumentException(mountPointID+
544.289 - ": invalid mountPointID");
544.290 - return formatted;
544.291 - } catch (MalformedObjectNameException x) {
544.292 - throw new IllegalArgumentException(mountPointID,x);
544.293 - }
544.294 - }
544.295 -
544.296 - public boolean unmount(String mountPointID)
544.297 - throws IOException {
544.298 - final ObjectName dirName = getHandlerName(mountPointID);
544.299 - if (!mbeanServer.isRegistered(dirName))
544.300 - throw new IllegalArgumentException(mountPointID+
544.301 - ": no such name space");
544.302 - final JMXRemoteNamespaceMBean mbean =
544.303 - JMX.newMBeanProxy(mbeanServer,dirName,
544.304 - JMXRemoteNamespaceMBean.class);
544.305 - try {
544.306 - mbean.close();
544.307 - } catch (IOException io) {
544.308 - LOG.fine("Failed to close properly - ignoring exception: "+io);
544.309 - LOG.log(Level.FINEST,
544.310 - "Failed to close properly - ignoring exception",io);
544.311 - } finally {
544.312 - try {
544.313 - mbeanServer.unregisterMBean(dirName);
544.314 - } catch (InstanceNotFoundException x) {
544.315 - throw new IllegalArgumentException(mountPointID+
544.316 - ": no such name space", x);
544.317 - } catch (MBeanRegistrationException x) {
544.318 - final IOException io =
544.319 - new IOException(mountPointID +": failed to unmount");
544.320 - io.initCause(x);
544.321 - throw io;
544.322 - }
544.323 - }
544.324 - return true;
544.325 - }
544.326 -
544.327 - public boolean ismounted(String targetPath) {
544.328 - return mbeanServer.isRegistered(JMXNamespaces.getNamespaceObjectName(targetPath));
544.329 - }
544.330 -
544.331 - public ObjectName getHandlerNameFor(String targetPath) {
544.332 - return JMXNamespaces.getNamespaceObjectName(targetPath);
544.333 - }
544.334 -
544.335 - public String[] findNamespaces() {
544.336 - return findNamespaces(null,null,0);
544.337 - }
544.338 -
544.339 -
544.340 - private ObjectName getDirPattern(String from) {
544.341 - try {
544.342 - if (from == null)
544.343 - return ObjectName.getInstance(ALL_NAMESPACES);
544.344 - final String namespace =
544.345 - ObjectNameRouter.normalizeNamespacePath(from,false,true,false);
544.346 - if (namespace.equals(""))
544.347 - return ObjectName.getInstance(ALL_NAMESPACES);
544.348 - if (JMXNamespaces.getNamespaceObjectName(namespace).isDomainPattern())
544.349 - throw new IllegalArgumentException(from);
544.350 - return ObjectName.getInstance(namespace+NAMESPACE_SEPARATOR+ALL_NAMESPACES);
544.351 - } catch (MalformedObjectNameException x) {
544.352 - throw new IllegalArgumentException(from,x);
544.353 - }
544.354 - }
544.355 -
544.356 - public String[] findNamespaces(String from, String regex, int depth) {
544.357 - if (depth < 0) return new String[0];
544.358 - final Set<String> res = new TreeSet<String>();
544.359 - final ObjectName all = getDirPattern(from);
544.360 - Set<ObjectName> names = mbeanServer.queryNames(all,null);
544.361 - for (ObjectName dirName : names) {
544.362 - final String dir = dirName.getDomain();
544.363 - if (regex == null || dir.matches(regex))
544.364 - res.add(dir);
544.365 - if (depth > 0)
544.366 - res.addAll(Arrays.asList(findNamespaces(dir,regex,depth-1)));
544.367 - }
544.368 - return res.toArray(new String[res.size()]);
544.369 - }
544.370 -
544.371 - /**
544.372 - * Creates a {@link NamespaceController} MBean in the provided
544.373 - * {@link MBeanServerConnection}.
544.374 - * <p>The name of the MBean is that returned by {@link #preRegister}
544.375 - * as described by {@link #getObjectName}.
544.376 - * @throws IOException if an {@code IOException} is raised when invoking
544.377 - * the provided connection.
544.378 - * @throws InstanceAlreadyExistsException if an MBean was already
544.379 - * registered with the NamespaceController's name.
544.380 - * @throws MBeanRegistrationException if thrown by {@link
544.381 - * MBeanServerConnection#createMBean(java.lang.String,javax.management.ObjectName)
544.382 - * server.createMBean}
544.383 - * @throws MBeanException if thrown by {@link
544.384 - * MBeanServerConnection#createMBean(java.lang.String,javax.management.ObjectName)
544.385 - * server.createMBean}
544.386 - * @return the {@link ObjectInstance}, as returned by {@link
544.387 - * MBeanServerConnection#createMBean(java.lang.String,javax.management.ObjectName)
544.388 - * server.createMBean}
544.389 - **/
544.390 - public static ObjectInstance createInstance(MBeanServerConnection server)
544.391 - throws IOException, InstanceAlreadyExistsException,
544.392 - MBeanRegistrationException, MBeanException {
544.393 - try {
544.394 - final ObjectInstance instance =
544.395 - server.createMBean(NamespaceController.class.getName(), null);
544.396 - return instance;
544.397 - } catch (NotCompliantMBeanException ex) {
544.398 - throw new RuntimeException("unexpected exception: " + ex, ex);
544.399 - } catch (ReflectionException ex) {
544.400 - throw new RuntimeException("unexpected exception: " + ex, ex);
544.401 - }
544.402 - }
544.403 -
544.404 - private final static String ALL_NAMESPACES=
544.405 - "*"+NAMESPACE_SEPARATOR+":"+
544.406 - JMXNamespace.TYPE_ASSIGNMENT;
544.407 -
544.408 -}
545.1 --- a/test/javax/management/namespace/NamespaceControllerMBean.java Mon Nov 23 10:04:47 2009 +0000
545.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
545.3 @@ -1,143 +0,0 @@
545.4 -/*
545.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
545.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
545.7 - *
545.8 - * This code is free software; you can redistribute it and/or modify it
545.9 - * under the terms of the GNU General Public License version 2 only, as
545.10 - * published by the Free Software Foundation. Sun designates this
545.11 - * particular file as subject to the "Classpath" exception as provided
545.12 - * by Sun in the LICENSE file that accompanied this code.
545.13 - *
545.14 - * This code is distributed in the hope that it will be useful, but WITHOUT
545.15 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
545.16 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
545.17 - * version 2 for more details (a copy is included in the LICENSE file that
545.18 - * accompanied this code).
545.19 - *
545.20 - * You should have received a copy of the GNU General Public License version
545.21 - * 2 along with this work; if not, write to the Free Software Foundation,
545.22 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
545.23 - *
545.24 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
545.25 - * CA 95054 USA or visit www.sun.com if you need additional information or
545.26 - * have any questions.
545.27 - */
545.28 -
545.29 -import java.io.IOException;
545.30 -import java.util.Map;
545.31 -
545.32 -import javax.management.ObjectName;
545.33 -import javax.management.remote.JMXServiceURL;
545.34 -
545.35 -/**
545.36 - * The {@link NamespaceController} MBean makes it possible to easily
545.37 - * create mount points ({@link JMXNamespace JMXNamespaces}) in an
545.38 - * {@code MBeanServer}.
545.39 - */
545.40 -// This API was originally in the draft of javax/management/namespaces
545.41 -// but we decided to retire it. Rather than removing all the associated
545.42 -// tests I have moved the API to the test hierarchy - so it is now used as
545.43 -// an additional (though somewhat complex) test case...
545.44 -//
545.45 -public interface NamespaceControllerMBean {
545.46 - /**
545.47 - * Mount MBeans from the source path of the source URL into the specified
545.48 - * target path of the target.
545.49 - * @param url URL of the mounted source.
545.50 - * @param targetPath Target path in which MBeans will be mounted.
545.51 - * @param optionsMap connection map and options. See {@link
545.52 - * javax.management.namespace.JMXRemoteNamespace.Options
545.53 - * JMXRemoteNamespace.Options}
545.54 - * @throws IOException Connection with the source failed
545.55 - * @throws IllegalArgumentException Supplied parameters are
545.56 - * illegal, or combination of supplied parameters is illegal.
545.57 - * @return A mount point id.
545.58 - */
545.59 - public String mount(JMXServiceURL url,
545.60 - String targetPath,
545.61 - Map<String,Object> optionsMap)
545.62 - throws IOException, IllegalArgumentException;
545.63 -
545.64 - /**
545.65 - * Mount MBeans from the source path of the source URL into the specified
545.66 - * target path of the target.
545.67 - * @param url URL of the mounted source.
545.68 - * @param targetPath Target path in which MBeans will be mounted.
545.69 - * @param sourcePath source namespace path.
545.70 - * @param optionsMap connection map and options. See {@link
545.71 - * javax.management.namespace.JMXRemoteNamespace.Options
545.72 - * JMXRemoteNamespace.Options}
545.73 - * @throws IOException Connection with the source failed
545.74 - * @throws IllegalArgumentException Supplied parameters are
545.75 - * illegal, or combination of supplied parameters is illegal.
545.76 - * @return A mount point id.
545.77 - */
545.78 - public String mount(JMXServiceURL url,
545.79 - String targetPath,
545.80 - String sourcePath,
545.81 - Map<String,Object> optionsMap)
545.82 - throws IOException, IllegalArgumentException;
545.83 -
545.84 - /**
545.85 - * Unmount a previously mounted mount point.
545.86 - * @param mountPointId A mount point id, as previously returned
545.87 - * by mount.
545.88 - * @throws IllegalArgumentException Supplied parameters are
545.89 - * illegal, or combination of supplied parameters is illegal.
545.90 - * @throws IOException thrown if the mount point {@link JMXNamespace}
545.91 - * couldn't be unregistered.
545.92 - */
545.93 - public boolean unmount(String mountPointId)
545.94 - throws IOException, IllegalArgumentException;
545.95 -
545.96 - /**
545.97 - * Tells whether there already exists a {@link JMXNamespace} for
545.98 - * the given <var>targetPath</var>.
545.99 - * @param targetPath a target name space path.
545.100 - * @return true if a {@link JMXNamespace} is registered for that
545.101 - * name space path.
545.102 - **/
545.103 - public boolean ismounted(String targetPath);
545.104 -
545.105 - /**
545.106 - * Returns the handler name for the provided target name space
545.107 - * path. Can throw IllegalArgumentException if the provided
545.108 - * targetPath contains invalid characters (like e.g. ':').
545.109 - * @param targetPath A target name space path.
545.110 - * @return the handler name for the provided target name space
545.111 - * path.
545.112 - **/
545.113 - public ObjectName getHandlerNameFor(String targetPath);
545.114 -
545.115 - /**
545.116 - * Return a sorted array of locally mounted name spaces.
545.117 - * This is equivalent to calling {@link
545.118 - * #findNamespaces(java.lang.String,java.lang.String,int)
545.119 - * findNamespaces(null,null,0)};
545.120 - * @return a sorted array of locally mounted name spaces.
545.121 - **/
545.122 - public String[] findNamespaces();
545.123 -
545.124 - /**
545.125 - * Return a sorted array of mounted name spaces, starting at
545.126 - * <var>from</var> (if non null), and recursively searching up to
545.127 - * provided <var>depth</var>.
545.128 - * @param from A name spaces from which to start the search. If null,
545.129 - * will start searching from the MBeanServer root.
545.130 - * If not null, all returned names will start with <var>from//</var>.
545.131 - * @param regex A regular expression that the returned names must match.
545.132 - * If null - no matching is performed and all found names are
545.133 - * returned. If not null, then all returned names satisfy
545.134 - * {@link String#matches name.matches(regex)};
545.135 - * @param depth the maximum number of levels that the search algorithm
545.136 - * will cross. 0 includes only top level name spaces, 1 top level
545.137 - * and first level children etc... <var>depth</var> is evaluated
545.138 - * with regard to where the search starts - if a non null
545.139 - * <var>from</var> parameter is provided - then {@code depth=0}
545.140 - * corresponds to all name spaces found right below
545.141 - * <var>from//</var>.
545.142 - * @return A sorted array of name spaces matching the provided criteria.
545.143 - * All returned names end with "//".
545.144 - **/
545.145 - public String[] findNamespaces(String from, String regex, int depth);
545.146 -}
546.1 --- a/test/javax/management/namespace/NamespaceCreationTest.java Mon Nov 23 10:04:47 2009 +0000
546.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
546.3 @@ -1,263 +0,0 @@
546.4 -/*
546.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
546.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
546.7 - *
546.8 - * This code is free software; you can redistribute it and/or modify it
546.9 - * under the terms of the GNU General Public License version 2 only, as
546.10 - * published by the Free Software Foundation.
546.11 - *
546.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
546.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
546.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
546.15 - * version 2 for more details (a copy is included in the LICENSE file that
546.16 - * accompanied this code).
546.17 - *
546.18 - * You should have received a copy of the GNU General Public License version
546.19 - * 2 along with this work; if not, write to the Free Software Foundation,
546.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
546.21 - *
546.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
546.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
546.24 - * have any questions.
546.25 - */
546.26 -/*
546.27 - *
546.28 - * @test NamespaceCreationTest.java
546.29 - * @summary General JMXNamespace test.
546.30 - * @author Daniel Fuchs
546.31 - * @bug 5072476
546.32 - * @run clean NamespaceCreationTest Wombat WombatMBean
546.33 - * @run build NamespaceCreationTest Wombat WombatMBean
546.34 - * @run main NamespaceCreationTest
546.35 - */
546.36 -
546.37 -
546.38 -import java.util.Collections;
546.39 -import java.util.Map;
546.40 -import javax.management.MBeanRegistration;
546.41 -import javax.management.MBeanRegistrationException;
546.42 -import javax.management.MBeanServer;
546.43 -import javax.management.MBeanServerFactory;
546.44 -import javax.management.ObjectInstance;
546.45 -import javax.management.ObjectName;
546.46 -import javax.management.RuntimeMBeanException;
546.47 -import javax.management.namespace.JMXNamespace;
546.48 -import javax.management.namespace.JMXNamespaces;
546.49 -
546.50 -/**
546.51 - * Test simple creation/registration of namespace.
546.52 - *
546.53 - */
546.54 -public class NamespaceCreationTest {
546.55 - private static Map<String,Object> emptyEnvMap() {
546.56 - return Collections.emptyMap();
546.57 - }
546.58 -
546.59 -
546.60 - public static class LocalNamespace extends JMXNamespace {
546.61 -
546.62 - public LocalNamespace() {
546.63 - super(MBeanServerFactory.newMBeanServer());
546.64 - }
546.65 -
546.66 - }
546.67 -
546.68 - private static MBeanServer newMBeanServer() {
546.69 - return MBeanServerFactory.newMBeanServer();
546.70 - }
546.71 -
546.72 - public static interface ThingMBean {}
546.73 - public static class Thing implements ThingMBean, MBeanRegistration {
546.74 - public ObjectName preRegister(MBeanServer server, ObjectName name)
546.75 - throws Exception {
546.76 - if (name == null) return new ObjectName(":type=Thing");
546.77 - else return name;
546.78 - }
546.79 - public void postRegister(Boolean registrationDone) {
546.80 - }
546.81 -
546.82 - public void preDeregister() throws Exception {
546.83 - }
546.84 - public void postDeregister() {
546.85 - }
546.86 - }
546.87 -
546.88 - /**
546.89 - * Test that it is possible to create a dummy MBean with a null
546.90 - * ObjectName - this is just a sanity check - as there are already
546.91 - * other JMX tests that check that.
546.92 - *
546.93 - * @throws java.lang.Exception
546.94 - */
546.95 - public static void testCreateWithNull() throws Exception {
546.96 - final MBeanServer server = newMBeanServer();
546.97 - final ObjectInstance oi = server.registerMBean(new Thing(),null);
546.98 - server.unregisterMBean(oi.getObjectName());
546.99 - System.out.println("testCreateWithNull PASSED");
546.100 - }
546.101 -
546.102 - /**
546.103 - * Check that we can register a JMXNamespace MBean, using its standard
546.104 - * ObjectName.
546.105 - * @throws java.lang.Exception
546.106 - */
546.107 - public static void testGoodObjectName() throws Exception {
546.108 - MBeanServer server = newMBeanServer();
546.109 - final ObjectName name =
546.110 - JMXNamespaces.getNamespaceObjectName("gloups");
546.111 - final ObjectInstance oi =
546.112 - server.registerMBean(new LocalNamespace(),name);
546.113 - System.out.println("Succesfully registered namespace: "+name);
546.114 - try {
546.115 - if (! name.equals(oi.getObjectName()))
546.116 - throw new RuntimeException("testGoodObjectName: TEST failed: " +
546.117 - "namespace registered as: "+
546.118 - oi.getObjectName()+" expected: "+name);
546.119 - } finally {
546.120 - server.unregisterMBean(oi.getObjectName());
546.121 - }
546.122 - System.out.println("Succesfully unregistered namespace: "+name);
546.123 - System.out.println("testGoodObjectName PASSED");
546.124 - }
546.125 -
546.126 - /**
546.127 - * Check that we cannot register a JMXNamespace MBean, if we don't use
546.128 - * its standard ObjectName.
546.129 - * @throws java.lang.Exception
546.130 - */
546.131 - public static void testBadObjectName() throws Exception {
546.132 - MBeanServer server = newMBeanServer();
546.133 - Throwable exp = null;
546.134 - final ObjectName name = new ObjectName("d:k=v");
546.135 - try {
546.136 - server.registerMBean(new LocalNamespace(),name);
546.137 - System.out.println("testBadObjectName: " +
546.138 - "Error: MBean registered, no exception thrown.");
546.139 - } catch(RuntimeMBeanException x) {
546.140 - exp = x.getCause();
546.141 - } catch(Exception x) {
546.142 - throw new RuntimeException("testBadObjectName: TEST failed: " +
546.143 - "expected RuntimeMBeanException - got "+
546.144 - x);
546.145 - }
546.146 - if (exp == null) server.unregisterMBean(name);
546.147 - if (exp == null)
546.148 - throw new RuntimeException("testBadObjectName: TEST failed: " +
546.149 - "expected IllegalArgumentException - got none");
546.150 - if (!(exp instanceof IllegalArgumentException))
546.151 - throw new RuntimeException("testBadObjectName: TEST failed: " +
546.152 - "expected IllegalArgumentException - got "+
546.153 - exp.toString(),exp);
546.154 - System.out.println("Got expected exception: "+exp);
546.155 - System.out.println("testBadObjectName PASSED");
546.156 - }
546.157 -
546.158 - /**
546.159 - * Check that we cannot register a Wombat MBean in a namespace that does
546.160 - * not exists.
546.161 - *
546.162 - * @throws java.lang.Exception
546.163 - */
546.164 - public static void testBadNamespace() throws Exception {
546.165 - MBeanServer server = newMBeanServer();
546.166 - Throwable exp = null;
546.167 - final ObjectName name = new ObjectName("glips//d:k=v");
546.168 -
546.169 - try {
546.170 - server.registerMBean(new Wombat(),name);
546.171 - System.out.println("testBadNamespace: " +
546.172 - "Error: MBean registered, no exception thrown.");
546.173 - } catch(MBeanRegistrationException x) {
546.174 - exp = x.getCause();
546.175 - } catch(Exception x) {
546.176 - throw new RuntimeException("testBadNamespace: TEST failed: " +
546.177 - "expected MBeanRegistrationException - got "+
546.178 - x);
546.179 - }
546.180 - if (exp == null) server.unregisterMBean(name);
546.181 - if (exp == null)
546.182 - throw new RuntimeException("testBadNamespace: TEST failed: " +
546.183 - "expected IllegalArgumentException - got none");
546.184 - if (!(exp instanceof IllegalArgumentException))
546.185 - throw new RuntimeException("testBadNamespace: TEST failed: " +
546.186 - "expected IllegalArgumentException - got "+
546.187 - exp.toString(),exp);
546.188 - System.out.println("Got expected exception: "+exp);
546.189 - System.out.println("testBadNamespace PASSED");
546.190 - }
546.191 -
546.192 - /**
546.193 - * Check that we cannot register a Wombat MBean with a domain name
546.194 - * that ends with //. This is reserved for namespaces.
546.195 - *
546.196 - * @throws java.lang.Exception
546.197 - */
546.198 - public static void testBadDomain() throws Exception {
546.199 - MBeanServer server = newMBeanServer();
546.200 - Throwable exp = null;
546.201 - final ObjectName name = new ObjectName("glups//:k=v");
546.202 -
546.203 - try {
546.204 - server.registerMBean(new Wombat(),name);
546.205 - System.out.println("testBadDomain: Error: MBean registered, no exception thrown.");
546.206 - } catch(RuntimeMBeanException x) {
546.207 - exp = x.getCause();
546.208 - } catch(Exception x) {
546.209 - throw new RuntimeException("testBadDomain: TEST failed: " +
546.210 - "expected RuntimeMBeanException - got "+
546.211 - x);
546.212 - }
546.213 - if (exp == null) server.unregisterMBean(name);
546.214 - if (exp == null)
546.215 - throw new RuntimeException("testBadDomain: TEST failed: " +
546.216 - "expected IllegalArgumentException - got none");
546.217 - if (!(exp instanceof IllegalArgumentException))
546.218 - throw new RuntimeException("testBadDomain: TEST failed: " +
546.219 - "expected IllegalArgumentException - got "+
546.220 - exp.toString(),exp);
546.221 - System.out.println("Got expected exception: "+exp);
546.222 - System.out.println("testBadDomain PASSED");
546.223 - }
546.224 -
546.225 - /**
546.226 - * Check that we cannot register a Wombat MBean as if it were a
546.227 - * JMXNamespace. Only JMXNamespace MBeans can have JMX Namespace names.
546.228 - * @throws java.lang.Exception
546.229 - */
546.230 - public static void testBadClassName() throws Exception {
546.231 - MBeanServer server = newMBeanServer();
546.232 - Throwable exp = null;
546.233 - final ObjectName name =
546.234 - JMXNamespaces.getNamespaceObjectName("glops");
546.235 - try {
546.236 - server.registerMBean(new Wombat(),name);
546.237 - System.out.println("testBadClassName: " +
546.238 - "Error: MBean registered, no exception thrown.");
546.239 - } catch(RuntimeMBeanException x) {
546.240 - exp = x.getCause();
546.241 - } catch(Exception x) {
546.242 - throw new RuntimeException("testBadClassName: TEST failed: " +
546.243 - "expected RuntimeMBeanException - got "+
546.244 - x);
546.245 - }
546.246 - if (exp == null) server.unregisterMBean(name);
546.247 - if (exp == null)
546.248 - throw new RuntimeException("testBadClassName: TEST failed: " +
546.249 - "expected IllegalArgumentException - got none");
546.250 - if (!(exp instanceof IllegalArgumentException))
546.251 - throw new RuntimeException("testBadClassName: TEST failed: " +
546.252 - "expected IllegalArgumentException - got "+
546.253 - exp.toString(),exp);
546.254 - System.out.println("Got expected exception: "+exp);
546.255 - System.out.println("testBadClassName PASSED");
546.256 - }
546.257 -
546.258 - public static void main(String... args) throws Exception {
546.259 - testCreateWithNull();
546.260 - testGoodObjectName();
546.261 - testBadObjectName();
546.262 - testBadNamespace();
546.263 - testBadDomain();
546.264 - testBadClassName();
546.265 - }
546.266 -}
547.1 --- a/test/javax/management/namespace/NamespaceNotificationsTest.java Mon Nov 23 10:04:47 2009 +0000
547.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
547.3 @@ -1,381 +0,0 @@
547.4 -/*
547.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
547.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
547.7 - *
547.8 - * This code is free software; you can redistribute it and/or modify it
547.9 - * under the terms of the GNU General Public License version 2 only, as
547.10 - * published by the Free Software Foundation.
547.11 - *
547.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
547.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
547.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
547.15 - * version 2 for more details (a copy is included in the LICENSE file that
547.16 - * accompanied this code).
547.17 - *
547.18 - * You should have received a copy of the GNU General Public License version
547.19 - * 2 along with this work; if not, write to the Free Software Foundation,
547.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
547.21 - *
547.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
547.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
547.24 - * have any questions.
547.25 - */
547.26 -
547.27 -/*
547.28 - *
547.29 - * @test NamespaceNotificationsTest.java 1.12
547.30 - * @summary General Namespace & Notifications test.
547.31 - * @bug 5072476
547.32 - * @author Daniel Fuchs
547.33 - * @run clean NamespaceNotificationsTest
547.34 - * Wombat WombatMBean JMXRemoteTargetNamespace
547.35 - * NamespaceController NamespaceControllerMBean
547.36 - * @compile -XDignore.symbol.file=true NamespaceNotificationsTest.java
547.37 - * Wombat.java WombatMBean.java JMXRemoteTargetNamespace.java
547.38 - * NamespaceController.java NamespaceControllerMBean.java
547.39 - * @run main NamespaceNotificationsTest
547.40 - */
547.41 -import com.sun.jmx.remote.util.EventClientConnection;
547.42 -import java.lang.management.ManagementFactory;
547.43 -import java.util.Arrays;
547.44 -import java.util.HashMap;
547.45 -import java.util.Map;
547.46 -import java.util.concurrent.ArrayBlockingQueue;
547.47 -import java.util.concurrent.BlockingQueue;
547.48 -import java.util.concurrent.TimeUnit;
547.49 -import java.util.logging.Logger;
547.50 -import javax.management.JMX;
547.51 -import javax.management.MBeanServer;
547.52 -import javax.management.MBeanServerConnection;
547.53 -import javax.management.MBeanServerDelegate;
547.54 -import javax.management.MBeanServerFactory;
547.55 -import javax.management.MBeanServerNotification;
547.56 -import javax.management.MalformedObjectNameException;
547.57 -import javax.management.Notification;
547.58 -import javax.management.NotificationEmitter;
547.59 -import javax.management.NotificationListener;
547.60 -import javax.management.ObjectInstance;
547.61 -import javax.management.ObjectName;
547.62 -import javax.management.loading.MLet;
547.63 -import javax.management.namespace.JMXNamespace;
547.64 -import javax.management.namespace.JMXNamespaces;
547.65 -import javax.management.remote.JMXAddressable;
547.66 -import javax.management.remote.JMXConnector;
547.67 -import javax.management.remote.JMXConnectorFactory;
547.68 -import javax.management.remote.JMXConnectorServer;
547.69 -import javax.management.remote.JMXConnectorServerFactory;
547.70 -import javax.management.remote.JMXServiceURL;
547.71 -
547.72 -/**
547.73 - *
547.74 - * @author Sun Microsystems, Inc.
547.75 - */
547.76 -public class NamespaceNotificationsTest {
547.77 -
547.78 - /**
547.79 - * A logger for this class.
547.80 - **/
547.81 - private static final Logger LOG =
547.82 - Logger.getLogger(NamespaceNotificationsTest.class.getName());
547.83 -
547.84 - /** Creates a new instance of NamespaceNotificationsTest */
547.85 - public NamespaceNotificationsTest() {
547.86 - }
547.87 -
547.88 -
547.89 - public static JMXServiceURL export(MBeanServer server)
547.90 - throws Exception {
547.91 - final JMXServiceURL in = new JMXServiceURL("rmi",null,0);
547.92 - final JMXConnectorServer cs =
547.93 - JMXConnectorServerFactory.newJMXConnectorServer(in,null,null);
547.94 - final ObjectName csname = ObjectName.
547.95 - getInstance(cs.getClass().getPackage().getName()+
547.96 - ":type="+cs.getClass().getSimpleName());
547.97 - server.registerMBean(cs,csname);
547.98 - cs.start();
547.99 - return cs.getAddress();
547.100 - }
547.101 -
547.102 - public static class Counter {
547.103 - int count;
547.104 - public synchronized int count() {
547.105 - count++;
547.106 - notifyAll();
547.107 - return count;
547.108 - }
547.109 - public synchronized int peek() {
547.110 - return count;
547.111 - }
547.112 - public synchronized int waitfor(int max, long timeout)
547.113 - throws InterruptedException {
547.114 - final long start = System.currentTimeMillis();
547.115 - while (count < max && timeout > 0) {
547.116 - final long rest = timeout -
547.117 - (System.currentTimeMillis() - start);
547.118 - if (rest <= 0) break;
547.119 - wait(rest);
547.120 - }
547.121 - return count;
547.122 - }
547.123 - }
547.124 -
547.125 - public static class CounterListener
547.126 - implements NotificationListener {
547.127 - final private Counter counter;
547.128 - public CounterListener(Counter counter) {
547.129 - this.counter = counter;
547.130 - }
547.131 - public void handleNotification(Notification notification,
547.132 - Object handback) {
547.133 - System.out.println("Received notif from " + handback +
547.134 - ":\n\t" + notification);
547.135 - if (!notification.getSource().equals(handback)) {
547.136 - System.err.println("OhOh... Unexpected source: \n\t"+
547.137 - notification.getSource()+"\n\twas expecting:\n\t"+
547.138 - handback);
547.139 - }
547.140 - counter.count();
547.141 - }
547.142 - }
547.143 -
547.144 - public static void simpleTest(String[] args) {
547.145 - try {
547.146 - final MBeanServer server1 =
547.147 - ManagementFactory.getPlatformMBeanServer();
547.148 - final JMXServiceURL url1 = export(server1);
547.149 -
547.150 - final MBeanServer server2 =
547.151 - MBeanServerFactory.createMBeanServer("server2");
547.152 - final JMXServiceURL url2 = export(server2);
547.153 -
547.154 - final MBeanServer server3 =
547.155 - MBeanServerFactory.createMBeanServer("server3");
547.156 - final JMXServiceURL url3 = export(server3);
547.157 -
547.158 - final ObjectInstance ncinst =
547.159 - NamespaceController.createInstance(server1);
547.160 -
547.161 - final NamespaceControllerMBean nc =
547.162 - JMX.newMBeanProxy(server1,ncinst.getObjectName(),
547.163 - NamespaceControllerMBean.class);
547.164 -
547.165 - final Map<String,Object> options = new HashMap<String,Object>();
547.166 - options.put(JMXRemoteTargetNamespace.CREATE_EVENT_CLIENT,"true");
547.167 -
547.168 - final String mount1 =
547.169 - nc.mount(url1,"server1",options);
547.170 - final String mount2 = nc.mount(url2,"server1//server2",
547.171 - options);
547.172 - final String mount3 = nc.mount(url3,
547.173 - "server1//server2//server3",
547.174 - options);
547.175 - final String mount13 = nc.mount(
547.176 - url1,
547.177 - "server3",
547.178 - "server2//server3",
547.179 - options);
547.180 - final String mount21 = nc.mount(url1,"server2//server1",
547.181 - options);
547.182 - final String mount31 = nc.mount(
547.183 - url1,
547.184 - "server3//server1",
547.185 - "server1",
547.186 - options);
547.187 - final String mount32 = nc.mount(
547.188 - url1,
547.189 - "server3//server2",
547.190 - "server2",
547.191 - options);
547.192 -
547.193 -
547.194 - final ObjectName deep =
547.195 - new ObjectName("server1//server2//server3//bush:type=Wombat,name=kanga");
547.196 - server1.createMBean(Wombat.class.getName(),deep);
547.197 -
547.198 - System.err.println("There's a wombat in the bush!");
547.199 -
547.200 - final Counter counter = new Counter();
547.201 -
547.202 - final NotificationListener listener =
547.203 - new CounterListener(counter);
547.204 -
547.205 - final JMXConnector jc = JMXConnectorFactory.connect(url1);
547.206 - final MBeanServerConnection aconn =
547.207 - EventClientConnection.getEventConnectionFor(
547.208 - jc.getMBeanServerConnection(),null);
547.209 - aconn.addNotificationListener(deep,listener,null,deep);
547.210 -
547.211 -
547.212 - MBeanServerConnection iconn =
547.213 - JMXNamespaces.narrowToNamespace(aconn, "server1//server1");
547.214 - MBeanServerConnection bconn =
547.215 - JMXNamespaces.narrowToNamespace(aconn, "server3");
547.216 - final ObjectName shallow =
547.217 - new ObjectName("bush:"+
547.218 - deep.getKeyPropertyListString());
547.219 - final WombatMBean proxy =
547.220 - JMX.newMBeanProxy(EventClientConnection.getEventConnectionFor(
547.221 - bconn,null),shallow,WombatMBean.class,true);
547.222 -
547.223 - ((NotificationEmitter)proxy).
547.224 - addNotificationListener(listener,null,shallow);
547.225 - proxy.setCaption("I am a new Wombat!");
547.226 - System.err.println("New caption: "+proxy.getCaption());
547.227 - final int rcvcount = counter.waitfor(2,3000);
547.228 - if (rcvcount != 2)
547.229 - throw new RuntimeException("simpleTest failed: "+
547.230 - "received count is " +rcvcount);
547.231 -
547.232 - System.err.println("simpleTest passed: got "+rcvcount+
547.233 - " notifs");
547.234 -
547.235 - } catch (RuntimeException x) {
547.236 - throw x;
547.237 - } catch (Exception x) {
547.238 - throw new RuntimeException("simpleTest failed: " + x,x);
547.239 - }
547.240 - }
547.241 -
547.242 - public static class LocalNamespace extends
547.243 - JMXNamespace {
547.244 - LocalNamespace() {
547.245 - super(MBeanServerFactory.newMBeanServer());
547.246 - }
547.247 -
547.248 - }
547.249 -
547.250 - public static class ContextObject<K,V> {
547.251 - public final K name;
547.252 - public final V object;
547.253 - public ContextObject(K name, V object) {
547.254 - this.name = name;
547.255 - this.object = object;
547.256 - }
547.257 - private Object[] data() {
547.258 - return new Object[] {name,object};
547.259 - }
547.260 -
547.261 - @Override
547.262 - public boolean equals(Object x) {
547.263 - if (x instanceof ContextObject)
547.264 - return Arrays.deepEquals(data(),((ContextObject<?,?>)x).data());
547.265 - return false;
547.266 - }
547.267 - @Override
547.268 - public int hashCode() {
547.269 - return Arrays.deepHashCode(data());
547.270 - }
547.271 - }
547.272 -
547.273 - private static <K,V> ContextObject<K,V> context(K k, V v) {
547.274 - return new ContextObject<K,V>(k,v);
547.275 - }
547.276 -
547.277 - private static ObjectName name(String name) {
547.278 - try {
547.279 - return new ObjectName(name);
547.280 - } catch(MalformedObjectNameException x) {
547.281 - throw new IllegalArgumentException(name,x);
547.282 - }
547.283 - }
547.284 -
547.285 - public static void simpleTest2() {
547.286 - try {
547.287 - System.out.println("\nsimpleTest2: STARTING\n");
547.288 - final LocalNamespace foo = new LocalNamespace();
547.289 - final LocalNamespace joe = new LocalNamespace();
547.290 - final LocalNamespace bar = new LocalNamespace();
547.291 - final MBeanServer server = MBeanServerFactory.newMBeanServer();
547.292 -
547.293 - server.registerMBean(foo,JMXNamespaces.getNamespaceObjectName("foo"));
547.294 - server.registerMBean(joe,JMXNamespaces.getNamespaceObjectName("foo//joe"));
547.295 - server.registerMBean(bar,JMXNamespaces.getNamespaceObjectName("foo//bar"));
547.296 - final BlockingQueue<ContextObject<String,MBeanServerNotification>> queue =
547.297 - new ArrayBlockingQueue<ContextObject<String,MBeanServerNotification>>(20);
547.298 -
547.299 - final NotificationListener listener = new NotificationListener() {
547.300 - public void handleNotification(Notification n, Object handback) {
547.301 - if (!(n instanceof MBeanServerNotification)) {
547.302 - System.err.println("Error: expected MBeanServerNotification");
547.303 - return;
547.304 - }
547.305 - final MBeanServerNotification mbsn =
547.306 - (MBeanServerNotification) n;
547.307 -
547.308 - // We will pass the namespace name in the handback.
547.309 - //
547.310 - final String namespace = (String) handback;
547.311 - System.out.println("Received " + mbsn.getType() +
547.312 - " for MBean " + mbsn.getMBeanName() +
547.313 - " from name space " + namespace);
547.314 - try {
547.315 - queue.offer(context(namespace,mbsn),500,TimeUnit.MILLISECONDS);
547.316 - } catch (Exception x) {
547.317 - System.err.println("Failed to enqueue received notif: "+mbsn);
547.318 - x.printStackTrace();
547.319 - }
547.320 - }
547.321 - };
547.322 -
547.323 - server.addNotificationListener(JMXNamespaces.insertPath("foo//joe",
547.324 - MBeanServerDelegate.DELEGATE_NAME),listener,null,"foo//joe");
547.325 - server.addNotificationListener(JMXNamespaces.insertPath("foo//bar",
547.326 - MBeanServerDelegate.DELEGATE_NAME),listener,null,"foo//bar");
547.327 - server.createMBean(MLet.class.getName(),
547.328 - name("foo//joe//domain:type=MLet"));
547.329 - checkQueue(queue,"foo//joe",
547.330 - MBeanServerNotification.REGISTRATION_NOTIFICATION);
547.331 - server.createMBean(MLet.class.getName(),
547.332 - name("foo//bar//domain:type=MLet"));
547.333 - checkQueue(queue,"foo//bar",
547.334 - MBeanServerNotification.REGISTRATION_NOTIFICATION);
547.335 - server.unregisterMBean(
547.336 - name("foo//joe//domain:type=MLet"));
547.337 - checkQueue(queue,"foo//joe",
547.338 - MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
547.339 - server.unregisterMBean(
547.340 - name("foo//bar//domain:type=MLet"));
547.341 - checkQueue(queue,"foo//bar",
547.342 - MBeanServerNotification.UNREGISTRATION_NOTIFICATION);
547.343 - } catch (RuntimeException x) {
547.344 - System.err.println("FAILED: "+x);
547.345 - throw x;
547.346 - } catch(Exception x) {
547.347 - System.err.println("FAILED: "+x);
547.348 - throw new RuntimeException("Unexpected exception: "+x,x);
547.349 - }
547.350 - }
547.351 -
547.352 -
547.353 - private static void checkQueue(
547.354 - BlockingQueue<ContextObject<String,MBeanServerNotification>> q,
547.355 - String path, String type) {
547.356 - try {
547.357 - final ContextObject<String,MBeanServerNotification> ctxt =
547.358 - q.poll(500,TimeUnit.MILLISECONDS);
547.359 - if (ctxt == null)
547.360 - throw new RuntimeException("Timeout expired: expected notif from "+
547.361 - path +", type="+type);
547.362 - if (!ctxt.name.equals(path))
547.363 - throw new RuntimeException("expected notif from "+
547.364 - path +", got "+ctxt.name);
547.365 - if (!ctxt.object.getType().equals(type))
547.366 - throw new RuntimeException(ctxt.name+": expected type="+
547.367 - type +", got "+ctxt.object.getType());
547.368 - if (!ctxt.object.getType().equals(type))
547.369 - throw new RuntimeException(ctxt.name+": expected type="+
547.370 - type +", got "+ctxt.object.getType());
547.371 - if (!ctxt.object.getMBeanName().equals(name("domain:type=MLet")))
547.372 - throw new RuntimeException(ctxt.name+": expected MBean=domain:type=MLet"+
547.373 - ", got "+ctxt.object.getMBeanName());
547.374 - } catch(InterruptedException x) {
547.375 - throw new RuntimeException("unexpected interruption: "+x,x);
547.376 - }
547.377 - }
547.378 -
547.379 - public static void main(String[] args) {
547.380 - simpleTest(args);
547.381 - simpleTest2();
547.382 - }
547.383 -
547.384 -}
548.1 --- a/test/javax/management/namespace/NullDomainObjectNameTest.java Mon Nov 23 10:04:47 2009 +0000
548.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
548.3 @@ -1,307 +0,0 @@
548.4 -/*
548.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
548.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
548.7 - *
548.8 - * This code is free software; you can redistribute it and/or modify it
548.9 - * under the terms of the GNU General Public License version 2 only, as
548.10 - * published by the Free Software Foundation.
548.11 - *
548.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
548.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
548.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
548.15 - * version 2 for more details (a copy is included in the LICENSE file that
548.16 - * accompanied this code).
548.17 - *
548.18 - * You should have received a copy of the GNU General Public License version
548.19 - * 2 along with this work; if not, write to the Free Software Foundation,
548.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
548.21 - *
548.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
548.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
548.24 - * have any questions.
548.25 - */
548.26 -/*
548.27 - * @test NullDomainObjectNameTest.java
548.28 - * @summary Test that null domains are correctly handled in namespaces.
548.29 - * @author Daniel Fuchs
548.30 - * @run clean NullDomainObjectNameTest Wombat WombatMBean
548.31 - * @compile -XDignore.symbol.file=true NullDomainObjectNameTest.java
548.32 - * @run build NullDomainObjectNameTest Wombat WombatMBean
548.33 - * @run main NullDomainObjectNameTest
548.34 - */
548.35 -
548.36 -import com.sun.jmx.namespace.RoutingServerProxy;
548.37 -import java.lang.management.ManagementFactory;
548.38 -import java.util.Arrays;
548.39 -import java.util.logging.Logger;
548.40 -import javax.management.MBeanRegistrationException;
548.41 -import javax.management.MBeanServer;
548.42 -import javax.management.MBeanServerFactory;
548.43 -import javax.management.NotCompliantMBeanException;
548.44 -import javax.management.ObjectInstance;
548.45 -import javax.management.ObjectName;
548.46 -import javax.management.RuntimeOperationsException;
548.47 -import javax.management.namespace.JMXNamespaces;
548.48 -import javax.management.namespace.JMXRemoteNamespace;
548.49 -import javax.management.namespace.JMXNamespace;
548.50 -import javax.management.remote.JMXConnectorServer;
548.51 -import javax.management.remote.JMXConnectorServerFactory;
548.52 -import javax.management.remote.JMXServiceURL;
548.53 -
548.54 -/**
548.55 - * Class NullDomainObjectNameTest
548.56 - * @author Sun Microsystems, 2005 - All rights reserved.
548.57 - */
548.58 -public class NullDomainObjectNameTest {
548.59 -
548.60 - /**
548.61 - * A logger for this class.
548.62 - **/
548.63 - private static final Logger LOG =
548.64 - Logger.getLogger(NullDomainObjectNameTest.class.getName());
548.65 -
548.66 - /** Creates a new instance of NullDomainObjectNameTest */
548.67 - public NullDomainObjectNameTest() {
548.68 - }
548.69 -
548.70 - public static class MyWombat
548.71 - extends Wombat {
548.72 - public MyWombat() throws NotCompliantMBeanException {
548.73 - super();
548.74 - }
548.75 - @Override
548.76 - public ObjectName preRegister(MBeanServer server, ObjectName name)
548.77 - throws Exception {
548.78 -
548.79 - if (name == null)
548.80 - name = new ObjectName(":type=Wombat");
548.81 -
548.82 - return super.preRegister(server, name);
548.83 - }
548.84 -
548.85 - }
548.86 -
548.87 - static String failure=null;
548.88 -
548.89 - public static void testRegister() throws Exception {
548.90 - final MBeanServer top = ManagementFactory.getPlatformMBeanServer();
548.91 - final MBeanServer sub = MBeanServerFactory.createMBeanServer();
548.92 - final JMXServiceURL url = new JMXServiceURL("rmi",null,0);
548.93 - final JMXConnectorServer srv =
548.94 - JMXConnectorServerFactory.newJMXConnectorServer(url,null,sub);
548.95 - srv.start();
548.96 -
548.97 - try {
548.98 -
548.99 - // Create a namespace rmi// that points to 'sub' and flows through
548.100 - // a JMXRemoteNamespace connected to 'srv'
548.101 - // The namespace rmi// will accept createMBean, but not registerMBean.
548.102 - //
548.103 - final JMXRemoteNamespace rmiHandler = JMXRemoteNamespace.
548.104 - newJMXRemoteNamespace(srv.getAddress(),
548.105 - null);
548.106 - top.registerMBean(rmiHandler,JMXNamespaces.getNamespaceObjectName("rmi"));
548.107 - top.invoke(JMXNamespaces.getNamespaceObjectName("rmi"),
548.108 - "connect", null, null);
548.109 -
548.110 - // Create a namespace direct// that points to 'sub' and flows
548.111 - // through a direct reference to 'sub'.
548.112 - // The namespace direct// will accept createMBean, and registerMBean.
548.113 - //
548.114 - final JMXNamespace directHandler = new JMXNamespace(sub);
548.115 - top.registerMBean(directHandler,
548.116 - JMXNamespaces.getNamespaceObjectName("direct"));
548.117 -
548.118 - // Now cd to each of the created namespace.
548.119 - //
548.120 - MBeanServer cdrmi = JMXNamespaces.narrowToNamespace(top,"rmi");
548.121 - MBeanServer cddirect = JMXNamespaces.narrowToNamespace(top,"direct");
548.122 - boolean ok = false;
548.123 -
548.124 - // Check that calling createMBean with a null domain works
548.125 - // for namespace rmi//
548.126 - //
548.127 - try {
548.128 - final ObjectInstance moi1 =
548.129 - cdrmi.createMBean(MyWombat.class.getName(),
548.130 - new ObjectName(":type=Wombat"));
548.131 - System.out.println(moi1.getObjectName().toString()+
548.132 - ": created through rmi//");
548.133 - assertEquals(moi1.getObjectName().getDomain(),
548.134 - cddirect.getDefaultDomain());
548.135 - cddirect.unregisterMBean(moi1.getObjectName());
548.136 - } catch (MBeanRegistrationException x) {
548.137 - System.out.println("Received unexpected exception: " + x);
548.138 - failed("Received unexpected exception: " + x);
548.139 - }
548.140 -
548.141 - // Check that calling refgisterMBean with a null domain works
548.142 - // for namespace direct//
548.143 - //
548.144 - try {
548.145 - final ObjectInstance moi2 =
548.146 - cddirect.registerMBean(new MyWombat(),
548.147 - new ObjectName(":type=Wombat"));
548.148 - System.out.println(moi2.getObjectName().toString()+
548.149 - ": created through direct//");
548.150 - assertEquals(moi2.getObjectName().getDomain(),
548.151 - cdrmi.getDefaultDomain());
548.152 - cdrmi.unregisterMBean(moi2.getObjectName());
548.153 - } catch (MBeanRegistrationException x) {
548.154 - System.out.println("Received unexpected exception: " + x);
548.155 - failed("Received unexpected exception: " + x);
548.156 - }
548.157 -
548.158 - // Now artificially pretend that 'sub' is contained in a faked//
548.159 - // namespace.
548.160 - //
548.161 - RoutingServerProxy proxy =
548.162 - new RoutingServerProxy(sub, "", "faked", true);
548.163 -
548.164 - // These should fail because the ObjectName doesn't start
548.165 - // with "faked//"
548.166 - try {
548.167 - final ObjectInstance moi3 =
548.168 - proxy.registerMBean(new MyWombat(),
548.169 - new ObjectName(":type=Wombat"));
548.170 - System.out.println(moi3.getObjectName().toString()+
548.171 - ": created through faked//");
548.172 - failed("expected MBeanRegistrationException");
548.173 - } catch (MBeanRegistrationException x) {
548.174 - System.out.println("Received expected exception: " + x);
548.175 - if (!(x.getCause() instanceof IllegalArgumentException)) {
548.176 - System.err.println("Bad wrapped exception: "+ x.getCause());
548.177 - failed("expected IllegalArgumentException");
548.178 - }
548.179 - }
548.180 -
548.181 - // null should work with "faked//"
548.182 - final ObjectInstance moi3 =
548.183 - proxy.registerMBean(new MyWombat(),null);
548.184 - assertEquals(moi3.getObjectName().getDomain(),
548.185 - "faked//"+sub.getDefaultDomain());
548.186 -
548.187 - System.out.println(moi3.getObjectName().toString() +
548.188 - ": created through faked//");
548.189 -
548.190 - // Now check that null is correctly handled (accepted or rejected)
548.191 - // in queries for each of the above configs.
548.192 - //
548.193 - ObjectName wombat = moi3.getObjectName().withDomain(
548.194 - moi3.getObjectName().getDomain().substring("faked//".length()));
548.195 - ObjectInstance moi = new ObjectInstance(wombat,moi3.getClassName());
548.196 -
548.197 - System.out.println("Checking queryNames(" +
548.198 - "new ObjectName(\":*\"),null) with rmi//");
548.199 - assertEquals(cdrmi.queryNames(
548.200 - new ObjectName(":*"),null).contains(wombat),true);
548.201 - System.out.println("Checking queryNames(" +
548.202 - "new ObjectName(\":*\"),null) with direct//");
548.203 - assertEquals(cddirect.queryNames(
548.204 - new ObjectName(":*"),null).contains(wombat),true);
548.205 - System.out.println("Checking queryMBeans(" +
548.206 - "new ObjectName(\":*\"),null) with rmi//");
548.207 - assertEquals(cdrmi.queryMBeans(
548.208 - new ObjectName(":*"),null).contains(moi),true);
548.209 - System.out.println("Checking queryMBeans(" +
548.210 - "new ObjectName(\":*\"),null) with direct//");
548.211 - assertEquals(cddirect.queryMBeans(
548.212 - new ObjectName(":*"),null).contains(moi),true);
548.213 -
548.214 - // These should fail because the ObjectName doesn't start
548.215 - // with "faked//"
548.216 - try {
548.217 - System.out.println("Checking queryNames(" +
548.218 - "new ObjectName(\":*\"),null) with faked//");
548.219 - assertEquals(proxy.queryNames(
548.220 - new ObjectName(":*"),null).
548.221 - contains(moi3.getObjectName()),true);
548.222 - failed("queryNames(new ObjectName(\":*\"),null) " +
548.223 - "should have failed for faked//");
548.224 - } catch (RuntimeOperationsException x) {
548.225 - if (x.getCause() instanceof IllegalArgumentException)
548.226 - System.out.println(
548.227 - "Received expected exception for faked//: "+x);
548.228 - else {
548.229 - System.err.println(
548.230 - "Expected exception has unexpected cause " +
548.231 - "for faked//: "+x.getCause());
548.232 - x.printStackTrace();
548.233 - failed("queryNames(new ObjectName(\":*\"),null)" +
548.234 - " failed with unexpected cause for faked//");
548.235 - }
548.236 - }
548.237 - // These should fail because the ObjectName doesn't start
548.238 - // with "faked//"
548.239 - try {
548.240 - System.out.println("Checking queryMBeans(" +
548.241 - "new ObjectName(\":*\"),null) with faked//");
548.242 - assertEquals(proxy.queryMBeans(
548.243 - new ObjectName(":*"),null).contains(moi3),true);
548.244 - failed("queryMBeans(new ObjectName(\":*\"),null)" +
548.245 - " should have failed for faked//");
548.246 - } catch (RuntimeOperationsException x) {
548.247 - if (x.getCause() instanceof IllegalArgumentException)
548.248 - System.out.println(
548.249 - "Received expected exception for faked//: "+x);
548.250 - else {
548.251 - System.err.println(
548.252 - "Expected exception has unexpected cause " +
548.253 - "for faked//: "+x.getCause());
548.254 - x.printStackTrace();
548.255 - failed("queryMBeans(new ObjectName(\":*\"),null) " +
548.256 - "failed with unexpected cause for faked//");
548.257 - }
548.258 - }
548.259 -
548.260 - System.out.println("Checking queryNames(faked//*:*,null)");
548.261 - assertEquals(proxy.queryNames(new ObjectName("faked//*:*"),null).
548.262 - contains(moi3.getObjectName()),true);
548.263 -
548.264 - System.out.println("Checking queryMBeans(faked//*:*,null)");
548.265 - assertEquals(proxy.queryMBeans(new ObjectName("faked//*:*"),null).
548.266 - contains(moi3),true);
548.267 -
548.268 - proxy.unregisterMBean(moi3.getObjectName());
548.269 -
548.270 - // ADD NEW TESTS HERE ^^^
548.271 -
548.272 - } finally {
548.273 - srv.stop();
548.274 - }
548.275 -
548.276 - if (failure != null)
548.277 - throw new Exception(failure);
548.278 -
548.279 -
548.280 - }
548.281 - private static void assertEquals(Object x, Object y) {
548.282 - if (!equal(x, y))
548.283 - failed("expected " + string(x) + "; got " + string(y));
548.284 - }
548.285 -
548.286 - private static boolean equal(Object x, Object y) {
548.287 - if (x == y)
548.288 - return true;
548.289 - if (x == null || y == null)
548.290 - return false;
548.291 - if (x.getClass().isArray())
548.292 - return Arrays.deepEquals(new Object[] {x}, new Object[] {y});
548.293 - return x.equals(y);
548.294 - }
548.295 -
548.296 - private static String string(Object x) {
548.297 - String s = Arrays.deepToString(new Object[] {x});
548.298 - return s.substring(1, s.length() - 1);
548.299 - }
548.300 -
548.301 -
548.302 - private static void failed(String why) {
548.303 - failure = why;
548.304 - new Throwable("FAILED: " + why).printStackTrace(System.out);
548.305 - }
548.306 -
548.307 - public static void main(String[] args) throws Exception {
548.308 - testRegister();
548.309 - }
548.310 -}
549.1 --- a/test/javax/management/namespace/NullObjectNameTest.java Mon Nov 23 10:04:47 2009 +0000
549.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
549.3 @@ -1,273 +0,0 @@
549.4 -/*
549.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
549.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
549.7 - *
549.8 - * This code is free software; you can redistribute it and/or modify it
549.9 - * under the terms of the GNU General Public License version 2 only, as
549.10 - * published by the Free Software Foundation.
549.11 - *
549.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
549.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
549.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
549.15 - * version 2 for more details (a copy is included in the LICENSE file that
549.16 - * accompanied this code).
549.17 - *
549.18 - * You should have received a copy of the GNU General Public License version
549.19 - * 2 along with this work; if not, write to the Free Software Foundation,
549.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
549.21 - *
549.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
549.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
549.24 - * have any questions.
549.25 - */
549.26 -/*
549.27 - * @test NullObjectNameTest.java
549.28 - * @summary Test that null ObjectName are correctly handled in namespaces.
549.29 - * @author Daniel Fuchs
549.30 - * @bug 5072476
549.31 - * @run clean NullObjectNameTest Wombat WombatMBean
549.32 - * @compile -XDignore.symbol.file=true NullObjectNameTest.java
549.33 - * @run build NullObjectNameTest Wombat WombatMBean
549.34 - * @run main NullObjectNameTest
549.35 - */
549.36 -
549.37 -import com.sun.jmx.namespace.RoutingServerProxy;
549.38 -import java.lang.management.ManagementFactory;
549.39 -import java.util.Arrays;
549.40 -import java.util.logging.Logger;
549.41 -import javax.management.MBeanRegistrationException;
549.42 -import javax.management.MBeanServer;
549.43 -import javax.management.MBeanServerFactory;
549.44 -import javax.management.NotCompliantMBeanException;
549.45 -import javax.management.ObjectInstance;
549.46 -import javax.management.ObjectName;
549.47 -import javax.management.RuntimeOperationsException;
549.48 -import javax.management.namespace.JMXNamespaces;
549.49 -import javax.management.namespace.JMXRemoteNamespace;
549.50 -import javax.management.namespace.JMXNamespace;
549.51 -import javax.management.remote.JMXConnectorServer;
549.52 -import javax.management.remote.JMXConnectorServerFactory;
549.53 -import javax.management.remote.JMXServiceURL;
549.54 -
549.55 -/**
549.56 - * Class NullObjectNameTest
549.57 - * @author Sun Microsystems, 2005 - All rights reserved.
549.58 - */
549.59 -public class NullObjectNameTest {
549.60 -
549.61 - /**
549.62 - * A logger for this class.
549.63 - **/
549.64 - private static final Logger LOG =
549.65 - Logger.getLogger(NullObjectNameTest.class.getName());
549.66 -
549.67 - /** Creates a new instance of NullObjectNameTest */
549.68 - public NullObjectNameTest() {
549.69 - }
549.70 -
549.71 - public static class MyWombat
549.72 - extends Wombat {
549.73 - public MyWombat() throws NotCompliantMBeanException {
549.74 - super();
549.75 - }
549.76 - @Override
549.77 - public ObjectName preRegister(MBeanServer server, ObjectName name)
549.78 - throws Exception {
549.79 -
549.80 - if (name == null)
549.81 - name = new ObjectName(":type=Wombat");
549.82 -
549.83 - return super.preRegister(server, name);
549.84 - }
549.85 -
549.86 - }
549.87 -
549.88 - static String failure=null;
549.89 -
549.90 - public static void testRegister() throws Exception {
549.91 - final MBeanServer top = ManagementFactory.getPlatformMBeanServer();
549.92 - final MBeanServer sub = MBeanServerFactory.createMBeanServer();
549.93 - final JMXServiceURL url = new JMXServiceURL("rmi",null,0);
549.94 - final JMXConnectorServer srv =
549.95 - JMXConnectorServerFactory.newJMXConnectorServer(url,null,sub);
549.96 - srv.start();
549.97 -
549.98 - try {
549.99 -
549.100 - // Create a namespace rmi// that points to 'sub' and flows through
549.101 - // a JMXRemoteNamespace connected to 'srv'
549.102 - // The namespace rmi// will accept createMBean, but not registerMBean.
549.103 - //
549.104 - final JMXRemoteNamespace rmiHandler = JMXRemoteNamespace.
549.105 - newJMXRemoteNamespace(srv.getAddress(),null);
549.106 - top.registerMBean(rmiHandler,JMXNamespaces.getNamespaceObjectName("rmi"));
549.107 - top.invoke(JMXNamespaces.getNamespaceObjectName("rmi"),
549.108 - "connect", null, null);
549.109 -
549.110 - // Create a namespace direct// that points to 'sub' and flows
549.111 - // through a direct reference to 'sub'.
549.112 - // The namespace direct// will accept createMBean, and registerMBean.
549.113 - //
549.114 - final JMXNamespace directHandler = new JMXNamespace(sub);
549.115 - top.registerMBean(directHandler,
549.116 - JMXNamespaces.getNamespaceObjectName("direct"));
549.117 -
549.118 - // Now cd to each of the created namespace.
549.119 - //
549.120 - MBeanServer cdrmi = JMXNamespaces.narrowToNamespace(top,"rmi");
549.121 - MBeanServer cddirect = JMXNamespaces.narrowToNamespace(top,"direct");
549.122 - boolean ok = false;
549.123 -
549.124 - // Check that calling createMBean with a null ObjectName fails
549.125 - // gracefully for namespace rmi// (we can't add rmi// to a null
549.126 - // ObjectName.
549.127 - //
549.128 - // TODO: do this test for all createMBean flavors!
549.129 - try {
549.130 - final ObjectInstance moi1 =
549.131 - cdrmi.createMBean(MyWombat.class.getName(),null);
549.132 - System.out.println(moi1.getObjectName().toString()+
549.133 - ": created through rmi//");
549.134 - cddirect.unregisterMBean(moi1.getObjectName());
549.135 - failed("expected MBeanRegistrationException");
549.136 - } catch (MBeanRegistrationException x) {
549.137 - System.out.println("Received expected exception: " + x);
549.138 - if (!(x.getCause() instanceof IllegalArgumentException)) {
549.139 - System.err.println("Bad wrapped exception: "+ x.getCause());
549.140 - failed("expected IllegalArgumentException");
549.141 - }
549.142 - }
549.143 -
549.144 - // Check that calling refgisterMBean with a null ObjectName fails
549.145 - // gracefully for namespace direct// (we can't add direct// to a null
549.146 - // ObjectName.
549.147 - //
549.148 - try {
549.149 - final ObjectInstance moi2 =
549.150 - cddirect.registerMBean(new MyWombat(), (ObjectName)null);
549.151 - System.out.println(moi2.getObjectName().toString()+
549.152 - ": created through direct//");
549.153 - cdrmi.unregisterMBean(moi2.getObjectName());
549.154 - failed("expected MBeanRegistrationException");
549.155 - } catch (MBeanRegistrationException x) {
549.156 - System.out.println("Received expected exception: " + x);
549.157 - if (!(x.getCause() instanceof IllegalArgumentException)) {
549.158 - System.err.println("Bad wrapped exception: "+ x.getCause());
549.159 - failed("expected IllegalArgumentException");
549.160 - }
549.161 - }
549.162 -
549.163 - // Now artificially pretend that 'sub' is contained in a faked//
549.164 - // namespace.
549.165 - // We should be able to use 'null' in registerMBean/createMBean in
549.166 - // this case.
549.167 - //
549.168 - RoutingServerProxy proxy =
549.169 - new RoutingServerProxy(sub, "", "faked", true);
549.170 - final ObjectInstance moi3 =
549.171 - proxy.registerMBean(new MyWombat(),null);
549.172 - System.out.println(moi3.getObjectName().toString()+
549.173 - ": created through faked//");
549.174 -
549.175 - // Now check that null is correctly handled (accepted or rejected)
549.176 - // in queries for each of the above configs.
549.177 - //
549.178 - ObjectName wombat = moi3.getObjectName().withDomain(
549.179 - moi3.getObjectName().getDomain().substring("faked//".length()));
549.180 - ObjectInstance moi = new ObjectInstance(wombat,moi3.getClassName());
549.181 -
549.182 - System.out.println("Checking queryNames(null,null) with rmi//");
549.183 - assertEquals(cdrmi.queryNames(null,null).contains(wombat),true);
549.184 - System.out.println("Checking queryNames(null,null) with direct//");
549.185 - assertEquals(cddirect.queryNames(null,null).contains(wombat),true);
549.186 - System.out.println("Checking queryMBeans(null,null) with rmi//");
549.187 - assertEquals(cdrmi.queryMBeans(null,null).contains(moi),true);
549.188 - System.out.println("Checking queryMBeans(null,null) with direct//");
549.189 - assertEquals(cddirect.queryMBeans(null,null).contains(moi),true);
549.190 -
549.191 - try {
549.192 - System.out.println("Checking queryNames(null,null) with faked//");
549.193 - assertEquals(proxy.queryNames(null,null).
549.194 - contains(moi3.getObjectName()),true);
549.195 - failed("queryNames(null,null) should have failed for faked//");
549.196 - } catch (RuntimeOperationsException x) {
549.197 - if (x.getCause() instanceof IllegalArgumentException)
549.198 - System.out.println(
549.199 - "Received expected exception for faked//: "+x);
549.200 - else {
549.201 - System.err.println(
549.202 - "Expected exception has unexpected cause " +
549.203 - "for faked//: "+x.getCause());
549.204 - x.printStackTrace();
549.205 - failed("queryNames(null,null) failed with unexpected " +
549.206 - "cause for faked//");
549.207 - }
549.208 - }
549.209 - try {
549.210 - System.out.println("Checking queryMBeans(null,null) with faked//");
549.211 - assertEquals(proxy.queryMBeans(null,null).contains(moi3),true);
549.212 - failed("queryMBeans(null,null) should have failed for faked//");
549.213 - } catch (RuntimeOperationsException x) {
549.214 - if (x.getCause() instanceof IllegalArgumentException)
549.215 - System.out.println(
549.216 - "Received expected exception for faked//: "+x);
549.217 - else {
549.218 - System.err.println(
549.219 - "Expected exception has unexpected cause " +
549.220 - "for faked//: "+x.getCause());
549.221 - x.printStackTrace();
549.222 - failed("queryMBeans(null,null) failed with unexpected " +
549.223 - "cause for faked//");
549.224 - }
549.225 - }
549.226 - System.out.println("Checking queryNames(faked//*:*,null)");
549.227 - assertEquals(proxy.queryNames(new ObjectName("faked//*:*"),null).
549.228 - contains(moi3.getObjectName()),true);
549.229 -
549.230 - System.out.println("Checking queryMBeans(faked//*:*,null)");
549.231 - assertEquals(proxy.queryMBeans(new ObjectName("faked//*:*"),null).
549.232 - contains(moi3),true);
549.233 -
549.234 - proxy.unregisterMBean(moi3.getObjectName());
549.235 -
549.236 - // ADD NEW TESTS HERE ^^^
549.237 -
549.238 - } finally {
549.239 - srv.stop();
549.240 - }
549.241 -
549.242 - if (failure != null)
549.243 - throw new Exception(failure);
549.244 -
549.245 -
549.246 - }
549.247 - private static void assertEquals(Object x, Object y) {
549.248 - if (!equal(x, y))
549.249 - failed("expected " + string(x) + "; got " + string(y));
549.250 - }
549.251 -
549.252 - private static boolean equal(Object x, Object y) {
549.253 - if (x == y)
549.254 - return true;
549.255 - if (x == null || y == null)
549.256 - return false;
549.257 - if (x.getClass().isArray())
549.258 - return Arrays.deepEquals(new Object[] {x}, new Object[] {y});
549.259 - return x.equals(y);
549.260 - }
549.261 -
549.262 - private static String string(Object x) {
549.263 - String s = Arrays.deepToString(new Object[] {x});
549.264 - return s.substring(1, s.length() - 1);
549.265 - }
549.266 -
549.267 -
549.268 - private static void failed(String why) {
549.269 - failure = why;
549.270 - new Throwable("FAILED: " + why).printStackTrace(System.out);
549.271 - }
549.272 -
549.273 - public static void main(String[] args) throws Exception {
549.274 - testRegister();
549.275 - }
549.276 -}
550.1 --- a/test/javax/management/namespace/QueryNamesTest.java Mon Nov 23 10:04:47 2009 +0000
550.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
550.3 @@ -1,473 +0,0 @@
550.4 -/*
550.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
550.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
550.7 - *
550.8 - * This code is free software; you can redistribute it and/or modify it
550.9 - * under the terms of the GNU General Public License version 2 only, as
550.10 - * published by the Free Software Foundation.
550.11 - *
550.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
550.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
550.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
550.15 - * version 2 for more details (a copy is included in the LICENSE file that
550.16 - * accompanied this code).
550.17 - *
550.18 - * You should have received a copy of the GNU General Public License version
550.19 - * 2 along with this work; if not, write to the Free Software Foundation,
550.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
550.21 - *
550.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
550.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
550.24 - * have any questions.
550.25 - */
550.26 -/*
550.27 - *
550.28 - * @test QueryNamesTest.java 1.4
550.29 - * @summary Test how queryNames works with Namespaces.
550.30 - * @author Daniel Fuchs
550.31 - * @bug 5072476 6768935
550.32 - * @run clean QueryNamesTest Wombat WombatMBean
550.33 - * @run build QueryNamesTest Wombat WombatMBean
550.34 - * @run main QueryNamesTest
550.35 - */
550.36 -
550.37 -
550.38 -import java.io.IOException;
550.39 -import java.lang.management.ManagementFactory;
550.40 -import java.util.ArrayList;
550.41 -import java.util.Arrays;
550.42 -import java.util.Collections;
550.43 -import java.util.HashMap;
550.44 -import java.util.HashSet;
550.45 -import java.util.LinkedHashMap;
550.46 -import java.util.LinkedHashSet;
550.47 -import java.util.LinkedList;
550.48 -import java.util.List;
550.49 -import java.util.Map;
550.50 -import java.util.Random;
550.51 -import java.util.Set;
550.52 -import java.util.logging.Logger;
550.53 -import javax.management.InstanceNotFoundException;
550.54 -import javax.management.JMException;
550.55 -import javax.management.MBeanServer;
550.56 -import javax.management.MBeanServerConnection;
550.57 -import javax.management.MBeanServerFactory;
550.58 -import javax.management.MalformedObjectNameException;
550.59 -import javax.management.ObjectInstance;
550.60 -import javax.management.ObjectName;
550.61 -import javax.management.RuntimeOperationsException;
550.62 -import javax.management.namespace.JMXNamespace;
550.63 -import javax.management.namespace.JMXNamespaces;
550.64 -
550.65 -/**
550.66 - * Class QueryNamesTest
550.67 - * @author Sun Microsystems, 2005 - All rights reserved.
550.68 - */
550.69 -public class QueryNamesTest {
550.70 -
550.71 - /**
550.72 - * A logger for this class.
550.73 - **/
550.74 - private static final Logger LOG =
550.75 - Logger.getLogger(QueryNamesTest.class.getName());
550.76 -
550.77 - public static class LocalNamespace
550.78 - extends JMXNamespace {
550.79 -
550.80 - private static MBeanServer check(MBeanServer server) {
550.81 - if (server == null)
550.82 - throw new IllegalArgumentException("MBeanServer can't be null");
550.83 - return server;
550.84 - }
550.85 -
550.86 - public LocalNamespace() {
550.87 - this(MBeanServerFactory.createMBeanServer());
550.88 - }
550.89 -
550.90 - public LocalNamespace(MBeanServer server) {
550.91 - super(check(server));
550.92 - }
550.93 -
550.94 -
550.95 - public static String add(MBeanServerConnection server,
550.96 - String nspath)
550.97 - throws IOException, JMException {
550.98 - server.createMBean(LocalNamespace.class.getName(),
550.99 - JMXNamespaces.getNamespaceObjectName(nspath));
550.100 - return nspath;
550.101 - }
550.102 - }
550.103 -
550.104 - /** Creates a new instance of QueryNamesTest */
550.105 - public QueryNamesTest() {
550.106 - }
550.107 -
550.108 - private static String[] namespaces = {
550.109 - "greg", "greg//chichille", "greg//chichille//petard",
550.110 - "greg//alambic", "greg//alambic//canette",
550.111 - "greg//chichille/virgule", "greg//chichille/funeste",
550.112 - "greg//chichille/virgule//bidouble",
550.113 - "greg//chichille/virgule//bi/double",
550.114 - "fran", "fran//gast", "fran//gast//gaf",
550.115 - "fran//longtar", "fran//longtar//parcmetre"
550.116 - };
550.117 -
550.118 - private static void createNamespaces(MBeanServer server) throws Exception {
550.119 - final LinkedList<String> all = new LinkedList<String>();
550.120 - try {
550.121 - for (String ns : namespaces)
550.122 - all.addFirst(LocalNamespace.add(server,ns));
550.123 - } catch (Exception e) {
550.124 - removeNamespaces(server,all.toArray(new String[all.size()]));
550.125 - throw e;
550.126 - }
550.127 - }
550.128 -
550.129 - // Dummy test that checks that all JMXNamespaces are registered,
550.130 - // but are not returned by queryNames("*:*");
550.131 - //
550.132 - private static void checkRegistration(MBeanServer server)
550.133 - throws Exception {
550.134 - final Set<ObjectName> handlerNames = new HashSet<ObjectName>(namespaces.length);
550.135 - for (String ns : namespaces)
550.136 - handlerNames.add(JMXNamespaces.getNamespaceObjectName(ns));
550.137 - for (ObjectName nh : handlerNames) // check handler registration
550.138 - if (!server.isRegistered(nh))
550.139 - throw new InstanceNotFoundException("handler "+nh+
550.140 - " is not registered");
550.141 -
550.142 - // global: queryNames("*:*") from top level
550.143 - final Set<ObjectName> all1 = server.queryNames(null,null);
550.144 - final Set<ObjectName> all2 = server.queryNames(ObjectName.WILDCARD,null);
550.145 - if (!all1.equals(all2))
550.146 - throw new Exception("queryNames(*:*) != queryNames(null)");
550.147 - final Set<ObjectName> common = new HashSet<ObjectName>(all1);
550.148 - common.retainAll(handlerNames);
550.149 -
550.150 - final Set<ObjectName> ref = new HashSet<ObjectName>();
550.151 - for (String ns : namespaces) {
550.152 - if (!ns.contains(JMXNamespaces.NAMESPACE_SEPARATOR))
550.153 - ref.add(JMXNamespaces.getNamespaceObjectName(ns));
550.154 - }
550.155 - if (!common.equals(ref)) {
550.156 - throw new Exception("some handler names were not returned by " +
550.157 - "wildcard query - only returned: "+common+
550.158 - ", expected: "+ref);
550.159 - }
550.160 -
550.161 - // for each namespace: queryNames("<namespace>//*:*");
550.162 - for (String ns : namespaces) {
550.163 - final ObjectName pattern = new ObjectName(ns+
550.164 - JMXNamespaces.NAMESPACE_SEPARATOR+"*:*");
550.165 - final Set<ObjectName> all4 =
550.166 - server.queryNames(pattern,null);
550.167 - final Set<ObjectName> common4 = new HashSet<ObjectName>(all4);
550.168 - common4.retainAll(handlerNames);
550.169 -
550.170 - final Set<ObjectName> ref4 = new HashSet<ObjectName>();
550.171 - for (String ns2 : namespaces) {
550.172 - if (! ns2.startsWith(ns+JMXNamespaces.NAMESPACE_SEPARATOR))
550.173 - continue;
550.174 - if (!ns2.substring(ns.length()+
550.175 - JMXNamespaces.NAMESPACE_SEPARATOR.length()).
550.176 - contains(JMXNamespaces.NAMESPACE_SEPARATOR))
550.177 - ref4.add(JMXNamespaces.getNamespaceObjectName(ns2));
550.178 - }
550.179 - if (!common4.equals(ref4)) {
550.180 - throw new Exception("some handler names were not returned by " +
550.181 - "wildcard query on "+pattern+" - only returned: "+common4+
550.182 - ", expected: "+ref4);
550.183 - }
550.184 - }
550.185 - }
550.186 -
550.187 - // Make a Map<parent, direct children>
550.188 - private static Map<String,Set<String>> makeNsTree(String[] nslist) {
550.189 - final Map<String,Set<String>> nsTree =
550.190 - new LinkedHashMap<String,Set<String>>(nslist.length);
550.191 - for (String ns : nslist) {
550.192 - if (nsTree.get(ns) == null)
550.193 - nsTree.put(ns,new LinkedHashSet<String>());
550.194 - final String[] elts = ns.split(JMXNamespaces.NAMESPACE_SEPARATOR);
550.195 - int last = ns.lastIndexOf(JMXNamespaces.NAMESPACE_SEPARATOR);
550.196 - if (last<0) continue;
550.197 - while (last > 0 && ns.charAt(last-1) == '/') last--;
550.198 - final String parent = ns.substring(0,last);
550.199 - if (nsTree.get(parent) == null)
550.200 - nsTree.put(parent,new LinkedHashSet<String>());
550.201 - nsTree.get(parent).add(ns);
550.202 - }
550.203 - return nsTree;
550.204 - }
550.205 -
550.206 - private static class Rigolo {
550.207 - final static String[] ones = { "a", "e", "i", "o", "u", "y", "ai", "oo",
550.208 - "ae", "ey", "ay", "oy", "au", "ou", "eu", "oi", "ei", "ea"};
550.209 - final static String[] twos = { "b", "bz", "c", "cz", "ch",
550.210 - "ct", "ck", "cs", "d", "ds", "f", "g", "gh", "h", "j", "k", "l", "m",
550.211 - "n", "p", "ps", "q", "r", "s", "sh", "t", "v", "w", "x",
550.212 - "z"};
550.213 - final static String[] threes = {"rr","tt","pp","ss","dd","ff","ll", "mm", "nn",
550.214 - "zz", "cc", "bb"};
550.215 - final static String[] fours = {"x", "s", "ght", "cks", "rt", "rts", "ghts", "bs",
550.216 - "ts", "gg" };
550.217 - final static String[] fives = { "br", "bl", "cr", "cn", "cth", "dr",
550.218 - "fr", "fl", "cl", "chr", "gr", "gl", "kr", "kh", "pr", "pl", "ph",
550.219 - "rh", "sr", "tr", "vr"};
550.220 -
550.221 - private Random rg = new Random();
550.222 -
550.223 - private String next(String[] table) {
550.224 - return table[rg.nextInt(table.length)];
550.225 - }
550.226 -
550.227 - public String nextName(int max) {
550.228 - final Random rg = new Random();
550.229 - final int nl = 3 + rg.nextInt(max);
550.230 - boolean begin = rg.nextBoolean();
550.231 - StringBuilder sb = new StringBuilder();
550.232 - for (int j = 0; j < nl ; j++) {
550.233 - if (begin) {
550.234 - sb.append(next(ones));
550.235 - } else if (j > 0 && j < nl-1 && rg.nextInt(4)==0) {
550.236 - sb.append(next(threes));
550.237 - } else if (j < nl-1 && rg.nextInt(3)==0) {
550.238 - sb.append(next(fives));
550.239 - } else {
550.240 - sb.append(next(twos));
550.241 - }
550.242 - begin = !begin;
550.243 - }
550.244 - if (!begin && rg.nextInt(2)==0)
550.245 - sb.append(next(fours));
550.246 - return sb.toString();
550.247 - }
550.248 -
550.249 - private ObjectName getWombatName(String ns, String domain, String name)
550.250 - throws MalformedObjectNameException {
550.251 - String d = domain;
550.252 - if (ns != null && !ns.equals(""))
550.253 - d = ns + JMXNamespaces.NAMESPACE_SEPARATOR + domain;
550.254 - return new ObjectName(d+":type=Wombat,name="+name);
550.255 - }
550.256 -
550.257 - public Set<ObjectName> nextWombats(String ns)
550.258 - throws MalformedObjectNameException {
550.259 - final int dcount = 1 + rg.nextInt(5);
550.260 - final Set<ObjectName> wombats = new HashSet<ObjectName>();
550.261 - for (int i = 0; i < dcount ; i++) {
550.262 - final String d = nextName(7);
550.263 - final int ncount = 5 + rg.nextInt(20);
550.264 - for (int j = 0 ; j<ncount; j++) {
550.265 - final String n = nextName(5);
550.266 - wombats.add(getWombatName(ns,d,n));
550.267 - }
550.268 - }
550.269 - return wombats;
550.270 - }
550.271 - }
550.272 -
550.273 - public static void checkNsQuery(MBeanServer server)
550.274 - throws Exception {
550.275 - final Map<String,Set<String>> nsTree = makeNsTree(namespaces);
550.276 - final Random rg = new Random();
550.277 - final Rigolo rigolo = new Rigolo();
550.278 - for (String ns : namespaces) {
550.279 - final ObjectName name = JMXNamespaces.getNamespaceObjectName(ns);
550.280 - final String[] doms =
550.281 - (String[])server.getAttribute(name,"Domains");
550.282 - final Set<String> subs = new HashSet<String>();
550.283 - for (String d : doms) {
550.284 - if (d.endsWith(JMXNamespaces.NAMESPACE_SEPARATOR)) {
550.285 - subs.add(ns+JMXNamespaces.NAMESPACE_SEPARATOR+d.substring(0,
550.286 - d.length()-JMXNamespaces.NAMESPACE_SEPARATOR.length()));
550.287 - }
550.288 - }
550.289 -
550.290 - final Set<String> expectNs = new HashSet<String>(nsTree.get(ns));
550.291 -
550.292 - if (! subs.containsAll(expectNs))
550.293 - throw new Exception("getDomains didn't return all namespaces: "+
550.294 - "returned="+subs+", expected="+expectNs);
550.295 - if (! expectNs.containsAll(subs))
550.296 - throw new Exception("getDomains returned additional namespaces: "+
550.297 - "returned="+subs+", expected="+expectNs);
550.298 -
550.299 - final Set<ObjectName> nsNames = server.queryNames(
550.300 - new ObjectName(ns+
550.301 - JMXNamespaces.NAMESPACE_SEPARATOR+"*"+
550.302 - JMXNamespaces.NAMESPACE_SEPARATOR+":*"),null);
550.303 -
550.304 - final Set<ObjectName> expect =
550.305 - new HashSet<ObjectName>(expectNs.size());
550.306 - for (String sub : expectNs) {
550.307 - expect.add(JMXNamespaces.getNamespaceObjectName(sub));
550.308 - }
550.309 -
550.310 - if (! nsNames.containsAll(expect))
550.311 - throw new Exception("queryNames didn't return all namespaces: "+
550.312 - "returned="+nsNames+", expected="+expect);
550.313 - if (! expect.containsAll(nsNames))
550.314 - throw new Exception("getDomains returned additional namespaces: "+
550.315 - "returned="+nsNames+", expected="+expect);
550.316 -
550.317 - }
550.318 - }
550.319 -
550.320 - private static void addWombats(MBeanServer server, Set<ObjectName> names)
550.321 - throws Exception {
550.322 - for (ObjectName on : names) {
550.323 - if (! server.isRegistered(on)) {
550.324 - server.createMBean(Wombat.class.getName(),on);
550.325 - System.out.println("A new wombat is born: "+on);
550.326 - }
550.327 - }
550.328 - }
550.329 -
550.330 - private static void addWombats(MBeanServer server,
550.331 - Map<String,Set<ObjectName>> wombats)
550.332 - throws Exception {
550.333 - for (String ns : wombats.keySet()) {
550.334 - addWombats(server,wombats.get(ns));
550.335 - }
550.336 - }
550.337 -
550.338 - private static Map<String,Set<ObjectName>> nameWombats()
550.339 - throws Exception {
550.340 - final Rigolo rigolo = new Rigolo();
550.341 - final Map<String,Set<ObjectName>> wombats =
550.342 - new HashMap<String,Set<ObjectName>>(namespaces.length);
550.343 -
550.344 - for (String ns : namespaces) {
550.345 - wombats.put(ns,rigolo.nextWombats(ns));
550.346 - }
550.347 - wombats.put("",rigolo.nextWombats(""));
550.348 - return wombats;
550.349 - }
550.350 -
550.351 - private static boolean removeWombats(MBeanServer server,
550.352 - Map<String,Set<ObjectName>> wombats) {
550.353 - boolean res = true;
550.354 - for (String ns : wombats.keySet()) {
550.355 - res = res && removeWombats(server,wombats.get(ns));
550.356 - }
550.357 - return res;
550.358 - }
550.359 -
550.360 - private static boolean removeWombats(MBeanServer server,
550.361 - Set<ObjectName> wombats) {
550.362 - boolean res = true;
550.363 - for (ObjectName on : wombats) {
550.364 - try {
550.365 - if (server.isRegistered(on))
550.366 - server.unregisterMBean(on);
550.367 - } catch (Exception x) {
550.368 - res = false;
550.369 - System.out.println("Failed to remove "+on+": "+x);
550.370 - }
550.371 - }
550.372 - return res;
550.373 - }
550.374 -
550.375 - private static void checkNsPattern(MBeanServer server) throws Exception {
550.376 - final List<String> list = new ArrayList<String>();
550.377 - for (String s : namespaces) {
550.378 - final String[] cmpnt = s.split("//");
550.379 - for (int i=0;i<cmpnt.length;i++) {
550.380 - final String[] clone = cmpnt.clone();
550.381 - if (clone[i].length() < 3) {
550.382 - clone[i] = "*";
550.383 - } else {
550.384 - clone[i] = "?"+cmpnt[i].substring(1, cmpnt[i].length()-2)+"*";
550.385 - }
550.386 - final StringBuilder sb = new StringBuilder();
550.387 - for (int j=0;j<cmpnt.length;j++) {
550.388 - sb.append(clone[j]).append("//");
550.389 - }
550.390 - list.add(sb.toString()+"*:*");
550.391 - }
550.392 - }
550.393 - for (String s : list) {
550.394 - final Set<ObjectName> res = new HashSet<ObjectName>();
550.395 -
550.396 - try {
550.397 - res.addAll(server.queryNames(ObjectName.valueOf(s),null));
550.398 - } catch (RuntimeOperationsException x) {
550.399 - if (x.getCause() instanceof IllegalArgumentException) {
550.400 - System.out.println("queryNames("+s+"): OK - received "+x.getCause());
550.401 - continue;
550.402 - }
550.403 - System.err.println("queryNames("+s+"): Bad cause: "+x.getCause());
550.404 - throw x;
550.405 - } catch (Exception x) {
550.406 - System.err.println("queryNames("+s+"): Bad exception: "+x);
550.407 - throw x;
550.408 - }
550.409 - System.err.println("queryNames("+s+"): Bad result: "+res);
550.410 - System.err.println("queryNames("+s+"): Excpected exception not thrown.");
550.411 - throw new Exception("queryNames("+s+"): Excpected exception not thrown.");
550.412 - }
550.413 - for (String s : list) {
550.414 - final Set<ObjectInstance> res = new HashSet<ObjectInstance>();
550.415 -
550.416 - try {
550.417 - res.addAll(server.queryMBeans(ObjectName.valueOf(s),null));
550.418 - } catch (RuntimeOperationsException x) {
550.419 - if (x.getCause() instanceof IllegalArgumentException) {
550.420 - System.out.println("queryMBeans("+s+"): OK - received "+x.getCause());
550.421 - continue;
550.422 - }
550.423 - System.err.println("queryMBeans("+s+"): Bad cause: "+x.getCause());
550.424 - throw x;
550.425 - } catch (Exception x) {
550.426 - System.err.println("queryMBeans("+s+"): Bad exception: "+x);
550.427 - throw x;
550.428 - }
550.429 - System.err.println("queryMBeans("+s+"): Bad result: "+res);
550.430 - System.err.println("queryMBeans("+s+"): Excpected exception not thrown.");
550.431 - throw new Exception("queryMBeans("+s+"): Excpected exception not thrown.");
550.432 - }
550.433 - }
550.434 -
550.435 - public static void main(String[] args)
550.436 - throws Exception {
550.437 - final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
550.438 - Map<String,Set<ObjectName>> wombats = nameWombats();
550.439 - createNamespaces(server);
550.440 - try {
550.441 - addWombats(server,wombats);
550.442 - System.out.println("MBeans: " +server.getMBeanCount());
550.443 - System.out.println("Visible: " +server.queryNames(null,null).size());
550.444 - System.out.println("Domains: " +Arrays.asList(server.getDomains()));
550.445 - checkRegistration(server);
550.446 - checkNsQuery(server);
550.447 - checkNsPattern(server);
550.448 - } finally {
550.449 - boolean res = true;
550.450 - res = res && removeWombats(server, wombats);
550.451 - if (!res)
550.452 - throw new RuntimeException("failed to cleanup some namespaces");
550.453 - }
550.454 -
550.455 - }
550.456 -
550.457 - private static boolean removeNamespaces(MBeanServer server) {
550.458 - final List<String> l = Arrays.asList(namespaces);
550.459 - Collections.reverse(l);
550.460 - return removeNamespaces(server, l.toArray(new String[namespaces.length]));
550.461 - }
550.462 -
550.463 - private static boolean removeNamespaces(MBeanServer server, String[] t) {
550.464 - boolean success = true;
550.465 - for (String ns : t) {
550.466 - try {
550.467 - server.unregisterMBean(JMXNamespaces.getNamespaceObjectName(ns));
550.468 - } catch (Exception x) {
550.469 - System.out.println("failed to remove namespace: "+ ns);
550.470 - success = false;
550.471 - }
550.472 - }
550.473 - return success;
550.474 - }
550.475 -
550.476 -}
551.1 --- a/test/javax/management/namespace/RemoveNotificationListenerTest.java Mon Nov 23 10:04:47 2009 +0000
551.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
551.3 @@ -1,377 +0,0 @@
551.4 -/*
551.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
551.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
551.7 - *
551.8 - * This code is free software; you can redistribute it and/or modify it
551.9 - * under the terms of the GNU General Public License version 2 only, as
551.10 - * published by the Free Software Foundation.
551.11 - *
551.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
551.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
551.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
551.15 - * version 2 for more details (a copy is included in the LICENSE file that
551.16 - * accompanied this code).
551.17 - *
551.18 - * You should have received a copy of the GNU General Public License version
551.19 - * 2 along with this work; if not, write to the Free Software Foundation,
551.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
551.21 - *
551.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
551.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
551.24 - * have any questions.
551.25 - */
551.26 -/*
551.27 - *
551.28 - * @test RemoveNotificationListenerTest.java 1.8
551.29 - * @summary General RemoveNotificationListenerTest test.
551.30 - * @author Daniel Fuchs
551.31 - * @bug 5072476
551.32 - * @run clean RemoveNotificationListenerTest JMXRemoteTargetNamespace
551.33 - * @compile -XDignore.symbol.file=true JMXRemoteTargetNamespace.java
551.34 - * @run build RemoveNotificationListenerTest JMXRemoteTargetNamespace
551.35 - * @run main/othervm RemoveNotificationListenerTest
551.36 - */
551.37 -
551.38 -import com.sun.jmx.remote.util.EventClientConnection;
551.39 -import java.io.IOException;
551.40 -import java.lang.management.ManagementFactory;
551.41 -import java.security.Principal;
551.42 -import java.util.Arrays;
551.43 -import java.util.Collections;
551.44 -import java.util.HashMap;
551.45 -import java.util.HashSet;
551.46 -import java.util.Map;
551.47 -import java.util.Set;
551.48 -import java.util.concurrent.ArrayBlockingQueue;
551.49 -import java.util.concurrent.BlockingQueue;
551.50 -import java.util.concurrent.TimeUnit;
551.51 -import java.util.logging.Logger;
551.52 -import javax.management.JMException;
551.53 -import javax.management.JMX;
551.54 -import javax.management.MBeanNotificationInfo;
551.55 -import javax.management.MBeanServer;
551.56 -import javax.management.MBeanServerConnection;
551.57 -import javax.management.MBeanServerFactory;
551.58 -import javax.management.Notification;
551.59 -import javax.management.NotificationBroadcasterSupport;
551.60 -import javax.management.NotificationEmitter;
551.61 -import javax.management.NotificationListener;
551.62 -import javax.management.ObjectName;
551.63 -import javax.management.namespace.JMXNamespaces;
551.64 -import javax.management.remote.JMXAuthenticator;
551.65 -import javax.management.remote.JMXConnector;
551.66 -import javax.management.remote.JMXConnectorFactory;
551.67 -import javax.management.remote.JMXConnectorServer;
551.68 -import javax.management.remote.JMXConnectorServerFactory;
551.69 -import javax.management.remote.JMXConnectorServerMBean;
551.70 -import javax.management.remote.JMXPrincipal;
551.71 -import javax.management.remote.JMXServiceURL;
551.72 -import javax.security.auth.Subject;
551.73 -
551.74 -/**
551.75 - * Class RemoveNotificationListenerTest
551.76 - */
551.77 -public class RemoveNotificationListenerTest {
551.78 -
551.79 - /**
551.80 - * A logger for this class.
551.81 - **/
551.82 - private static final Logger LOG =
551.83 - Logger.getLogger(RemoveNotificationListenerTest.class.getName());
551.84 -
551.85 - /** Creates a new instance of RemoveNotificationListenerTest */
551.86 - public RemoveNotificationListenerTest() {
551.87 - }
551.88 -
551.89 - public static class SubjectAuthenticator implements JMXAuthenticator {
551.90 - final Set<Subject> authorized;
551.91 - public SubjectAuthenticator(Subject[] authorized) {
551.92 - this.authorized = new HashSet<Subject>(Arrays.asList(authorized));
551.93 - }
551.94 -
551.95 - public Subject authenticate(Object credentials) {
551.96 - if (authorized.contains(credentials))
551.97 - return (Subject)credentials;
551.98 - else
551.99 - throw new SecurityException("Subject not authorized: "+credentials);
551.100 - }
551.101 -
551.102 - }
551.103 -
551.104 - public static interface LongtarMBean {
551.105 - public void sendNotification(Object userData)
551.106 - throws IOException, JMException;
551.107 - }
551.108 - public static class Longtar extends NotificationBroadcasterSupport
551.109 - implements LongtarMBean {
551.110 - public Longtar() {
551.111 - super(new MBeanNotificationInfo[] {
551.112 - new MBeanNotificationInfo(new String[] {"papillon"},
551.113 - "pv","M'enfin???")
551.114 - });
551.115 - }
551.116 -
551.117 - public void sendNotification(Object userData)
551.118 - throws IOException, JMException {
551.119 - final Notification n =
551.120 - new Notification("papillon",this,nextseq(),"M'enfin???");
551.121 - n.setUserData(userData);
551.122 - System.out.println("Sending notification: "+userData);
551.123 - sendNotification(n);
551.124 - }
551.125 -
551.126 - private static synchronized long nextseq() {return ++seqnb;}
551.127 - private static volatile long seqnb=0;
551.128 - }
551.129 -
551.130 - private static final String NS = JMXNamespaces.NAMESPACE_SEPARATOR;
551.131 - private static final String CS = "jmx.rmi:type=JMXConnectorServer";
551.132 - private static final String BD = "longtar:type=Longtar";
551.133 -
551.134 - private static void createNamespace(MBeanServerConnection server,
551.135 - String namespace, Subject creator, boolean forwarding)
551.136 - throws Exception {
551.137 - final MBeanServer sub = MBeanServerFactory.createMBeanServer();
551.138 - final JMXServiceURL url = new JMXServiceURL("rmi",null,0);
551.139 - final Map<String,Object> smap = new HashMap<String,Object>();
551.140 - smap.put(JMXConnectorServer.AUTHENTICATOR,
551.141 - new SubjectAuthenticator(new Subject[] {creator}));
551.142 - final JMXConnectorServer rmi =
551.143 - JMXConnectorServerFactory.newJMXConnectorServer(url,smap,null);
551.144 - final ObjectName name = new ObjectName(CS);
551.145 - sub.registerMBean(rmi,name);
551.146 - rmi.start();
551.147 - final Map<String,Object> cmap = new HashMap<String,Object>();
551.148 - cmap.put(JMXConnector.CREDENTIALS,creator);
551.149 - final Map<String,Object> options = new HashMap<String,Object>(cmap);
551.150 - options.put(JMXRemoteTargetNamespace.CREATE_EVENT_CLIENT,"true");
551.151 - JMXRemoteTargetNamespace.createNamespace(server,
551.152 - namespace,
551.153 - rmi.getAddress(),
551.154 - options
551.155 - );
551.156 - server.invoke(JMXNamespaces.getNamespaceObjectName(namespace),
551.157 - "connect", null,null);
551.158 - }
551.159 - private static void closeNamespace(MBeanServerConnection server,
551.160 - String namespace) {
551.161 - try {
551.162 - final ObjectName hname =
551.163 - JMXNamespaces.getNamespaceObjectName(namespace);
551.164 - if (!server.isRegistered(hname))
551.165 - return;
551.166 - final ObjectName sname =
551.167 - new ObjectName(namespace+NS+CS);
551.168 - if (!server.isRegistered(sname))
551.169 - return;
551.170 - final JMXConnectorServerMBean cs =
551.171 - JMX.newMBeanProxy(server,sname,
551.172 - JMXConnectorServerMBean.class,true);
551.173 - try {
551.174 - cs.stop();
551.175 - } finally {
551.176 - server.unregisterMBean(hname);
551.177 - }
551.178 - } catch (Throwable t) {
551.179 - t.printStackTrace();
551.180 - }
551.181 - }
551.182 -
551.183 - private static Subject newSubject(String[] principals) {
551.184 - final Set<Principal> ps = new HashSet<Principal>();
551.185 - for (String p:principals) ps.add(new JMXPrincipal(p));
551.186 - return new Subject(true,ps,Collections.emptySet(),Collections.emptySet());
551.187 - }
551.188 -
551.189 -
551.190 - public static void testSubject() throws Exception {
551.191 - final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
551.192 - final String a = "a";
551.193 - final String b = a + NS + "b";
551.194 -
551.195 - final Subject s1 = newSubject(new String[] {"chichille"});
551.196 - final Subject s2 = newSubject(new String[] {"alambic"});
551.197 - final Subject s3 = newSubject(new String[] {"virgule"});
551.198 - final Subject s4 = newSubject(new String[] {"funeste"});
551.199 -
551.200 - final JMXServiceURL url = new JMXServiceURL("rmi",null,0);
551.201 - final Map<String,Object> smap = new HashMap<String,Object>();
551.202 - smap.put(JMXConnectorServer.AUTHENTICATOR,
551.203 - new SubjectAuthenticator(new Subject[] {s1}));
551.204 - final JMXConnectorServer rmi =
551.205 - JMXConnectorServerFactory.newJMXConnectorServer(url,smap,null);
551.206 - final ObjectName name = new ObjectName(CS);
551.207 - server.registerMBean(rmi,name);
551.208 - rmi.start();
551.209 -
551.210 - try {
551.211 -
551.212 - final Map<String,Object> map = new HashMap<String,Object>();
551.213 - map.put(JMXConnector.CREDENTIALS,s1);
551.214 - final JMXConnector c =
551.215 - JMXConnectorFactory.connect(rmi.getAddress(),map);
551.216 - final MBeanServerConnection mbsorig = c.getMBeanServerConnection();
551.217 -
551.218 - final MBeanServerConnection mbs =
551.219 - EventClientConnection.getEventConnectionFor(mbsorig,null);
551.220 -
551.221 - createNamespace(mbs,a,s2,true);
551.222 - createNamespace(mbs,b,s3,true);
551.223 -
551.224 - final ObjectName longtar = new ObjectName(b+NS+BD);
551.225 -
551.226 - mbs.createMBean(Longtar.class.getName(),longtar);
551.227 - final LongtarMBean proxy =
551.228 - JMX.newMBeanProxy(mbs,longtar,LongtarMBean.class,true);
551.229 -
551.230 -
551.231 - final BlockingQueue<Notification> bbq =
551.232 - new ArrayBlockingQueue<Notification>(10);
551.233 - final NotificationListener listener1 = new NotificationListener() {
551.234 - public void handleNotification(Notification notification,
551.235 - Object handback) {
551.236 - System.out.println(notification.getSequenceNumber()+": "+
551.237 - notification.getMessage());
551.238 - bbq.add(notification);
551.239 - }
551.240 - };
551.241 - final NotificationListener listener2 = new NotificationListener() {
551.242 - public void handleNotification(Notification notification,
551.243 - Object handback) {
551.244 - System.out.println(notification.getSequenceNumber()+": "+
551.245 - notification.getMessage());
551.246 - bbq.add(notification);
551.247 - }
551.248 - };
551.249 -
551.250 - final NotificationEmitter ubpdalfdla = (NotificationEmitter)proxy;
551.251 - try {
551.252 -
551.253 - // Add 1 NL, send 1 notif (1)
551.254 - ubpdalfdla.addNotificationListener(listener1,null,listener1);
551.255 - proxy.sendNotification(new Integer(1));
551.256 - // Thread.sleep(180000);
551.257 -
551.258 - // We should have 1 notif with userdata = 1
551.259 - final Notification n1 = bbq.poll(3,TimeUnit.SECONDS);
551.260 - // may throw NPE => would indicate a bug.
551.261 - if (((Integer)n1.getUserData()).intValue() != 1)
551.262 - throw new Exception("Expected 1, got"+n1.getUserData());
551.263 -
551.264 - // remove NL, send 1 notif (2) => we shouldn't receive it
551.265 - ubpdalfdla.removeNotificationListener(listener1,null,listener1);
551.266 - proxy.sendNotification(new Integer(2));
551.267 -
551.268 - // add NL, send 1 notif (3)
551.269 - ubpdalfdla.addNotificationListener(listener1,null,listener1);
551.270 - proxy.sendNotification(new Integer(3));
551.271 -
551.272 - // we should receive only 1 notif (3)
551.273 - final Notification n3 = bbq.poll(3,TimeUnit.SECONDS);
551.274 - // may throw NPE => would indicate a bug.
551.275 - if (((Integer)n3.getUserData()).intValue() != 3)
551.276 - throw new Exception("Expected 3, got"+n3.getUserData());
551.277 -
551.278 - // remove NL, send 1 notif (4) => we shouldn't receive it.
551.279 - ubpdalfdla.removeNotificationListener(listener1);
551.280 - proxy.sendNotification(new Integer(4));
551.281 -
551.282 - // add NL, send 1 notif (5).
551.283 - ubpdalfdla.addNotificationListener(listener1,null,listener1);
551.284 - proxy.sendNotification(new Integer(5));
551.285 -
551.286 - // next notif in queue should be (5)
551.287 - final Notification n5 = bbq.poll(3,TimeUnit.SECONDS);
551.288 - // may throw NPE => would indicate a bug.
551.289 - if (((Integer)n5.getUserData()).intValue() != 5)
551.290 - throw new Exception("Expected 5, got"+n5.getUserData());
551.291 -
551.292 - // add 2 NL, send 1 notif (6)
551.293 - ubpdalfdla.addNotificationListener(listener2,null,listener2);
551.294 - ubpdalfdla.addNotificationListener(listener2,null,null);
551.295 - proxy.sendNotification(new Integer(6));
551.296 -
551.297 - // We have 3 NL, we should receive (6) 3 times....
551.298 - final Notification n61 = bbq.poll(3,TimeUnit.SECONDS);
551.299 - // may throw NPE => would indicate a bug.
551.300 - if (((Integer)n61.getUserData()).intValue() != 6)
551.301 - throw new Exception("Expected 6 (#1), got"+n61.getUserData());
551.302 - final Notification n62 = bbq.poll(3,TimeUnit.SECONDS);
551.303 - // may throw NPE => would indicate a bug.
551.304 - if (((Integer)n62.getUserData()).intValue() != 6)
551.305 - throw new Exception("Expected 6 (#2), got"+n62.getUserData());
551.306 - final Notification n63 = bbq.poll(3,TimeUnit.SECONDS);
551.307 - // may throw NPE => would indicate a bug.
551.308 - if (((Integer)n63.getUserData()).intValue() != 6)
551.309 - throw new Exception("Expected 6 (#3), got"+n63.getUserData());
551.310 -
551.311 - // Remove 1 NL, send 1 notif (7)
551.312 - ubpdalfdla.removeNotificationListener(listener2,null,null);
551.313 - proxy.sendNotification(new Integer(7));
551.314 -
551.315 - // next notifs in queue should be (7), twice...
551.316 - final Notification n71 = bbq.poll(3,TimeUnit.SECONDS);
551.317 - // may throw NPE => would indicate a bug.
551.318 - if (((Integer)n71.getUserData()).intValue() != 7)
551.319 - throw new Exception("Expected 7 (#1), got"+n71.getUserData());
551.320 - final Notification n72 = bbq.poll(3,TimeUnit.SECONDS);
551.321 - // may throw NPE => would indicate a bug.
551.322 - if (((Integer)n72.getUserData()).intValue() != 7)
551.323 - throw new Exception("Expected 7 (#2), got"+n72.getUserData());
551.324 -
551.325 - // Add 1 NL, send 1 notif (8)
551.326 - ubpdalfdla.addNotificationListener(listener2,null,null);
551.327 - proxy.sendNotification(new Integer(8));
551.328 -
551.329 - // Next notifs in queue should be (8), 3 times.
551.330 - final Notification n81 = bbq.poll(3,TimeUnit.SECONDS);
551.331 - // may throw NPE => would indicate a bug.
551.332 - if (((Integer)n81.getUserData()).intValue() != 8)
551.333 - throw new Exception("Expected 8 (#1), got"+n81.getUserData());
551.334 - final Notification n82 = bbq.poll(3,TimeUnit.SECONDS);
551.335 - // may throw NPE => would indicate a bug.
551.336 - if (((Integer)n82.getUserData()).intValue() != 8)
551.337 - throw new Exception("Expected 8 (#2), got"+n82.getUserData());
551.338 - final Notification n83 = bbq.poll(3,TimeUnit.SECONDS);
551.339 - // may throw NPE => would indicate a bug.
551.340 - if (((Integer)n83.getUserData()).intValue() != 8)
551.341 - throw new Exception("Expected 8 (#3), got"+n83.getUserData());
551.342 -
551.343 - // Remove 2 NL, send 1 notif (9)
551.344 - ubpdalfdla.removeNotificationListener(listener2);
551.345 - proxy.sendNotification(new Integer(9));
551.346 -
551.347 - // Next notifs in queue should be (9), 1 time only.
551.348 - final Notification n9 = bbq.poll(3,TimeUnit.SECONDS);
551.349 - // may throw NPE => would indicate a bug.
551.350 - if (((Integer)n9.getUserData()).intValue() != 9)
551.351 - throw new Exception("Expected 9, got"+n9.getUserData());
551.352 -
551.353 - // send 1 notif (10)
551.354 - proxy.sendNotification(new Integer(10));
551.355 -
551.356 - // Next notifs in queue should be (10), 1 time only.
551.357 - final Notification n10 = bbq.poll(3,TimeUnit.SECONDS);
551.358 - // may throw NPE => would indicate a bug.
551.359 - if (((Integer)n10.getUserData()).intValue() != 10)
551.360 - throw new Exception("Expected 10, got"+n10.getUserData());
551.361 -
551.362 - ubpdalfdla.removeNotificationListener(listener1);
551.363 - mbs.unregisterMBean(longtar);
551.364 -
551.365 - } finally {
551.366 - c.close();
551.367 - }
551.368 - } finally {
551.369 - closeNamespace(server,b);
551.370 - closeNamespace(server,a);
551.371 - rmi.stop();
551.372 - }
551.373 -
551.374 - }
551.375 -
551.376 - public static void main(String[] args) throws Exception {
551.377 - testSubject();
551.378 - }
551.379 -
551.380 -}
552.1 --- a/test/javax/management/namespace/RoutingServerProxyTest.java Mon Nov 23 10:04:47 2009 +0000
552.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
552.3 @@ -1,400 +0,0 @@
552.4 -/*
552.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
552.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
552.7 - *
552.8 - * This code is free software; you can redistribute it and/or modify it
552.9 - * under the terms of the GNU General Public License version 2 only, as
552.10 - * published by the Free Software Foundation.
552.11 - *
552.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
552.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
552.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
552.15 - * version 2 for more details (a copy is included in the LICENSE file that
552.16 - * accompanied this code).
552.17 - *
552.18 - * You should have received a copy of the GNU General Public License version
552.19 - * 2 along with this work; if not, write to the Free Software Foundation,
552.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
552.21 - *
552.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
552.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
552.24 - * have any questions.
552.25 - */
552.26 -
552.27 -/*
552.28 - * @test RoutingServerProxyTest.java 1.6
552.29 - * @summary General RoutingServerProxyTest test.
552.30 - * @author Daniel Fuchs
552.31 - * @bug 5072476
552.32 - * @run clean RoutingServerProxyTest Wombat WombatMBean
552.33 - * @compile -XDignore.symbol.file=true RoutingServerProxyTest.java
552.34 - * @run build RoutingServerProxyTest Wombat WombatMBean
552.35 - * @run main RoutingServerProxyTest
552.36 - */
552.37 -
552.38 -import com.sun.jmx.namespace.RoutingServerProxy;
552.39 -import java.io.IOException;
552.40 -import java.util.Collections;
552.41 -import java.util.Map;
552.42 -import java.util.Set;
552.43 -import java.util.concurrent.ConcurrentHashMap;
552.44 -import java.util.logging.Logger;
552.45 -
552.46 -import javax.management.DynamicMBean;
552.47 -import javax.management.InstanceNotFoundException;
552.48 -import javax.management.JMException;
552.49 -import javax.management.JMX;
552.50 -import javax.management.MBeanInfo;
552.51 -import javax.management.MBeanRegistration;
552.52 -import javax.management.MBeanServer;
552.53 -import javax.management.MBeanServerFactory;
552.54 -import javax.management.MalformedObjectNameException;
552.55 -import javax.management.NotCompliantMBeanException;
552.56 -import javax.management.NotificationEmitter;
552.57 -import javax.management.ObjectInstance;
552.58 -import javax.management.ObjectName;
552.59 -import javax.management.StandardEmitterMBean;
552.60 -import javax.management.namespace.JMXNamespace;
552.61 -import javax.management.namespace.JMXNamespaces;
552.62 -import javax.management.namespace.MBeanServerSupport;
552.63 -
552.64 -/**
552.65 - * Class RoutingServerProxyTest
552.66 - *
552.67 - * @author Sun Microsystems, Inc.
552.68 - */
552.69 -public class RoutingServerProxyTest {
552.70 -
552.71 - /**
552.72 - * A logger for this class.
552.73 - **/
552.74 - private static final Logger LOG =
552.75 - Logger.getLogger(RoutingServerProxyTest.class.getName());
552.76 -
552.77 - /**
552.78 - * Creates a new instance of RoutingServerProxyTest
552.79 - */
552.80 - public RoutingServerProxyTest() {
552.81 - }
552.82 -
552.83 - public static class DynamicWombat extends StandardEmitterMBean {
552.84 - DynamicWombat(Wombat w) throws NotCompliantMBeanException {
552.85 - super(w,WombatMBean.class,w);
552.86 - }
552.87 -
552.88 - @Override
552.89 - public ObjectName preRegister(MBeanServer server, ObjectName name)
552.90 - throws Exception {
552.91 - final ObjectName myname = ((Wombat)getImplementation()).
552.92 - preRegister(server,name);
552.93 - return super.preRegister(server,myname);
552.94 - }
552.95 -
552.96 - @Override
552.97 - public void postRegister(Boolean registrationDone) {
552.98 - try {
552.99 - ((Wombat)getImplementation()).
552.100 - postRegister(registrationDone);
552.101 - } finally {
552.102 - super.postRegister(registrationDone);
552.103 - }
552.104 - }
552.105 -
552.106 - @Override
552.107 - public void preDeregister() throws Exception {
552.108 - ((Wombat)getImplementation()).
552.109 - preDeregister();
552.110 - super.preDeregister();
552.111 -
552.112 - }
552.113 -
552.114 - @Override
552.115 - public void postDeregister() {
552.116 - try {
552.117 - ((Wombat)getImplementation()).
552.118 - postDeregister();
552.119 - } finally {
552.120 - super.postDeregister();
552.121 - }
552.122 - }
552.123 - }
552.124 -
552.125 - public static class VirtualWombatHandler
552.126 - extends JMXNamespace {
552.127 -
552.128 - public static class VirtualWombatRepository
552.129 - extends MBeanServerSupport {
552.130 -
552.131 - final Map<ObjectName, DynamicMBean> bush;
552.132 -
552.133 - VirtualWombatRepository(Map<ObjectName, DynamicMBean> bush) {
552.134 - this.bush = bush;
552.135 - }
552.136 -
552.137 - @Override
552.138 - protected Set<ObjectName> getNames() {
552.139 - return bush.keySet();
552.140 - }
552.141 -
552.142 - @Override
552.143 - public DynamicMBean getDynamicMBeanFor(ObjectName name)
552.144 - throws InstanceNotFoundException {
552.145 - final DynamicMBean mb = bush.get(name);
552.146 - if (mb == null) {
552.147 - throw new InstanceNotFoundException(String.valueOf(name));
552.148 - }
552.149 - return mb;
552.150 - }
552.151 -
552.152 - @Override
552.153 - public NotificationEmitter getNotificationEmitterFor(
552.154 - ObjectName name) throws InstanceNotFoundException {
552.155 - DynamicMBean mbean = getDynamicMBeanFor(name);
552.156 - if (mbean instanceof NotificationEmitter) {
552.157 - return (NotificationEmitter) mbean;
552.158 - }
552.159 - return null;
552.160 - }
552.161 - }
552.162 - VirtualWombatRepository bush;
552.163 -
552.164 - VirtualWombatHandler(Map<ObjectName, DynamicMBean> bush) {
552.165 - this(new VirtualWombatRepository(Collections.synchronizedMap(bush)));
552.166 - }
552.167 -
552.168 - private VirtualWombatHandler(VirtualWombatRepository repository) {
552.169 - super(repository);
552.170 - bush = repository;
552.171 - }
552.172 -
552.173 - @Override
552.174 - public ObjectName preRegister(MBeanServer server, ObjectName name)
552.175 - throws Exception {
552.176 - final ObjectName myname = super.preRegister(server, name);
552.177 - return myname;
552.178 - }
552.179 -
552.180 - @Override
552.181 - public void postRegister(Boolean registrationDone) {
552.182 - if (!registrationDone.booleanValue()) {
552.183 - return;
552.184 - }
552.185 - final MBeanServer me = JMXNamespaces.narrowToNamespace(getMBeanServer(),
552.186 - getObjectName().getDomain());
552.187 - for (Map.Entry<ObjectName, DynamicMBean> e : bush.bush.entrySet()) {
552.188 - final DynamicMBean obj = e.getValue();
552.189 - try {
552.190 - if (obj instanceof MBeanRegistration) {
552.191 - ((MBeanRegistration) obj).preRegister(me, e.getKey());
552.192 - }
552.193 - } catch (Exception x) {
552.194 - System.err.println("preRegister failed for " +
552.195 - e.getKey() + ": " + x);
552.196 - bush.bush.remove(e.getKey());
552.197 - }
552.198 - }
552.199 - for (Map.Entry<ObjectName, DynamicMBean> e : bush.bush.entrySet()) {
552.200 - final Object obj = e.getValue();
552.201 - if (obj instanceof MBeanRegistration) {
552.202 - ((MBeanRegistration) obj).postRegister(registrationDone);
552.203 - }
552.204 - }
552.205 - }
552.206 -
552.207 - @Override
552.208 - public void preDeregister() throws Exception {
552.209 - for (Map.Entry<ObjectName, DynamicMBean> e : bush.bush.entrySet()) {
552.210 - final Object obj = e.getValue();
552.211 - if (obj instanceof MBeanRegistration) {
552.212 - ((MBeanRegistration) obj).preDeregister();
552.213 - }
552.214 - }
552.215 - }
552.216 -
552.217 - @Override
552.218 - public void postDeregister() {
552.219 - for (Map.Entry<ObjectName, DynamicMBean> e : bush.bush.entrySet()) {
552.220 - final Object obj = e.getValue();
552.221 - if (obj instanceof MBeanRegistration) {
552.222 - ((MBeanRegistration) obj).postDeregister();
552.223 - }
552.224 - }
552.225 - }
552.226 - }
552.227 -
552.228 - public static ObjectName getWombatName(String name)
552.229 - throws MalformedObjectNameException {
552.230 - return ObjectName.getInstance("australian.bush:type=Wombat,name="+name);
552.231 - }
552.232 -
552.233 - public static ObjectName addDir(String dir, ObjectName name)
552.234 - throws MalformedObjectNameException {
552.235 - return name.withDomain(
552.236 - dir+JMXNamespaces.NAMESPACE_SEPARATOR+ name.getDomain());
552.237 - }
552.238 -
552.239 - public static void simpleTest()
552.240 - throws JMException, IOException {
552.241 - final MBeanServer master = MBeanServerFactory.createMBeanServer();
552.242 - final MBeanServer agent1 = MBeanServerFactory.createMBeanServer();
552.243 - final Wombat w1 = new Wombat();
552.244 - final Wombat w2 = new Wombat();
552.245 - final Wombat w3 = new Wombat();
552.246 - final Map<ObjectName,DynamicMBean> wombats =
552.247 - new ConcurrentHashMap<ObjectName,DynamicMBean>();
552.248 - wombats.put(getWombatName("LittleWombat"),
552.249 - new DynamicWombat(w2));
552.250 - wombats.put(getWombatName("BigWombat"),
552.251 - new DynamicWombat(w3));
552.252 - final Wombat w4 = new Wombat();
552.253 - final Wombat w5 = new Wombat();
552.254 -
552.255 - final JMXNamespace agent2 =
552.256 - new VirtualWombatHandler(wombats);
552.257 - agent1.registerMBean(w4,getWombatName("LittleWombat"));
552.258 - master.registerMBean(w1,getWombatName("LittleWombat"));
552.259 - master.registerMBean(new JMXNamespace(agent1),
552.260 - JMXNamespaces.getNamespaceObjectName("south.east"));
552.261 - master.registerMBean(agent2,
552.262 - JMXNamespaces.getNamespaceObjectName("north"));
552.263 - master.registerMBean(w5,addDir("south.east",
552.264 - getWombatName("GrandWombat")));
552.265 -
552.266 - MBeanServer se = null;
552.267 -
552.268 - try {
552.269 - se = JMXNamespaces.narrowToNamespace(master,"south.easht");
552.270 - } catch (Exception x) {
552.271 - System.out.println("Caught expected exception: "+x);
552.272 - }
552.273 - if (se != null)
552.274 - throw new RuntimeException("Expected exception for "+
552.275 - "cd(south.easht)");
552.276 - se = JMXNamespaces.narrowToNamespace(master,"south.east");
552.277 -
552.278 - MBeanServer nth = JMXNamespaces.narrowToNamespace(master,"north");
552.279 -
552.280 - final ObjectName ln = getWombatName("LittleWombat");
552.281 - MBeanInfo mb1 = master.getMBeanInfo(ln);
552.282 - MBeanInfo mb2 = se.getMBeanInfo(ln);
552.283 - MBeanInfo mb3 = nth.getMBeanInfo(ln);
552.284 -
552.285 - final WombatMBean grand = JMX.newMBeanProxy(se,
552.286 - getWombatName("GrandWombat"),WombatMBean.class);
552.287 - final WombatMBean big = JMX.newMBeanProxy(nth,
552.288 - getWombatName("BigWombat"),WombatMBean.class);
552.289 - grand.getCaption();
552.290 - big.getCaption();
552.291 - grand.setCaption("I am GrandWombat");
552.292 - big.setCaption("I am BigWombat");
552.293 -
552.294 - final WombatMBean grand2 =
552.295 - JMX.newMBeanProxy(master,addDir("south.east",
552.296 - getWombatName("GrandWombat")),WombatMBean.class);
552.297 - final WombatMBean big2 =
552.298 - JMX.newMBeanProxy(master,addDir("north",
552.299 - getWombatName("BigWombat")),WombatMBean.class);
552.300 - if (!"I am GrandWombat".equals(grand2.getCaption()))
552.301 - throw new RuntimeException("bad caption for GrandWombat"+
552.302 - grand2.getCaption());
552.303 - if (!"I am BigWombat".equals(big2.getCaption()))
552.304 - throw new RuntimeException("bad caption for BigWombat"+
552.305 - big2.getCaption());
552.306 -
552.307 -
552.308 - final Set<ObjectInstance> northWombats =
552.309 - nth.queryMBeans(ObjectName.WILDCARD,null);
552.310 - final Set<ObjectInstance> seWombats =
552.311 - se.queryMBeans(ObjectName.WILDCARD,null);
552.312 - if (!northWombats.equals(
552.313 - agent2.getSourceServer().queryMBeans(ObjectName.WILDCARD,null))) {
552.314 - throw new RuntimeException("Bad Wombat census in northern territory: got "
552.315 - +northWombats+", expected "+
552.316 - agent2.getSourceServer().
552.317 - queryMBeans(ObjectName.WILDCARD,null));
552.318 - }
552.319 - if (!seWombats.equals(
552.320 - agent1.queryMBeans(ObjectName.WILDCARD,null))) {
552.321 - throw new RuntimeException("Bad Wombat census in south east: got "
552.322 - +seWombats+", expected "+
552.323 - agent1.
552.324 - queryMBeans(ObjectName.WILDCARD,null));
552.325 - }
552.326 -
552.327 - final MBeanServer supermaster = MBeanServerFactory.createMBeanServer();
552.328 - supermaster.registerMBean(new JMXNamespace(master),
552.329 - JMXNamespaces.getNamespaceObjectName("australia"));
552.330 - final MBeanServer proxymaster =
552.331 - JMXNamespaces.narrowToNamespace(supermaster,"australia");
552.332 - final MBeanServer sem =
552.333 - JMXNamespaces.narrowToNamespace(proxymaster,"south.east");
552.334 - final MBeanServer nthm =
552.335 - JMXNamespaces.narrowToNamespace(proxymaster,"north");
552.336 - final Set<ObjectInstance> northWombats2 =
552.337 - nthm.queryMBeans(ObjectName.WILDCARD,null);
552.338 - final Set<ObjectInstance> seWombats2 =
552.339 - sem.queryMBeans(ObjectName.WILDCARD,null);
552.340 - if (!northWombats2.equals(
552.341 - agent2.getSourceServer().queryMBeans(ObjectName.WILDCARD,null))) {
552.342 - throw new RuntimeException("Bad Wombat census in " +
552.343 - "Australia // North");
552.344 - }
552.345 - if (!seWombats2.equals(
552.346 - agent1.queryMBeans(ObjectName.WILDCARD,null))) {
552.347 - throw new RuntimeException("Bad Wombat census in " +
552.348 - "Australia // South East");
552.349 - }
552.350 - final WombatMBean grand3 =
552.351 - JMX.newMBeanProxy(supermaster,
552.352 - addDir("australia//south.east",
552.353 - getWombatName("GrandWombat")),WombatMBean.class);
552.354 - final WombatMBean big3 =
552.355 - JMX.newMBeanProxy(supermaster,addDir("australia//north",
552.356 - getWombatName("BigWombat")),WombatMBean.class);
552.357 - if (!"I am GrandWombat".equals(grand3.getCaption()))
552.358 - throw new RuntimeException("bad caption for " +
552.359 - "australia//south.east//GrandWombat"+
552.360 - grand3.getCaption());
552.361 - if (!"I am BigWombat".equals(big3.getCaption()))
552.362 - throw new RuntimeException("bad caption for " +
552.363 - "australia//north//BigWombat"+
552.364 - big3.getCaption());
552.365 - final WombatMBean grand4 =
552.366 - JMX.newMBeanProxy(sem,
552.367 - getWombatName("GrandWombat"),WombatMBean.class);
552.368 - final WombatMBean big4 =
552.369 - JMX.newMBeanProxy(nthm,
552.370 - getWombatName("BigWombat"),WombatMBean.class);
552.371 - if (!"I am GrandWombat".equals(grand4.getCaption()))
552.372 - throw new RuntimeException("bad caption for " +
552.373 - "[australia//south.east//] GrandWombat"+
552.374 - grand4.getCaption());
552.375 - if (!"I am BigWombat".equals(big4.getCaption()))
552.376 - throw new RuntimeException("bad caption for " +
552.377 - "[australia//north//] BigWombat"+
552.378 - big4.getCaption());
552.379 -
552.380 - if (!(nthm instanceof RoutingServerProxy))
552.381 - throw new AssertionError("expected RoutingServerProxy for nthm");
552.382 - if (!(sem instanceof RoutingServerProxy))
552.383 - throw new AssertionError("expected RoutingServerProxy for sem");
552.384 -
552.385 - if (!"australia//north".equals((
552.386 - (RoutingServerProxy)nthm).getSourceNamespace()))
552.387 - throw new RuntimeException("north territory should be in australia");
552.388 - if (!"australia//south.east".equals((
552.389 - (RoutingServerProxy)sem).getSourceNamespace()))
552.390 - throw new RuntimeException("south east territory should be in australia");
552.391 -
552.392 - }
552.393 -
552.394 - public static void main(String[] args) {
552.395 - try {
552.396 - simpleTest();
552.397 - } catch (Exception x) {
552.398 - System.err.println("SimpleTest failed: "+x);
552.399 - throw new RuntimeException(x);
552.400 - }
552.401 - }
552.402 -
552.403 -}
553.1 --- a/test/javax/management/namespace/SerialParamProcessorTest.java Mon Nov 23 10:04:47 2009 +0000
553.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
553.3 @@ -1,572 +0,0 @@
553.4 -/*
553.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
553.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
553.7 - *
553.8 - * This code is free software; you can redistribute it and/or modify it
553.9 - * under the terms of the GNU General Public License version 2 only, as
553.10 - * published by the Free Software Foundation.
553.11 - *
553.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
553.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
553.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
553.15 - * version 2 for more details (a copy is included in the LICENSE file that
553.16 - * accompanied this code).
553.17 - *
553.18 - * You should have received a copy of the GNU General Public License version
553.19 - * 2 along with this work; if not, write to the Free Software Foundation,
553.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
553.21 - *
553.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
553.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
553.24 - * have any questions.
553.25 - */
553.26 -
553.27 -/*
553.28 - *
553.29 - * @test SerialParamProcessorTest.java 1.8
553.30 - * @summary General SerialParamProcessorTest test.
553.31 - * @author Daniel Fuchs
553.32 - * @bug 5072476
553.33 - * @run clean SerialParamProcessorTest Wombat WombatMBean
553.34 - * @compile -XDignore.symbol.file=true SerialParamProcessorTest.java
553.35 - * @run build SerialParamProcessorTest Wombat WombatMBean
553.36 - * @run main SerialParamProcessorTest
553.37 - */
553.38 -
553.39 -import com.sun.jmx.namespace.serial.RewritingProcessor;
553.40 -import java.beans.ConstructorProperties;
553.41 -import java.io.Serializable;
553.42 -import java.util.ArrayList;
553.43 -import java.util.Arrays;
553.44 -import java.util.HashMap;
553.45 -import java.util.LinkedList;
553.46 -import java.util.List;
553.47 -import java.util.Map;
553.48 -import javax.management.AttributeChangeNotification;
553.49 -import javax.management.AttributeList;
553.50 -import javax.management.JMException;
553.51 -import javax.management.Notification;
553.52 -import javax.management.ObjectName;
553.53 -import javax.management.StandardMBean;
553.54 -
553.55 -/**
553.56 - * Class SerialParamProcessorTest
553.57 - *
553.58 - * @author Sun Microsystems, Inc.
553.59 - */
553.60 -public class SerialParamProcessorTest {
553.61 -
553.62 - /**
553.63 - * Creates a new instance of SerialParamProcessorTest
553.64 - */
553.65 - public SerialParamProcessorTest() {
553.66 - }
553.67 -
553.68 - public static class MyCompositeData implements Serializable {
553.69 - private static final long serialVersionUID = 3186492415099133506L;
553.70 - public MyCompositeData(ObjectName foobar,ObjectName absolute,
553.71 - long count, String name) {
553.72 - this(foobar,absolute,count,name,new ObjectName[]{foobar,absolute});
553.73 - }
553.74 - @ConstructorProperties(value={"fooBar","absolute","count","name",
553.75 - "allNames"})
553.76 - public MyCompositeData(ObjectName foobar,ObjectName absolute,
553.77 - long count, String name, ObjectName[] allnames) {
553.78 - this.foobar = foobar;
553.79 - this.absolute = absolute;
553.80 - this.count = count;
553.81 - this.name = name;
553.82 - this.allnames = allnames;
553.83 - }
553.84 - ObjectName foobar,absolute,allnames[];
553.85 - long count;
553.86 - String name;
553.87 - public ObjectName getFooBar() {
553.88 - return foobar;
553.89 - }
553.90 - public ObjectName getAbsolute() {
553.91 - return absolute;
553.92 - }
553.93 - public ObjectName[] getAllNames() {
553.94 - return allnames;
553.95 - }
553.96 - public long getCount() {
553.97 - return count;
553.98 - }
553.99 - public String getName() {
553.100 - return name;
553.101 - }
553.102 - private Object[] toArray() {
553.103 - final Object[] props = {
553.104 - getName(),getFooBar(),getAbsolute(),getAllNames(),getCount()
553.105 - };
553.106 - return props;
553.107 - }
553.108 - @Override
553.109 - public boolean equals(Object o) {
553.110 - if (o instanceof MyCompositeData)
553.111 - return Arrays.deepEquals(toArray(),
553.112 - ((MyCompositeData)o).toArray());
553.113 - return false;
553.114 - }
553.115 - @Override
553.116 - public int hashCode() {
553.117 - return Arrays.deepHashCode(toArray());
553.118 - }
553.119 - }
553.120 -
553.121 - public static interface MyMXBean {
553.122 - public Map<String,MyCompositeData> getAll();
553.123 - public MyCompositeData lookup(String name);
553.124 - public void put(String name, MyCompositeData data);
553.125 - public MyCompositeData remove(String name);
553.126 - }
553.127 -
553.128 - public static class My implements MyMXBean {
553.129 - Map<String,MyCompositeData> datas =
553.130 - new HashMap<String,MyCompositeData>();
553.131 - public Map<String,MyCompositeData> getAll() {
553.132 - return datas;
553.133 - }
553.134 - public MyCompositeData lookup(String name) {
553.135 - return datas.get(name);
553.136 - }
553.137 - public void put(String name, MyCompositeData data) {
553.138 - datas.put(name,data);
553.139 - }
553.140 - public MyCompositeData remove(String name) {
553.141 - return datas.remove(name);
553.142 - }
553.143 - }
553.144 -
553.145 - public static class BandicootClass implements Serializable {
553.146 - private static final long serialVersionUID = -5494055748633966355L;
553.147 - public final Object gloups;
553.148 - public BandicootClass(Object gloups) {
553.149 - this.gloups = gloups;
553.150 - }
553.151 - private Object[] toArray() {
553.152 - final Object[] one = {gloups};
553.153 - return one;
553.154 - }
553.155 - @Override
553.156 - public boolean equals(Object obj) {
553.157 - if (!(obj instanceof BandicootClass)) return false;
553.158 - final Object[] one = {gloups};
553.159 - return Arrays.deepEquals(toArray(),((BandicootClass)obj).toArray());
553.160 - }
553.161 - @Override
553.162 - public int hashCode() {
553.163 - if (gloups == null) return 0;
553.164 - return Arrays.deepHashCode(toArray());
553.165 - }
553.166 - }
553.167 -
553.168 - // Need this to override equals.
553.169 - public static class BandicootNotification extends Notification {
553.170 - private static final long serialVersionUID = 664758643764049001L;
553.171 - public BandicootNotification(String type, Object source, long seq) {
553.172 - super(type,source,seq,0L,"");
553.173 - }
553.174 - private Object[] toArray() {
553.175 - final Object[] vals = {getMessage(),getSequenceNumber(),
553.176 - getSource(),getTimeStamp(),getType(),getUserData()};
553.177 - return vals;
553.178 - }
553.179 - @Override
553.180 - public boolean equals(Object o) {
553.181 - if (!(o instanceof BandicootNotification)) return false;
553.182 - return Arrays.deepEquals(toArray(),
553.183 - ((BandicootNotification)o).toArray());
553.184 - }
553.185 - @Override
553.186 - public int hashCode() {
553.187 - return Arrays.deepHashCode(toArray());
553.188 - }
553.189 -
553.190 - }
553.191 -
553.192 - // Need this to override equals.
553.193 - public static class BandicootAttributeChangeNotification
553.194 - extends AttributeChangeNotification {
553.195 - private static final long serialVersionUID = -1392435607144396125L;
553.196 - public BandicootAttributeChangeNotification(Object source,
553.197 - long seq, long time, String msg, String name, String type,
553.198 - Object oldv, Object newv) {
553.199 - super(source,seq,time,msg,name,type,oldv,newv);
553.200 - }
553.201 - private Object[] toArray() {
553.202 - final Object[] vals = {getMessage(),getSequenceNumber(),
553.203 - getSource(),getTimeStamp(),getType(),getUserData(),
553.204 - getAttributeName(), getAttributeType(),getNewValue(),
553.205 - getOldValue()};
553.206 - return vals;
553.207 - }
553.208 - @Override
553.209 - public boolean equals(Object o) {
553.210 - if (!(o instanceof BandicootAttributeChangeNotification))
553.211 - return false;
553.212 - return Arrays.deepEquals(toArray(),
553.213 - ((BandicootAttributeChangeNotification)o).toArray());
553.214 - }
553.215 - @Override
553.216 - public int hashCode() {
553.217 - return Arrays.deepHashCode(toArray());
553.218 - }
553.219 - @Override
553.220 - public String toString() {
553.221 - final StringBuilder b = new StringBuilder();
553.222 - b.append(this.getClass().getName()).append(": ");
553.223 - b.append("[type=").append(getType()).append("]");
553.224 - b.append("[source=").append(getSource()).append("]");
553.225 - b.append("[message=").append(getMessage()).append("]");
553.226 - b.append("[sequence=").append(getSequenceNumber()).append("]");
553.227 -
553.228 - b.append("[attribute=").append(getAttributeName()).append("]");
553.229 - b.append("[class=").append(getAttributeType()).append("]");
553.230 - b.append("[oldvalue=").append(getOldValue()).append("]");
553.231 - b.append("[newvalue=").append(getNewValue()).append("]");
553.232 -
553.233 - b.append("[time=").append(getTimeStamp()).append("]");
553.234 - b.append("[data=").append(getUserData()).append("]");
553.235 - return b.toString();
553.236 - }
553.237 - }
553.238 -
553.239 - private static void addToList(Object[] foos, List<Object> foolist) {
553.240 - final ArrayList<Object> fal = new ArrayList<Object>(foos.length);
553.241 - for (Object f : foos) {
553.242 - if (f.getClass().isArray()) {
553.243 - foolist.add(new BandicootClass(f));
553.244 - fal.add(new BandicootClass(f));
553.245 - } else {
553.246 - foolist.add(f);
553.247 - fal.add(f);
553.248 - }
553.249 - }
553.250 - foolist.add(new BandicootClass(foos));
553.251 - foolist.add(fal);
553.252 - }
553.253 -
553.254 - public static void testSerial(String msg, Object foo, Object bar,
553.255 - RewritingProcessor procForFoo,
553.256 - RewritingProcessor procForBar, List<Object> foolist,
553.257 - List<Object> barlist, boolean recurse) {
553.258 - System.err.println(msg+" Testing serial - "+foo.getClass().getName());
553.259 - final Object bar1 = procForFoo.rewriteInput(foo);
553.260 - final Object foo1 = procForFoo.rewriteOutput(bar);
553.261 - final Object bar2 = procForFoo.rewriteInput(foo1);
553.262 - final Object foo2 = procForFoo.rewriteOutput(bar1);
553.263 -
553.264 - final Object bar3 = procForBar.rewriteOutput(foo);
553.265 - final Object foo3 = procForBar.rewriteInput(bar);
553.266 - final Object bar4 = procForBar.rewriteOutput(foo3);
553.267 - final Object foo4 = procForBar.rewriteInput(bar3);
553.268 -
553.269 - final Object bar5 = procForFoo.rewriteInput(foo3);
553.270 - final Object foo5 = procForFoo.rewriteOutput(bar3);
553.271 -
553.272 - final Object bar6 = procForBar.rewriteOutput(foo1);
553.273 - final Object foo6 = procForBar.rewriteInput(bar1);
553.274 -
553.275 - final Object[] foos = {foo, foo1, foo2, foo3, foo4, foo5, foo6};
553.276 - final Object[] bars = {bar, bar1, bar2, bar3, bar4, bar5, bar6};
553.277 -
553.278 - final Object[] foot = { foo };
553.279 - final Object[] bart = { bar };
553.280 - for (int j=1;j<foos.length;j++) {
553.281 - final Object[] foox = { foos[j] };
553.282 - final Object[] barx = { bars[j] };
553.283 - if (!Arrays.deepEquals(foot,foox)) {
553.284 - System.err.println(msg+" foo"+j+" "+foos[j]+" != "+foo);
553.285 - throw new RuntimeException(msg+" foo"+j+" != foo");
553.286 - }
553.287 - if (!Arrays.deepEquals(bart,barx)) {
553.288 - System.err.println(msg+" bar"+j+" "+bars[j]+" != "+bar);
553.289 - throw new RuntimeException(msg+" bar"+j+" != bar");
553.290 - }
553.291 -
553.292 - }
553.293 - if (recurse) {
553.294 - testSerial("Array: " + msg,foos,bars,procForFoo,
553.295 - procForBar,foolist,barlist,false);
553.296 - addToList(foos,foolist);
553.297 - addToList(bars,barlist);
553.298 - }
553.299 - }
553.300 - public static void testSerial(Object[][] objects,
553.301 - RewritingProcessor procForFoo,
553.302 - RewritingProcessor procForBar) {
553.303 - int i=0;
553.304 - final List<Object> foolist = new LinkedList<Object>();
553.305 - final List<Object> barlist = new LinkedList<Object>();
553.306 - for (Object[] row : objects) {
553.307 - i++;
553.308 - Object foo = row[0];
553.309 - Object bar = row[1];
553.310 - String msg1 = "[" +foo.getClass().getName() + "] step " +
553.311 - i +": ";
553.312 -
553.313 - testSerial(msg1,foo,bar,procForFoo,procForBar,foolist,barlist,true);
553.314 -
553.315 - final BandicootClass kfoo = new BandicootClass(foo);
553.316 - final BandicootClass kbar = new BandicootClass(bar);
553.317 -
553.318 - String msg2 = "[" +kfoo.getClass().getName() + "] step " +
553.319 - i +": ";
553.320 - testSerial(msg2,kfoo,kbar,procForFoo,procForBar,foolist,barlist,true);
553.321 - }
553.322 - String msg31 = "foo[] and bar[]: ";
553.323 - testSerial(msg31,foolist.toArray(),barlist.toArray(),
553.324 - procForFoo,procForBar,foolist,barlist,false);
553.325 -
553.326 - String msg3 = "foolist and barlist: ";
553.327 - testSerial(msg3,new LinkedList<Object>(foolist),
553.328 - new LinkedList<Object>(barlist),
553.329 - procForFoo,procForBar,foolist,barlist,false);
553.330 -
553.331 - final BandicootClass kfoolist = new BandicootClass(foolist);
553.332 - final BandicootClass kbarlist = new BandicootClass(barlist);
553.333 - String msg4 = "kfoolist and kbarlist: ";
553.334 - testSerial(msg4,kfoolist,kbarlist,procForFoo,procForBar,foolist,barlist,false);
553.335 - }
553.336 -
553.337 - /**
553.338 - * The idea of this method is to convert {@code foo} things into
553.339 - * {@code bar} things...
553.340 - * @param foo the string to replace.
553.341 - * @param bar the replacement for {@code foo}
553.342 - * ({@code foo} becomes {@code bar}).
553.343 - * @param sfoo a string that may contain {@code foo}, that will be embedded
553.344 - * in non-replaceable parts of the domain in order to attempt to
553.345 - * trick the replacement logic.
553.346 - * @param sbar a string that may contain {@code bar}, that will be embedded
553.347 - * in non-replaceable parts of the domain in order to attempt to
553.348 - * trick the replacement logic.
553.349 - **/
553.350 - public static void doSerialTest(String foo, String bar, String sfoo,
553.351 - String sbar) {
553.352 - try {
553.353 - final RewritingProcessor procForFoo = RewritingProcessor.
553.354 - newRewritingProcessor(foo,bar);
553.355 - final RewritingProcessor procForBar =RewritingProcessor.
553.356 - newRewritingProcessor(bar,foo);
553.357 - final String foop = (foo.isEmpty())?foo:foo+"//";
553.358 - final String pfoo = (foo.isEmpty())?foo:"//"+foo;
553.359 - final String barp = (bar.isEmpty())?bar:bar+"//";
553.360 - final String pbar = (bar.isEmpty())?bar:"//"+bar;
553.361 - final String sfoop = (sfoo.isEmpty())?sfoo:sfoo+"//";
553.362 - final String psfoo = (sfoo.isEmpty())?sfoo:"//"+sfoo;
553.363 - final String sbarp = (sbar.isEmpty())?sbar:sbar+"//";
553.364 - final String psbar = (sbar.isEmpty())?sbar:"//"+sbar;
553.365 -
553.366 - // A trick to avoid writing Open Data by hand...
553.367 - final My tricks = new My();
553.368 -
553.369 - // A treat to automagically convert trick things into Open Data.
553.370 - final StandardMBean treats =
553.371 - new StandardMBean(tricks,MyMXBean.class,true);
553.372 -
553.373 - // datas[i][0] is expected to be transformed in datas[i][1]
553.374 - //
553.375 - final MyCompositeData[][] datas = {
553.376 - { // this foo thing:
553.377 - new MyCompositeData(new ObjectName(foop+sbarp+"x:y=z"),
553.378 - new ObjectName("//"+foop+sbarp+"x:y=z"),1,sfoop+sbarp+"foobar"),
553.379 - // should be transformed into this bar thing:
553.380 - new MyCompositeData(new ObjectName(barp+sbarp+"x:y=z"),
553.381 - new ObjectName("//"+foop+sbarp+"x:y=z"),1,sfoop+sbarp+"foobar"),
553.382 - },
553.383 - { // this foo thing:
553.384 - new MyCompositeData(new ObjectName(foop+sfoop+"x:y=z"),
553.385 - new ObjectName("//"+foop+sfoop+"x:y=z"),1,sfoop+sbarp+"barfoo"),
553.386 - // should be transformed into this bar thing:
553.387 - new MyCompositeData(new ObjectName(barp+sfoop+"x:y=z"),
553.388 - new ObjectName("//"+foop+sfoop+"x:y=z"),1,sfoop+sbarp+"barfoo"),
553.389 - }
553.390 - };
553.391 -
553.392 - // objects[i][0] is expected to be transformed into objects[i][1]
553.393 - //
553.394 - final Object[][] objects = new Object[][] {
553.395 - {new Long(1), new Long(1)},
553.396 - {
553.397 - new ObjectName(foop+sbarp+"x:y=z"),
553.398 - new ObjectName(barp+sbarp+"x:y=z")
553.399 - },
553.400 - {
553.401 - new ObjectName(foop+sfoop+"x:y=z"),
553.402 - new ObjectName(barp+sfoop+"x:y=z")
553.403 - },
553.404 - {
553.405 - new ObjectName("//"+foop+sbarp+"x:y=z"),
553.406 - new ObjectName("//"+foop+sbarp+"x:y=z"),
553.407 - },
553.408 - {
553.409 - new ObjectName("//"+foop+sfoop+"x:y=z"),
553.410 - new ObjectName("//"+foop+sfoop+"x:y=z")
553.411 - },
553.412 - {
553.413 - foop+sbarp+"x:y=z",foop+sbarp+"x:y=z"
553.414 - },
553.415 - {
553.416 - foop+sfoop+"x:y=z",foop+sfoop+"x:y=z"
553.417 - },
553.418 - {
553.419 - barp+sbarp+"x:y=z",barp+sbarp+"x:y=z"
553.420 - },
553.421 - {
553.422 - barp+sfoop+"x:y=z",barp+sfoop+"x:y=z"
553.423 - },
553.424 - {
553.425 - new BandicootNotification("test",new ObjectName(foop+sfoop+"x:y=z"),1L),
553.426 - new BandicootNotification("test",new ObjectName(barp+sfoop+"x:y=z"),1L),
553.427 - },
553.428 - {
553.429 - new BandicootNotification("test",new ObjectName("//"+foop+sfoop+"x:y=z"),2L),
553.430 - new BandicootNotification("test",new ObjectName("//"+foop+sfoop+"x:y=z"),2L),
553.431 - },
553.432 - {
553.433 - new BandicootAttributeChangeNotification(
553.434 - new ObjectName(foop+sfoop+"x:y=z"),1L,2L,"blah","attrname",
553.435 - ObjectName.class.getName(),
553.436 - new ObjectName(foop+sfoop+"x:y=old"),
553.437 - new ObjectName(foop+sfoop+"x:y=new")),
553.438 - new BandicootAttributeChangeNotification(
553.439 - new ObjectName(barp+sfoop+"x:y=z"),1L,2L,"blah","attrname",
553.440 - ObjectName.class.getName(),
553.441 - new ObjectName(barp+sfoop+"x:y=old"),
553.442 - new ObjectName(barp+sfoop+"x:y=new")),
553.443 - },
553.444 - {
553.445 - new BandicootAttributeChangeNotification(
553.446 - new ObjectName("//"+foop+sfoop+"x:y=z"),1L,2L,"blah","attrname",
553.447 - ObjectName.class.getName(),
553.448 - new ObjectName("//"+foop+sfoop+"x:y=old"),
553.449 - new ObjectName(foop+sfoop+"x:y=new")),
553.450 - new BandicootAttributeChangeNotification(
553.451 - new ObjectName("//"+foop+sfoop+"x:y=z"),1L,2L,"blah","attrname",
553.452 - ObjectName.class.getName(),
553.453 - new ObjectName("//"+foop+sfoop+"x:y=old"),
553.454 - new ObjectName(barp+sfoop+"x:y=new")),
553.455 - }
553.456 - };
553.457 -
553.458 - // List that will merge datas & objects & datas converted to open
553.459 - // types...
553.460 - //
553.461 - final List<Object[]> list = new ArrayList<Object[]>();
553.462 -
553.463 - // Add all objects...
553.464 - //
553.465 - list.addAll(Arrays.asList(objects));
553.466 -
553.467 - // Build Map<String,MyCompositeData> with datas[i][0] (cfoo)
553.468 - //
553.469 - for (int i=0;i<datas.length;i++) {
553.470 - tricks.put(sfoop+sbarp+"x"+i,datas[i][0]);
553.471 - }
553.472 -
553.473 - // Let MXBean convert Map<String,MyCompositeData> to TabularData
553.474 - // (foo things)
553.475 - final Object cfoo = treats.getAttribute("All");
553.476 - final AttributeList afoo = treats.getAttributes(new String[] {"All"});
553.477 -
553.478 - // Build Map<String,MyCompositeData> with datas[i][1] (cbar)
553.479 - //
553.480 - for (int i=0;i<datas.length;i++) {
553.481 - tricks.remove(sfoop+sbarp+"x"+i);
553.482 - tricks.put(sfoop+sbarp+"x"+i,datas[i][1]);
553.483 - }
553.484 -
553.485 - // Let MXBean convert Map<String,MyCompositeData> to TabularData
553.486 - // (bar things)
553.487 - final Object cbar = treats.getAttribute("All");
553.488 - final AttributeList abar = treats.getAttributes(new String[] {"All"});
553.489 -
553.490 - // Add all datas to list
553.491 - for (int i=0;i<datas.length;i++) {
553.492 - list.add(datas[i]);
553.493 - }
553.494 -
553.495 - // Add converted TabularDatas to list
553.496 - list.add(new Object[] {cfoo,cbar});
553.497 -
553.498 - // Add AttributeList containing TabularData to list
553.499 - list.add(new Object[] {afoo,abar});
553.500 -
553.501 - // Add Arrays of the above to list...
553.502 - list.add(new Object[] {new Object[] {cfoo,afoo,1L},
553.503 - new Object[] {cbar,abar,1L}});
553.504 -
553.505 - // Add MBeanInfo...
553.506 - list.add(new Object[] {treats.getMBeanInfo(),treats.getMBeanInfo()});
553.507 -
553.508 - // No ready to test conversion of all foo things into bar things.
553.509 - //
553.510 - testSerial(list.toArray(new Object[list.size()][]),
553.511 - procForFoo,procForBar);
553.512 - } catch (JMException x) {
553.513 - throw new RuntimeException(x);
553.514 - }
553.515 - }
553.516 -
553.517 - public static void aaaTest() {
553.518 - System.err.println("\n--------------------- aaaTest ----------------");
553.519 - System.err.println("---------------- 'foo' becomes 'bar' ---------\n");
553.520 - doSerialTest("foo","bar","foo","bar");
553.521 - }
553.522 -
553.523 - public static void aabTest() {
553.524 - System.err.println("\n--------------------- aabTest ----------------");
553.525 - System.err.println("---------- 'foo//bar' becomes 'bar//foo' -----\n");
553.526 - doSerialTest("foo//bar","bar//foo","foo","bar");
553.527 - }
553.528 -
553.529 - public static void aacTest() {
553.530 - System.err.println("\n----------------- aacTest --------------------");
553.531 - System.err.println("------------ 'foo//bar' becomes '' -----------\n");
553.532 - doSerialTest("foo//bar","","foo","bar");
553.533 - }
553.534 -
553.535 - public static void aadTest() {
553.536 - System.err.println("\n----------------- aadTest --------------------");
553.537 - System.err.println("----------- '' becomes 'bar//foo' ------------\n");
553.538 - doSerialTest("","bar//foo","","bar//foo");
553.539 - }
553.540 -
553.541 - public static void aaeTest() {
553.542 - System.err.println("\n----------------- aaeTest --------------------");
553.543 - System.err.println("----------------- '' becomes '' --------------\n");
553.544 - doSerialTest("","","foo","bar//foo");
553.545 - }
553.546 -
553.547 - // Let's be wild...
553.548 - public static void aafTest() {
553.549 - System.err.println("\n----------------- aafTest --------------------");
553.550 - System.err.println("----------- '' becomes '' -- (bis) -----------\n");
553.551 - doSerialTest("","","","");
553.552 - }
553.553 - public static void aagTest() {
553.554 - System.err.println("\n----------------- aagTest --------------------");
553.555 - System.err.println("----------- foobar becomes foobar ------------\n");
553.556 - doSerialTest("foobar","foobar","foobar","foobar");
553.557 - }
553.558 -
553.559 - // TODO add test with descriptor, MBeanInfo, Open Types, etc...
553.560 - public static void main(String[] args) {
553.561 - aaaTest();
553.562 - aabTest();
553.563 - aacTest();
553.564 - aadTest();
553.565 - aaeTest();
553.566 - aafTest();
553.567 - aagTest();
553.568 -
553.569 - // TODO: add a test case to test *exactly* the serialization
553.570 - // of Notification and AttributeChangeNotification, and not of
553.571 - // a subclass of these.
553.572 - // This will involve implementing some hack, because we
553.573 - // can't use equals() to compare the results.
553.574 - }
553.575 -}
554.1 --- a/test/javax/management/namespace/SourceNamespaceTest.java Mon Nov 23 10:04:47 2009 +0000
554.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
554.3 @@ -1,141 +0,0 @@
554.4 -/*
554.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
554.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
554.7 - *
554.8 - * This code is free software; you can redistribute it and/or modify it
554.9 - * under the terms of the GNU General Public License version 2 only, as
554.10 - * published by the Free Software Foundation.
554.11 - *
554.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
554.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
554.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
554.15 - * version 2 for more details (a copy is included in the LICENSE file that
554.16 - * accompanied this code).
554.17 - *
554.18 - * You should have received a copy of the GNU General Public License version
554.19 - * 2 along with this work; if not, write to the Free Software Foundation,
554.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
554.21 - *
554.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
554.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
554.24 - * have any questions.
554.25 - */
554.26 -/*
554.27 - *
554.28 - * @test SourceNamespaceTest.java
554.29 - * @summary Test how queryNames works with Namespaces.
554.30 - * @bug 5072476
554.31 - * @author Daniel Fuchs
554.32 - * @run clean SourceNamespaceTest Wombat WombatMBean
554.33 - * @run build SourceNamespaceTest Wombat WombatMBean
554.34 - * @run main SourceNamespaceTest
554.35 - */
554.36 -
554.37 -
554.38 -import javax.management.JMException;
554.39 -import javax.management.JMX;
554.40 -import javax.management.MBeanServer;
554.41 -import javax.management.MBeanServerFactory;
554.42 -import javax.management.ObjectName;
554.43 -import javax.management.namespace.JMXNamespace;
554.44 -import javax.management.namespace.JMXNamespaces;
554.45 -
554.46 -/**
554.47 - * A simple test to test the source directory parameter...
554.48 - * @author dfuchs
554.49 - */
554.50 -public class SourceNamespaceTest {
554.51 -
554.52 -
554.53 - public static void localTest() throws JMException {
554.54 - final JMXNamespace adir =
554.55 - new JMXNamespace(MBeanServerFactory.newMBeanServer());
554.56 -
554.57 - // put a wombat in adir...
554.58 - final Wombat w1 = new Wombat();
554.59 - final ObjectName wn1 = new ObjectName("wilderness:type=Wombat,name=gloups");
554.60 - adir.getSourceServer().registerMBean(w1,wn1);
554.61 -
554.62 - // register adir
554.63 - final MBeanServer server = MBeanServerFactory.newMBeanServer();
554.64 - server.registerMBean(adir, JMXNamespaces.getNamespaceObjectName("adir"));
554.65 -
554.66 - if (! (server.isRegistered(JMXNamespaces.insertPath("adir", wn1))))
554.67 - throw new RuntimeException("Test failed: " +
554.68 - JMXNamespaces.insertPath("adir", wn1) + " not found");
554.69 -
554.70 - System.out.println("Wombat gloups correctly registered...");
554.71 -
554.72 - // put another wombat in adir...
554.73 - final Wombat w2 = new Wombat();
554.74 - final ObjectName wn2 =
554.75 - new ObjectName("wilderness:type=Wombat,name=pasgloups");
554.76 - server.registerMBean(w2,JMXNamespaces.insertPath("adir", wn2));
554.77 -
554.78 - if (! (server.isRegistered(JMXNamespaces.insertPath("adir", wn2))))
554.79 - throw new RuntimeException("Test failed: " +
554.80 - JMXNamespaces.insertPath("adir", wn2) + " not found");
554.81 -
554.82 - System.out.println("Wombat pasgloups correctly registered...");
554.83 -
554.84 -
554.85 - // make an alias
554.86 - final JMXNamespace alias = new JMXNamespace(
554.87 - JMXNamespaces.narrowToNamespace(server,"adir"));
554.88 - server.registerMBean(alias,
554.89 - JMXNamespaces.getNamespaceObjectName("alias"));
554.90 -
554.91 - if (! (server.isRegistered(JMXNamespaces.insertPath("alias", wn1))))
554.92 - throw new RuntimeException("Test failed: " +
554.93 - JMXNamespaces.insertPath("alias", wn1) + " not found");
554.94 -
554.95 - System.out.println("Wombat gloups accessible through alias...");
554.96 -
554.97 - if (! (server.isRegistered(JMXNamespaces.insertPath("alias", wn2))))
554.98 - throw new RuntimeException("Test failed: " +
554.99 - JMXNamespaces.insertPath("alias", wn2) + " not found");
554.100 -
554.101 - System.out.println("Wombat pasgloups accessible through alias...");
554.102 -
554.103 - final WombatMBean wp2 = JMX.newMBeanProxy(server,
554.104 - JMXNamespaces.insertPath("alias",wn2), WombatMBean.class);
554.105 - System.out.println(JMXNamespaces.insertPath("alias",wn2).toString()
554.106 - +" says: "+wp2.getCaption());
554.107 -
554.108 - // We're going to make another alias, but register it in a different
554.109 - // MBeanServer. This is to make sure that source server and target
554.110 - // server are not mixed up.
554.111 - //
554.112 - final MBeanServer server2 = MBeanServerFactory.newMBeanServer();
554.113 - final JMXNamespace alias2 = new JMXNamespace(
554.114 - JMXNamespaces.narrowToNamespace(server,"adir"));
554.115 - server2.registerMBean(alias2,
554.116 - JMXNamespaces.getNamespaceObjectName("alias2"));
554.117 -
554.118 -
554.119 - if (! (server2.isRegistered(JMXNamespaces.insertPath("alias2", wn1))))
554.120 - throw new RuntimeException("Test failed: " +
554.121 - JMXNamespaces.insertPath("alias2", wn1) + " not found");
554.122 -
554.123 - System.out.println("Wombat gloups accessible through alias2...");
554.124 -
554.125 - if (! (server2.isRegistered(JMXNamespaces.insertPath("alias2", wn2))))
554.126 - throw new RuntimeException("Test failed: " +
554.127 - JMXNamespaces.insertPath("alias2", wn2) + " not found");
554.128 -
554.129 - System.out.println("Wombat pasgloups accessible through alias...");
554.130 -
554.131 - final WombatMBean wp22 = JMX.newMBeanProxy(server2,
554.132 - JMXNamespaces.insertPath("alias2",wn2), WombatMBean.class);
554.133 - System.out.println(JMXNamespaces.insertPath("alias2",wn2).toString()
554.134 - +" says: "+wp22.getCaption());
554.135 -
554.136 -
554.137 -
554.138 - }
554.139 -
554.140 - public static void main(String[] args) throws Exception {
554.141 - localTest();
554.142 - }
554.143 -
554.144 -}
555.1 --- a/test/javax/management/namespace/VirtualMBeanNotifTest.java Mon Nov 23 10:04:47 2009 +0000
555.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
555.3 @@ -1,569 +0,0 @@
555.4 -/*
555.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
555.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
555.7 - *
555.8 - * This code is free software; you can redistribute it and/or modify it
555.9 - * under the terms of the GNU General Public License version 2 only, as
555.10 - * published by the Free Software Foundation.
555.11 - *
555.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
555.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
555.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
555.15 - * version 2 for more details (a copy is included in the LICENSE file that
555.16 - * accompanied this code).
555.17 - *
555.18 - * You should have received a copy of the GNU General Public License version
555.19 - * 2 along with this work; if not, write to the Free Software Foundation,
555.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
555.21 - *
555.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
555.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
555.24 - * have any questions.
555.25 - */
555.26 -
555.27 -/*
555.28 - * @test VirtualMBeanNotifTest.java
555.29 - * @bug 5108776
555.30 - * @build VirtualMBeanNotifTest Wombat WombatMBean
555.31 - * @run main VirtualMBeanNotifTest
555.32 - * @summary Test that Virtual MBeans can be implemented and emit notifs.
555.33 - * @author Daniel Fuchs
555.34 - */
555.35 -import java.lang.management.ManagementFactory;
555.36 -import java.lang.reflect.InvocationHandler;
555.37 -import java.lang.reflect.InvocationTargetException;
555.38 -import java.lang.reflect.Method;
555.39 -import java.lang.reflect.Proxy;
555.40 -import java.util.ArrayList;
555.41 -import java.util.Arrays;
555.42 -import java.util.HashMap;
555.43 -import java.util.HashSet;
555.44 -import java.util.List;
555.45 -import java.util.Map;
555.46 -import java.util.Set;
555.47 -import java.util.concurrent.ArrayBlockingQueue;
555.48 -import java.util.concurrent.BlockingQueue;
555.49 -import java.util.concurrent.CopyOnWriteArrayList;
555.50 -import java.util.concurrent.TimeUnit;
555.51 -import javax.management.Attribute;
555.52 -import javax.management.DynamicMBean;
555.53 -import javax.management.InstanceNotFoundException;
555.54 -import javax.management.JMException;
555.55 -import javax.management.MBeanAttributeInfo;
555.56 -import javax.management.MBeanInfo;
555.57 -import javax.management.MBeanNotificationInfo;
555.58 -import javax.management.MBeanServer;
555.59 -import javax.management.Notification;
555.60 -import javax.management.NotificationBroadcaster;
555.61 -import javax.management.NotificationEmitter;
555.62 -import javax.management.NotificationListener;
555.63 -import javax.management.ObjectName;
555.64 -import javax.management.RuntimeOperationsException;
555.65 -import javax.management.StandardMBean;
555.66 -import javax.management.event.EventSubscriber;
555.67 -import javax.management.namespace.VirtualEventManager;
555.68 -import javax.management.namespace.MBeanServerSupport;
555.69 -
555.70 -public class VirtualMBeanNotifTest {
555.71 -
555.72 - /**
555.73 - * An invocation handler that can implement DynamicMBean,
555.74 - * NotificationBroadcaster, NotificationEmitter.
555.75 - * The invocation handler works by forwarding all calls received from
555.76 - * the implemented interfaces through a wrapped MBeanServer object.
555.77 - */
555.78 - public static class DynamicWrapper
555.79 - implements InvocationHandler {
555.80 -
555.81 - /**
555.82 - * Inserts an additional class at the head of a signature array.
555.83 - * @param first The first class in the signature
555.84 - * @param rest The other classes in the signature
555.85 - * @return A signature array, of length rest.length+1.
555.86 - */
555.87 - static Class[] concat(Class first, Class... rest) {
555.88 - if (rest == null || rest.length == 0) {
555.89 - return new Class[] { first };
555.90 - }
555.91 - final Class[] sig = new Class[rest.length+1];
555.92 - sig[0] = first;
555.93 - System.arraycopy(rest, 0, sig, 1, rest.length);
555.94 - return sig;
555.95 - }
555.96 -
555.97 - /**
555.98 - * Inserts an additional object at the head of a parameters array.
555.99 - * @param first The first object in the parameter array.
555.100 - * @param rest The other objects in the parameter array.
555.101 - * @return A parameter array, of length rest.length+1.
555.102 - */
555.103 - static Object[] concat(Object first, Object... rest) {
555.104 - if (rest == null || rest.length == 0) {
555.105 - return new Object[] { first };
555.106 - }
555.107 - final Object[] params = new Object[rest.length+1];
555.108 - params[0] = first;
555.109 - System.arraycopy(rest, 0, params, 1, rest.length);
555.110 - return params;
555.111 - }
555.112 -
555.113 - /**
555.114 - * These two sets are used to check that all methods from
555.115 - * implemented interfaces are mapped.
555.116 - * unmapped is the set of methods that couldn't be mapped.
555.117 - * mapped is the set of methods that could be mapped.
555.118 - */
555.119 - final static Set<Method> unmapped = new HashSet<Method>();
555.120 - final static Set<Method> mapped = new HashSet<Method>();
555.121 -
555.122 - /**
555.123 - * For each method define in one of the interfaces intf, tries
555.124 - * to find a corresponding method in the reference class ref, where
555.125 - * the method in ref has the same name, and takes an additional
555.126 - * ObjectName as first parameter.
555.127 - *
555.128 - * So for instance, if ref is MBeanServer and intf is {DynamicMBean}
555.129 - * the result map is:
555.130 - * DynamicMBean.getAttribute -> MBeanServer.getAttribute
555.131 - * DynamicMBean.setAttribute -> MBeanServer.setAttribute
555.132 - * etc...
555.133 - * If a method was mapped, it is additionally added to 'mapped'
555.134 - * If a method couldn't be mapped, it is added to 'unmmapped'.
555.135 - * In our example above, DynamicMBean.getNotificationInfo will end
555.136 - * up in 'unmapped'.
555.137 - *
555.138 - * @param ref The reference class - to which calls will be forwarded
555.139 - * with an additional ObjectName parameter inserted.
555.140 - * @param intf The proxy interface classes - for which we must find an
555.141 - * equivalent in 'ref'
555.142 - * @return A map mapping the methods from intfs to the method of ref.
555.143 - */
555.144 - static Map<Method,Method> makeMapFor(Class<?> ref, Class<?>... intf) {
555.145 - final Map<Method,Method> map = new HashMap<Method,Method>();
555.146 - for (Class<?> clazz : intf) {
555.147 - for (Method m : clazz.getMethods()) {
555.148 - try {
555.149 - final Method m2 =
555.150 - ref.getMethod(m.getName(),
555.151 - concat(ObjectName.class,m.getParameterTypes()));
555.152 - map.put(m,m2);
555.153 - mapped.add(m);
555.154 - } catch (Exception x) {
555.155 - unmapped.add(m);
555.156 - }
555.157 - }
555.158 - }
555.159 - return map;
555.160 - }
555.161 -
555.162 - /**
555.163 - * Tries to map all methods from DynamicMBean.class and
555.164 - * NotificationEmitter.class to their equivalent in MBeanServer.
555.165 - * This should be all the methods except
555.166 - * DynamicMBean.getNotificationInfo.
555.167 - */
555.168 - static final Map<Method,Method> mbeanmap =
555.169 - makeMapFor(MBeanServer.class,DynamicMBean.class,
555.170 - NotificationEmitter.class);
555.171 - /**
555.172 - * Tries to map all methods from DynamicMBean.class and
555.173 - * NotificationEmitter.class to an equivalent in DynamicWrapper.
555.174 - * This time only DynamicMBean.getNotificationInfo will be mapped.
555.175 - */
555.176 - static final Map<Method,Method> selfmap =
555.177 - makeMapFor(DynamicWrapper.class,DynamicMBean.class,
555.178 - NotificationEmitter.class);
555.179 -
555.180 - /**
555.181 - * Now check that we have mapped all methods.
555.182 - */
555.183 - static {
555.184 - unmapped.removeAll(mapped);
555.185 - if (unmapped.size() > 0)
555.186 - throw new ExceptionInInitializerError("Couldn't map "+ unmapped);
555.187 - }
555.188 -
555.189 - /**
555.190 - * The wrapped MBeanServer to which everything is delegated.
555.191 - */
555.192 - private final MBeanServer server;
555.193 -
555.194 - /**
555.195 - * The name of the MBean we're proxying.
555.196 - */
555.197 - private final ObjectName name;
555.198 - DynamicWrapper(MBeanServer server, ObjectName name) {
555.199 - this.server=server;
555.200 - this.name=name;
555.201 - }
555.202 -
555.203 - /**
555.204 - * Creates a new proxy for the given MBean. Implements
555.205 - * NotificationEmitter/NotificationBroadcaster if the proxied
555.206 - * MBean also does.
555.207 - * @param name the name of the proxied MBean
555.208 - * @param server the wrapped server
555.209 - * @return a DynamicMBean proxy
555.210 - * @throws javax.management.InstanceNotFoundException
555.211 - */
555.212 - public static DynamicMBean newProxy(ObjectName name, MBeanServer server)
555.213 - throws InstanceNotFoundException {
555.214 - if (server.isInstanceOf(name,
555.215 - NotificationEmitter.class.getName())) {
555.216 - // implements NotificationEmitter
555.217 - return (DynamicMBean)
555.218 - Proxy.newProxyInstance(
555.219 - DynamicWrapper.class.getClassLoader(),
555.220 - new Class[] {NotificationEmitter.class,
555.221 - DynamicMBean.class},
555.222 - new DynamicWrapper(server, name));
555.223 - }
555.224 - if (server.isInstanceOf(name,
555.225 - NotificationBroadcaster.class.getName())) {
555.226 - // implements NotificationBroadcaster
555.227 - return (DynamicMBean)
555.228 - Proxy.newProxyInstance(
555.229 - DynamicWrapper.class.getClassLoader(),
555.230 - new Class[] {NotificationBroadcaster.class,
555.231 - DynamicMBean.class},
555.232 - new DynamicWrapper(server, name));
555.233 - }
555.234 - // Only implements DynamicMBean.
555.235 - return (DynamicMBean)
555.236 - Proxy.newProxyInstance(
555.237 - DynamicWrapper.class.getClassLoader(),
555.238 - new Class[] {DynamicMBean.class},
555.239 - new DynamicWrapper(server, name));
555.240 - }
555.241 -
555.242 - public Object invoke(Object proxy, Method method, Object[] args)
555.243 - throws Throwable {
555.244 - // Look for a method on this class (takes precedence)
555.245 - final Method self = selfmap.get(method);
555.246 - if (self != null)
555.247 - return call(this,self,concat(name,args));
555.248 -
555.249 - // no method found on this class, look for the same method
555.250 - // on the wrapped MBeanServer
555.251 - final Method mbean = mbeanmap.get(method);
555.252 - if (mbean != null)
555.253 - return call(server,mbean,concat(name,args));
555.254 -
555.255 - // This isn't a method that can be forwarded to MBeanServer.
555.256 - // If it's a method from Object, call it on this.
555.257 - if (method.getDeclaringClass().equals(Object.class))
555.258 - return call(this,method,args);
555.259 - throw new NoSuchMethodException(method.getName());
555.260 - }
555.261 -
555.262 - // Call a method using reflection, unwraps invocation target exceptions
555.263 - public Object call(Object handle, Method m, Object[] args)
555.264 - throws Throwable {
555.265 - try {
555.266 - return m.invoke(handle, args);
555.267 - } catch (InvocationTargetException x) {
555.268 - throw x.getCause();
555.269 - }
555.270 - }
555.271 -
555.272 - // this method is called when DynamicMBean.getNotificationInfo() is
555.273 - // called. This is the method that should be mapped in
555.274 - // 'selfmap'
555.275 - public MBeanNotificationInfo[] getNotificationInfo(ObjectName name)
555.276 - throws JMException {
555.277 - return server.getMBeanInfo(name).getNotifications();
555.278 - }
555.279 - }
555.280 -
555.281 - /**
555.282 - * Just so that we can call the same test twice but with two
555.283 - * different implementations of VirtualMBeanServerSupport.
555.284 - */
555.285 - public static interface MBeanServerWrapperFactory {
555.286 - public MBeanServer wrapMBeanServer(MBeanServer wrapped);
555.287 - }
555.288 -
555.289 - /**
555.290 - * A VirtualMBeanServerSupport that wrapps an MBeanServer and does not
555.291 - * use VirtualEventManager.
555.292 - */
555.293 - public static class VirtualMBeanServerTest
555.294 - extends MBeanServerSupport {
555.295 -
555.296 - final MBeanServer wrapped;
555.297 -
555.298 - public VirtualMBeanServerTest(MBeanServer wrapped) {
555.299 - this.wrapped=wrapped;
555.300 - }
555.301 -
555.302 - @Override
555.303 - public DynamicMBean getDynamicMBeanFor(final ObjectName name)
555.304 - throws InstanceNotFoundException {
555.305 - if (wrapped.isRegistered(name))
555.306 - return DynamicWrapper.newProxy(name,wrapped);
555.307 - throw new InstanceNotFoundException(String.valueOf(name));
555.308 - }
555.309 -
555.310 - @Override
555.311 - protected Set<ObjectName> getNames() {
555.312 - return wrapped.queryNames(null, null);
555.313 - }
555.314 -
555.315 - public final static MBeanServerWrapperFactory factory =
555.316 - new MBeanServerWrapperFactory() {
555.317 -
555.318 - public MBeanServer wrapMBeanServer(MBeanServer wrapped) {
555.319 - return new VirtualMBeanServerTest(wrapped);
555.320 - }
555.321 - @Override
555.322 - public String toString() {
555.323 - return VirtualMBeanServerTest.class.getName();
555.324 - }
555.325 - };
555.326 - }
555.327 -
555.328 - /**
555.329 - * A VirtualMBeanServerSupport that wrapps an MBeanServer and
555.330 - * uses a VirtualEventManager.
555.331 - */
555.332 - public static class VirtualMBeanServerTest2
555.333 - extends VirtualMBeanServerTest {
555.334 -
555.335 - final EventSubscriber sub;
555.336 - final NotificationListener nl;
555.337 - final VirtualEventManager mgr;
555.338 -
555.339 - /**
555.340 - * We use an EventSubscriber to subscribe for all notifications from
555.341 - * the wrapped MBeanServer, and publish them through a
555.342 - * VirtualEventManager. Not a very efficient way of doing things.
555.343 - * @param wrapped
555.344 - */
555.345 - public VirtualMBeanServerTest2(MBeanServer wrapped) {
555.346 - super(wrapped);
555.347 - this.sub = EventSubscriber.getEventSubscriber(wrapped);
555.348 - this.mgr = new VirtualEventManager();
555.349 - this.nl = new NotificationListener() {
555.350 - public void handleNotification(Notification notification, Object handback) {
555.351 - mgr.publish((ObjectName)notification.getSource(), notification);
555.352 - }
555.353 - };
555.354 - try {
555.355 - sub.subscribe(ObjectName.WILDCARD, nl, null, null);
555.356 - } catch (RuntimeException x) {
555.357 - throw x;
555.358 - } catch (Exception x) {
555.359 - throw new IllegalStateException("can't subscribe for notifications!");
555.360 - }
555.361 - }
555.362 -
555.363 - @Override
555.364 - public NotificationEmitter
555.365 - getNotificationEmitterFor(ObjectName name)
555.366 - throws InstanceNotFoundException {
555.367 - final DynamicMBean mbean = getDynamicMBeanFor(name);
555.368 - if (mbean instanceof NotificationEmitter)
555.369 - return mgr.getNotificationEmitterFor(name);
555.370 - return null;
555.371 - }
555.372 -
555.373 - public final static MBeanServerWrapperFactory factory =
555.374 - new MBeanServerWrapperFactory() {
555.375 -
555.376 - public MBeanServer wrapMBeanServer(MBeanServer wrapped) {
555.377 - return new VirtualMBeanServerTest2(wrapped);
555.378 - }
555.379 - @Override
555.380 - public String toString() {
555.381 - return VirtualMBeanServerTest2.class.getName();
555.382 - }
555.383 - };
555.384 - }
555.385 -
555.386 -
555.387 - public static void test(MBeanServerWrapperFactory factory) throws Exception {
555.388 - final MBeanServer server = ManagementFactory.getPlatformMBeanServer();
555.389 -
555.390 - // names[] are NotificationEmitters
555.391 - final ObjectName[] emitters = new ObjectName[2];
555.392 - // shields[] have been shielded by wrapping them in a StandardMBean,
555.393 - // so although the resource is an MBean that implements
555.394 - // NotificationEmitter, the registered MBean (the wrapper) doesn't.
555.395 - final ObjectName[] shielded = new ObjectName[2];
555.396 -
555.397 - final List<ObjectName> registered = new ArrayList<ObjectName>(4);
555.398 -
555.399 - try {
555.400 - // register two MBeans before wrapping
555.401 - server.registerMBean(new Wombat(),
555.402 - emitters[0] = new ObjectName("bush:type=Wombat,name=wom"));
555.403 - registered.add(emitters[0]);
555.404 -
555.405 - // we shield the second MBean in a StandardMBean so that it does
555.406 - // not appear as a NotificationEmitter.
555.407 - server.registerMBean(
555.408 - new StandardMBean(new Wombat(), WombatMBean.class),
555.409 - shielded[0] = new ObjectName("bush:type=Wombat,name=womshield"));
555.410 - registered.add(shielded[0]);
555.411 -
555.412 - final MBeanServer vserver = factory.wrapMBeanServer(server);
555.413 -
555.414 - // register two other MBeans after wrapping
555.415 - server.registerMBean(new Wombat(),
555.416 - emitters[1] = new ObjectName("bush:type=Wombat,name=bat"));
555.417 - registered.add(emitters[1]);
555.418 -
555.419 - // we shield the second MBean in a StandardMBean so that it does
555.420 - // not appear as a NotificationEmitter.
555.421 - server.registerMBean(
555.422 - new StandardMBean(new Wombat(), WombatMBean.class),
555.423 - shielded[1] = new ObjectName("bush:type=Wombat,name=batshield"));
555.424 - registered.add(shielded[1]);
555.425 -
555.426 - // Call test with this config - we have two wombats who broadcast
555.427 - // notifs (emitters) and two wombats who don't (shielded).
555.428 - test(vserver, emitters, shielded);
555.429 -
555.430 - System.out.println("*** Test passed for: " + factory);
555.431 - } finally {
555.432 - // Clean up the platform mbean server for the next test...
555.433 - for (ObjectName n : registered) {
555.434 - try {
555.435 - server.unregisterMBean(n);
555.436 - } catch (Exception x) {
555.437 - x.printStackTrace();
555.438 - }
555.439 - }
555.440 - }
555.441 - }
555.442 -
555.443 - /**
555.444 - * Perform the actual test.
555.445 - * @param vserver A virtual MBeanServerSupport implementation
555.446 - * @param emitters Names of NotificationBroadcaster MBeans
555.447 - * @param shielded Names of non NotificationBroadcaster MBeans
555.448 - * @throws java.lang.Exception
555.449 - */
555.450 - public static void test(MBeanServer vserver, ObjectName[] emitters,
555.451 - ObjectName[] shielded) throws Exception {
555.452 -
555.453 - // To catch exception in NotificationListener
555.454 - final List<Exception> fail = new CopyOnWriteArrayList<Exception>();
555.455 -
555.456 - // A queue of received notifications
555.457 - final BlockingQueue<Notification> notifs =
555.458 - new ArrayBlockingQueue<Notification>(50);
555.459 -
555.460 - // A notification listener that puts the notification it receives
555.461 - // in the queue.
555.462 - final NotificationListener handler = new NotificationListener() {
555.463 -
555.464 - public void handleNotification(Notification notification,
555.465 - Object handback) {
555.466 - try {
555.467 - notifs.put(notification);
555.468 - } catch (Exception x) {
555.469 - fail.add(x);
555.470 - }
555.471 - }
555.472 - };
555.473 -
555.474 - // A list of attribute names for which we might receive an
555.475 - // exception. If an exception is received when getting these
555.476 - // attributes - the test will not fail.
555.477 - final List<String> exceptions = Arrays.asList( new String[] {
555.478 - "UsageThresholdCount","UsageThreshold","UsageThresholdExceeded",
555.479 - "CollectionUsageThresholdCount","CollectionUsageThreshold",
555.480 - "CollectionUsageThresholdExceeded"
555.481 - });
555.482 -
555.483 - // This is just a sanity check. Get all attributes of all MBeans.
555.484 - for (ObjectName n : vserver.queryNames(null, null)) {
555.485 - final MBeanInfo m = vserver.getMBeanInfo(n);
555.486 - for (MBeanAttributeInfo mba : m.getAttributes()) {
555.487 - // System.out.println(n+":");
555.488 - Object val;
555.489 - try {
555.490 - val = vserver.getAttribute(n, mba.getName());
555.491 - } catch (Exception x) {
555.492 - // only accept exception for those attributes that
555.493 - // have a valid reason to fail...
555.494 - if (exceptions.contains(mba.getName())) val = x;
555.495 - else throw new Exception("Failed to get " +
555.496 - mba.getName() + " from " + n,x);
555.497 - }
555.498 - // System.out.println("\t "+mba.getName()+": "+ val);
555.499 - }
555.500 - }
555.501 -
555.502 - // The actual tests. Register for notifications with notif emitters
555.503 - for (ObjectName n : emitters) {
555.504 - vserver.addNotificationListener(n, handler, null, n);
555.505 - }
555.506 -
555.507 - // Trigger the emission of notifications, check that we received them.
555.508 - for (ObjectName n : emitters) {
555.509 - vserver.setAttribute(n,
555.510 - new Attribute("Caption","I am a new wombat!"));
555.511 - final Notification notif = notifs.poll(4, TimeUnit.SECONDS);
555.512 - if (!notif.getSource().equals(n))
555.513 - throw new Exception("Bad source for "+ notif);
555.514 - if (fail.size() > 0)
555.515 - throw new Exception("Failed to handle notif",fail.remove(0));
555.516 - }
555.517 -
555.518 - // Check that we didn't get more notifs than expected
555.519 - if (notifs.size() > 0)
555.520 - throw new Exception("Extra notifications in queue: "+notifs);
555.521 -
555.522 - // Check that if the MBean doesn't exist, we get InstanceNotFound.
555.523 - try {
555.524 - vserver.addNotificationListener(new ObjectName("toto:toto=toto"),
555.525 - handler, null, null);
555.526 - throw new Exception("toto:toto=toto doesn't throw INFE");
555.527 - } catch (InstanceNotFoundException x) {
555.528 - System.out.println("Received "+x+" as expected.");
555.529 - }
555.530 -
555.531 - // For those MBeans that shouldn't be NotificationEmitters, check that
555.532 - // we get IllegalArgumentException
555.533 - for (ObjectName n : shielded) {
555.534 - try {
555.535 - vserver.addNotificationListener(n, handler, null, n);
555.536 - } catch (RuntimeOperationsException x) {
555.537 - System.out.println("Received "+x+" as expected.");
555.538 - System.out.println("Cause is: "+x.getCause());
555.539 - if (!(x.getCause() instanceof IllegalArgumentException))
555.540 - throw new Exception("was expecting IllegalArgumentException cause. Got "+x.getCause(),x);
555.541 - }
555.542 - }
555.543 -
555.544 - // Sanity check. Remove our listeners.
555.545 - for (ObjectName n : emitters) {
555.546 - vserver.removeNotificationListener(n, handler, null, n);
555.547 - }
555.548 -
555.549 - // That's it.
555.550 - // Sanity check: we shouldn't have received any new notif.
555.551 - if (notifs.size() > 0)
555.552 - throw new Exception("Extra notifications in queue: "+notifs);
555.553 - // The NotifListener shouldn't have logged any new exception.
555.554 - if (fail.size() > 0)
555.555 - throw new Exception("Failed to handle notif",fail.remove(0));
555.556 - }
555.557 -
555.558 - public static void main(String[] args) throws Exception {
555.559 - // test with a regular MBeanServer (no VirtualMBeanServerSupport)
555.560 - final MBeanServerWrapperFactory identity =
555.561 - new MBeanServerWrapperFactory() {
555.562 - public MBeanServer wrapMBeanServer(MBeanServer wrapped) {
555.563 - return wrapped;
555.564 - }
555.565 - };
555.566 - test(identity);
555.567 - // test with no EventManager
555.568 - test(VirtualMBeanServerTest.factory);
555.569 - // test with VirtualEventManager
555.570 - test(VirtualMBeanServerTest2.factory);
555.571 - }
555.572 -}
556.1 --- a/test/javax/management/namespace/VirtualMBeanTest.java Mon Nov 23 10:04:47 2009 +0000
556.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
556.3 @@ -1,409 +0,0 @@
556.4 -/*
556.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
556.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
556.7 - *
556.8 - * This code is free software; you can redistribute it and/or modify it
556.9 - * under the terms of the GNU General Public License version 2 only, as
556.10 - * published by the Free Software Foundation.
556.11 - *
556.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
556.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
556.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
556.15 - * version 2 for more details (a copy is included in the LICENSE file that
556.16 - * accompanied this code).
556.17 - *
556.18 - * You should have received a copy of the GNU General Public License version
556.19 - * 2 along with this work; if not, write to the Free Software Foundation,
556.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
556.21 - *
556.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
556.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
556.24 - * have any questions.
556.25 - */
556.26 -
556.27 -/*
556.28 - * @test VirtualMBeanTest.java
556.29 - * @bug 5108776 5072476
556.30 - * @summary Test that Virtual MBeans can be implemented and emit notifs.
556.31 - * @author Eamonn McManus
556.32 - */
556.33 -
556.34 -import java.io.PrintWriter;
556.35 -import java.io.StringWriter;
556.36 -import java.util.Arrays;
556.37 -import java.util.Collections;
556.38 -import java.util.List;
556.39 -import java.util.Map;
556.40 -import java.util.Set;
556.41 -import java.util.TreeMap;
556.42 -import java.util.TreeSet;
556.43 -import java.util.concurrent.ArrayBlockingQueue;
556.44 -import java.util.concurrent.BlockingQueue;
556.45 -import java.util.concurrent.TimeUnit;
556.46 -import javax.management.DynamicMBean;
556.47 -import javax.management.InstanceNotFoundException;
556.48 -import javax.management.MBeanInfo;
556.49 -import javax.management.MBeanServer;
556.50 -import javax.management.MBeanServerFactory;
556.51 -import javax.management.MalformedObjectNameException;
556.52 -import javax.management.Notification;
556.53 -import javax.management.NotificationBroadcaster;
556.54 -import javax.management.NotificationBroadcasterSupport;
556.55 -import javax.management.NotificationEmitter;
556.56 -import javax.management.NotificationListener;
556.57 -import javax.management.ObjectName;
556.58 -import javax.management.RuntimeOperationsException;
556.59 -import javax.management.SendNotification;
556.60 -import javax.management.StandardEmitterMBean;
556.61 -import javax.management.StandardMBean;
556.62 -import javax.management.namespace.JMXNamespace;
556.63 -import javax.management.namespace.JMXNamespaces;
556.64 -import javax.management.namespace.VirtualEventManager;
556.65 -import javax.management.namespace.MBeanServerSupport;
556.66 -import javax.management.timer.TimerMBean;
556.67 -
556.68 -// In this test, we check that the two main use case types for
556.69 -// MBeanServerSupport work correctly:
556.70 -// (1) as a special-purpose implementation of MBeanServer for a fixed number
556.71 -// of MBeans (e.g. for QueryNotificationFilter)
556.72 -// (2) as an MBeanServer supporting Virtual MBeans.
556.73 -// In each case we are particularly interested in the notification behaviour.
556.74 -// We check that the behaviour is correct when calling addNotificationListener
556.75 -// (a) for an MBean that does not exist; (b) for an MBean that does exist but
556.76 -// is not a NotificationEmitter; and (c) for an MBean that exists and is
556.77 -// a NotificationEmitter. We also check the degenerate and usual case
556.78 -// where the MBeanServerSupport subclass does not support notifications
556.79 -// at all.
556.80 -//
556.81 -// Each subclass will have an MBean called test:type=NotEmitter that
556.82 -// does not support addNotificationListener. If it also has MBeans called
556.83 -// test:type=Emitter,* then they are expected to support addNL. No subclass
556.84 -// will have any other MBeans, so in particular no subclass will have
556.85 -// test:type=Nonexistent.
556.86 -//
556.87 -public class VirtualMBeanTest {
556.88 - static final ObjectName
556.89 - nonExistentName, notEmitterName, emitterName1, emitterName2;
556.90 - static {
556.91 - try {
556.92 - nonExistentName = new ObjectName("test:type=NonExistent");
556.93 - notEmitterName = new ObjectName("test:type=NotEmitter");
556.94 - emitterName1 = new ObjectName("test:type=Emitter,id=1");
556.95 - emitterName2 = new ObjectName("test:type=Emitter,id=2");
556.96 - } catch (MalformedObjectNameException e) {
556.97 - throw new AssertionError(e);
556.98 - }
556.99 - }
556.100 -
556.101 - static final StandardMBean.Options wrappedVisible = new StandardMBean.Options();
556.102 - static {
556.103 - wrappedVisible.setWrappedObjectVisible(true);
556.104 - }
556.105 -
556.106 - public static interface NothingMBean {}
556.107 - public static class Nothing implements NothingMBean {}
556.108 - public static class NothingNBS extends NotificationBroadcasterSupport
556.109 - implements NothingMBean {}
556.110 -
556.111 - // Class that has hardwired MBeans test:type=NotEmitter,
556.112 - // test:type=Broadcaster, and test:type=Emitter.
556.113 - private static class HardwiredMBS extends MBeanServerSupport
556.114 - implements SendNotification {
556.115 - private final DynamicMBean notEmitter =
556.116 - new StandardMBean(new Nothing(), NothingMBean.class, wrappedVisible);
556.117 - private final StandardEmitterMBean emitter1, emitter2;
556.118 - {
556.119 - NothingNBS nnbs1 = new NothingNBS();
556.120 - emitter1 = new StandardEmitterMBean(
556.121 - nnbs1, NothingMBean.class, wrappedVisible, nnbs1);
556.122 - NothingNBS nnbs2 = new NothingNBS();
556.123 - emitter2 = new StandardEmitterMBean(
556.124 - nnbs2, NothingMBean.class, wrappedVisible, nnbs2);
556.125 - }
556.126 -
556.127 - private final Map<ObjectName, DynamicMBean> map =
556.128 - new TreeMap<ObjectName, DynamicMBean>();
556.129 - {
556.130 - map.put(notEmitterName, notEmitter);
556.131 - map.put(emitterName1, emitter1);
556.132 - map.put(emitterName2, emitter2);
556.133 - }
556.134 -
556.135 -
556.136 - @Override
556.137 - public DynamicMBean getDynamicMBeanFor(ObjectName name)
556.138 - throws InstanceNotFoundException {
556.139 - DynamicMBean mbean = map.get(name);
556.140 - if (mbean != null)
556.141 - return mbean;
556.142 - else
556.143 - throw new InstanceNotFoundException(name);
556.144 - }
556.145 -
556.146 - @Override
556.147 - protected Set<ObjectName> getNames() {
556.148 - return map.keySet();
556.149 - }
556.150 -
556.151 - @Override
556.152 - public String toString() {
556.153 - return "Hardwired MBeanServerSupport";
556.154 - }
556.155 -
556.156 - public void sendNotification(Notification notification) {
556.157 - emitter1.sendNotification(notification);
556.158 - emitter2.sendNotification(notification);
556.159 - }
556.160 - }
556.161 -
556.162 - // Class that has the notEmitter MBean but not either of the others, so does
556.163 - // not support listeners.
556.164 - private static class VirtualMBSWithoutListeners
556.165 - extends MBeanServerSupport {
556.166 - @Override
556.167 - public DynamicMBean getDynamicMBeanFor(ObjectName name)
556.168 - throws InstanceNotFoundException {
556.169 - if (name.equals(notEmitterName)) {
556.170 - return new StandardMBean(
556.171 - new Nothing(), NothingMBean.class, wrappedVisible);
556.172 - } else
556.173 - throw new InstanceNotFoundException(name);
556.174 - }
556.175 -
556.176 - @Override
556.177 - protected Set<ObjectName> getNames() {
556.178 - return Collections.singleton(notEmitterName);
556.179 - }
556.180 -
556.181 - @Override
556.182 - public String toString() {
556.183 - return "Virtual MBeanServerSupport without listener support";
556.184 - }
556.185 - }
556.186 -
556.187 - // Class that has the notEmitter and emitter MBeans as Virtual MBeans, using
556.188 - // VirtualEventManager to handle listeners for the emitter MBean. We
556.189 - // implement the broadcaster MBean (which is a NotificationBroadcaster but
556.190 - // not a NotificationEmitter) even though it's very hard to imagine a real
556.191 - // use case where that would happen.
556.192 - private static class VirtualMBSWithListeners
556.193 - extends MBeanServerSupport implements SendNotification {
556.194 - private final VirtualEventManager vem = new VirtualEventManager();
556.195 -
556.196 - private static final List<ObjectName> names =
556.197 - Arrays.asList(notEmitterName, emitterName1, emitterName2);
556.198 -
556.199 - @Override
556.200 - public DynamicMBean getDynamicMBeanFor(ObjectName name)
556.201 - throws InstanceNotFoundException {
556.202 - if (names.contains(name)) {
556.203 - return new StandardMBean(
556.204 - new Nothing(), NothingMBean.class, wrappedVisible);
556.205 - } else
556.206 - throw new InstanceNotFoundException(name);
556.207 - }
556.208 -
556.209 - @Override
556.210 - public NotificationEmitter getNotificationEmitterFor(
556.211 - ObjectName name) throws InstanceNotFoundException {
556.212 - if (name.equals(emitterName1) || name.equals(emitterName2))
556.213 - return vem.getNotificationEmitterFor(name);
556.214 - else if (name.equals(notEmitterName))
556.215 - return null;
556.216 - else
556.217 - throw new InstanceNotFoundException(name);
556.218 - }
556.219 -
556.220 - @Override
556.221 - protected Set<ObjectName> getNames() {
556.222 - return new TreeSet<ObjectName>(Arrays.asList(notEmitterName, emitterName2));
556.223 - }
556.224 -
556.225 - @Override
556.226 - public String toString() {
556.227 - return "Virtual MBeanServerSupport with listener support";
556.228 - }
556.229 -
556.230 - public void sendNotification(Notification notification) {
556.231 - vem.publish(emitterName1, notification);
556.232 - vem.publish(emitterName2, notification);
556.233 - }
556.234 - }
556.235 -
556.236 - private static final MBeanServer[] vmbsss = {
556.237 - new HardwiredMBS(),
556.238 - new VirtualMBSWithoutListeners(),
556.239 - new VirtualMBSWithListeners(),
556.240 - };
556.241 -
556.242 - public static void main(String[] args) throws Exception {
556.243 - Exception lastEx = null;
556.244 - for (MBeanServer vmbs : vmbsss) {
556.245 - String testName = "\"" + vmbs + "\"";
556.246 - System.out.println("===Test " + testName + "===");
556.247 - try {
556.248 - test(vmbs);
556.249 - } catch (Exception e) {
556.250 - System.out.println(
556.251 - "===Test " + testName + " failed with exception " + e);
556.252 - StringWriter sw = new StringWriter();
556.253 - PrintWriter pw = new PrintWriter(sw);
556.254 - e.printStackTrace(pw);
556.255 - pw.flush();
556.256 - String es = sw.toString();
556.257 - System.out.println("......" + es.replace("\n", "\n......"));
556.258 - lastEx = e;
556.259 - }
556.260 - }
556.261 - if (lastEx != null)
556.262 - throw lastEx;
556.263 - System.out.println("TEST PASSED");
556.264 - }
556.265 -
556.266 - private static class NothingListener implements NotificationListener {
556.267 - public void handleNotification(Notification notification,
556.268 - Object handback) {
556.269 - throw new UnsupportedOperationException("Not supported yet.");
556.270 - }
556.271 - }
556.272 -
556.273 - private static class QueueListener implements NotificationListener {
556.274 - final BlockingQueue<Notification> queue =
556.275 - new ArrayBlockingQueue<Notification>(10);
556.276 -
556.277 - public void handleNotification(Notification notification,
556.278 - Object handback) {
556.279 - queue.add(notification);
556.280 - }
556.281 - }
556.282 -
556.283 - private static void test(MBeanServer vmbs) throws Exception {
556.284 - MBeanServer mmbs = MBeanServerFactory.newMBeanServer();
556.285 - ObjectName namespaceName = new ObjectName("test//:type=JMXNamespace");
556.286 - JMXNamespace namespace = new JMXNamespace(vmbs);
556.287 - mmbs.registerMBean(namespace, namespaceName);
556.288 - MBeanServer mbs = JMXNamespaces.narrowToNamespace(mmbs, "test");
556.289 -
556.290 - Set<ObjectName> names = mbs.queryNames(null, null);
556.291 - //names.remove(new ObjectName(":type=JMXNamespace"));
556.292 -
556.293 - // Make sure that notEmitterName exists according to query...
556.294 - System.out.println("Checking query");
556.295 - if (!names.contains(notEmitterName))
556.296 - throw new Exception("Bad query result: " + names);
556.297 -
556.298 - // ...and according to getMBeanInfo
556.299 - System.out.println("Checking getMBeanInfo(" + notEmitterName + ")");
556.300 - MBeanInfo mbi = mbs.getMBeanInfo(notEmitterName);
556.301 - if (mbi.getNotifications().length > 0)
556.302 - throw new Exception("notEmitter has NotificationInfo");
556.303 -
556.304 - // Make sure we get the right exception for getMBeanInfo on a
556.305 - // non-existent MBean
556.306 - System.out.println("Checking getMBeanInfo on a non-existent MBean");
556.307 - try {
556.308 - mbi = mbs.getMBeanInfo(nonExistentName);
556.309 - throw new Exception("getMBI succeeded but should not have");
556.310 - } catch (InstanceNotFoundException e) {
556.311 - }
556.312 -
556.313 - // Make sure we get the right exception for addNotificationListener on a
556.314 - // non-existent MBean
556.315 - System.out.println(
556.316 - "Checking addNotificationListener on a non-existent MBean");
556.317 - try {
556.318 - mbs.addNotificationListener(
556.319 - nonExistentName, new NothingListener(), null, null);
556.320 - throw new Exception("addNL succeeded but should not have");
556.321 - } catch (InstanceNotFoundException e) {
556.322 - }
556.323 -
556.324 - // Make sure we get the right exception for isInstanceOf on a
556.325 - // non-existent MBean
556.326 - System.out.println(
556.327 - "Checking isInstanceOf on a non-existent MBean");
556.328 - for (Class<?> c : new Class<?>[] {
556.329 - Object.class, NotificationBroadcaster.class, NotificationEmitter.class,
556.330 - }) {
556.331 - try {
556.332 - boolean is = mbs.isInstanceOf(nonExistentName, c.getName());
556.333 - throw new Exception(
556.334 - "isInstanceOf " + c.getName() +
556.335 - " succeeded but should not have");
556.336 - } catch (InstanceNotFoundException e) {
556.337 - }
556.338 - }
556.339 -
556.340 - // Make sure isInstanceOf works correctly for classes without special
556.341 - // treatment
556.342 - System.out.println(
556.343 - "Checking isInstanceOf on normal classes");
556.344 - for (ObjectName name : names) {
556.345 - boolean isNothing = mbs.isInstanceOf(name, NothingMBean.class.getName());
556.346 - if (!isNothing) {
556.347 - throw new Exception("isInstanceOf " + NothingMBean.class.getName() +
556.348 - " returned false, should be true");
556.349 - }
556.350 - boolean isTimer = mbs.isInstanceOf(name, TimerMBean.class.getName());
556.351 - if (isTimer) {
556.352 - throw new Exception("isInstanceOf " + TimerMBean.class.getName() +
556.353 - " returned true, should be false");
556.354 - }
556.355 - }
556.356 -
556.357 - // Make sure that addNL on notEmitterName gets the right exception
556.358 - System.out.println("Checking addNL on non-broadcaster");
556.359 - try {
556.360 - mbs.addNotificationListener(
556.361 - notEmitterName, new NothingListener(), null, null);
556.362 - throw new Exception("addNL succeeded but should not have");
556.363 - } catch (RuntimeOperationsException e) {
556.364 - if (!(e.getCause() instanceof IllegalArgumentException))
556.365 - throw new Exception("Wrong exception from addNL", e);
556.366 - }
556.367 -
556.368 - if (!(vmbs instanceof SendNotification)) {
556.369 - System.out.println("Not testing notifications for this implementation");
556.370 - return;
556.371 - }
556.372 -
556.373 - QueueListener qListener = new QueueListener();
556.374 -
556.375 - System.out.println("Testing addNL on emitters");
556.376 - mbs.addNotificationListener(emitterName1, qListener, null, null);
556.377 - mbs.addNotificationListener(emitterName2, qListener, null, null);
556.378 -
556.379 - System.out.println("Testing that listeners work");
556.380 - Notification notif = new Notification("notif.type", "source", 0L);
556.381 -
556.382 - ((SendNotification) vmbs).sendNotification(notif);
556.383 - testListeners(qListener, "notif.type", 2);
556.384 -
556.385 - System.out.println("Testing 2-arg removeNL on emitter1");
556.386 - mbs.removeNotificationListener(emitterName1, qListener);
556.387 -
556.388 - ((SendNotification) vmbs).sendNotification(notif);
556.389 - testListeners(qListener, "notif.type", 1);
556.390 -
556.391 - System.out.println("Testing 4-arg removeNL on emitter2");
556.392 - mbs.removeNotificationListener(emitterName2, qListener, null, null);
556.393 -
556.394 - ((SendNotification) vmbs).sendNotification(notif);
556.395 - testListeners(qListener, "notif.type", 0);
556.396 - }
556.397 -
556.398 - private static void testListeners(
556.399 - QueueListener qListener, String expectedNotifType, int expectedNotifs)
556.400 - throws Exception {
556.401 - for (int i = 1; i <= expectedNotifs; i++) {
556.402 - Notification rNotif = qListener.queue.poll(1, TimeUnit.SECONDS);
556.403 - if (rNotif == null)
556.404 - throw new Exception("Notification " + i + " never arrived");
556.405 - if (!rNotif.getType().equals(expectedNotifType))
556.406 - throw new Exception("Wrong type notif: " + rNotif.getType());
556.407 - }
556.408 - Notification xNotif = qListener.queue.poll(10, TimeUnit.MILLISECONDS);
556.409 - if (xNotif != null)
556.410 - throw new Exception("Extra notif: " + xNotif);
556.411 - }
556.412 -}
557.1 --- a/test/javax/management/namespace/VirtualNamespaceQueryTest.java Mon Nov 23 10:04:47 2009 +0000
557.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
557.3 @@ -1,128 +0,0 @@
557.4 -/*
557.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
557.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
557.7 - *
557.8 - * This code is free software; you can redistribute it and/or modify it
557.9 - * under the terms of the GNU General Public License version 2 only, as
557.10 - * published by the Free Software Foundation.
557.11 - *
557.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
557.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
557.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
557.15 - * version 2 for more details (a copy is included in the LICENSE file that
557.16 - * accompanied this code).
557.17 - *
557.18 - * You should have received a copy of the GNU General Public License version
557.19 - * 2 along with this work; if not, write to the Free Software Foundation,
557.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
557.21 - *
557.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
557.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
557.24 - * have any questions.
557.25 - */
557.26 -
557.27 -/*
557.28 - *
557.29 - * @test VirtualNamespaceQueryTest.java
557.30 - * @summary General VirtualNamespaceQueryTest test.
557.31 - * @author Daniel Fuchs
557.32 - * @bug 5072476
557.33 - * @run clean VirtualNamespaceQueryTest Wombat WombatMBean
557.34 - * NamespaceController NamespaceControllerMBean
557.35 - * JMXRemoteTargetNamespace
557.36 - * @compile -XDignore.symbol.file=true VirtualNamespaceQueryTest.java
557.37 - * Wombat.java WombatMBean.java
557.38 - * NamespaceController.java NamespaceControllerMBean.java
557.39 - * JMXRemoteTargetNamespace.java
557.40 - * @run main VirtualNamespaceQueryTest
557.41 - */
557.42 -
557.43 -import java.util.Arrays;
557.44 -import java.util.Collections;
557.45 -import java.util.Set;
557.46 -import javax.management.DynamicMBean;
557.47 -import javax.management.InstanceNotFoundException;
557.48 -import javax.management.JMX;
557.49 -import javax.management.MBeanServer;
557.50 -import javax.management.MBeanServerFactory;
557.51 -import javax.management.NotificationEmitter;
557.52 -import javax.management.ObjectInstance;
557.53 -import javax.management.ObjectName;
557.54 -import javax.management.StandardMBean;
557.55 -import javax.management.namespace.JMXNamespace;
557.56 -import javax.management.namespace.JMXNamespaces;
557.57 -import javax.management.namespace.MBeanServerSupport;
557.58 -
557.59 -/**
557.60 - *
557.61 - * @author dfuchs
557.62 - */
557.63 -public class VirtualNamespaceQueryTest {
557.64 - public static class WombatRepository extends MBeanServerSupport {
557.65 - final Wombat wombat;
557.66 - final StandardMBean mbean;
557.67 - final ObjectName wombatName;
557.68 -
557.69 - public WombatRepository(ObjectName wombatName) {
557.70 - try {
557.71 - wombat = new Wombat();
557.72 - mbean = wombat;
557.73 - this.wombatName = wombatName;
557.74 - wombat.preRegister(null,wombatName);
557.75 - } catch (Exception x) {
557.76 - throw new IllegalArgumentException(x);
557.77 - }
557.78 - }
557.79 -
557.80 - @Override
557.81 - public DynamicMBean getDynamicMBeanFor(ObjectName name)
557.82 - throws InstanceNotFoundException {
557.83 - if (wombatName.equals(name)) return mbean;
557.84 - else throw new InstanceNotFoundException(String.valueOf(name));
557.85 - }
557.86 -
557.87 - @Override
557.88 - protected Set<ObjectName> getNames() {
557.89 - final Set<ObjectName> res = Collections.singleton(wombatName);
557.90 - return res;
557.91 - }
557.92 -
557.93 - @Override
557.94 - public NotificationEmitter getNotificationEmitterFor(
557.95 - ObjectName name) throws InstanceNotFoundException {
557.96 - DynamicMBean mb = getDynamicMBeanFor(name);
557.97 - if (mb instanceof NotificationEmitter)
557.98 - return (NotificationEmitter)mb;
557.99 - return null;
557.100 - }
557.101 - }
557.102 - public static class WombatNamespace extends JMXNamespace {
557.103 - public WombatNamespace(ObjectName wombatName) {
557.104 - super(new WombatRepository(wombatName));
557.105 - }
557.106 - }
557.107 -
557.108 - public static void simpleTest() throws Exception {
557.109 - final MBeanServer server = MBeanServerFactory.newMBeanServer();
557.110 - final ObjectName wombatName = new ObjectName("burrow:type=Wombat");
557.111 - final JMXNamespace ns = new WombatNamespace(wombatName);
557.112 - server.registerMBean(ns, JMXNamespaces.getNamespaceObjectName("wombats"));
557.113 - final Set<ObjectName> dirs =
557.114 - server.queryNames(new ObjectName("wombats//*//:type=JMXNamespace"),
557.115 - wombatName);
557.116 - System.out.println("all dirs: "+dirs);
557.117 - if (dirs.size()>0)
557.118 - throw new RuntimeException("Unexpected ObjectNames returned: "+dirs);
557.119 -
557.120 - final ObjectInstance inst = NamespaceController.createInstance(server);
557.121 - final NamespaceControllerMBean controller =
557.122 - JMX.newMBeanProxy(server, inst.getObjectName(),
557.123 - NamespaceControllerMBean.class);
557.124 - final String[] dirNames = controller.findNamespaces(null,null,2);
557.125 - System.err.println(Arrays.toString(dirNames));
557.126 - }
557.127 -
557.128 - public static void main(String[] args) throws Exception {
557.129 - simpleTest();
557.130 - }
557.131 -}
558.1 --- a/test/javax/management/namespace/VirtualPropsTest.java Mon Nov 23 10:04:47 2009 +0000
558.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
558.3 @@ -1,179 +0,0 @@
558.4 -/*
558.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
558.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
558.7 - *
558.8 - * This code is free software; you can redistribute it and/or modify it
558.9 - * under the terms of the GNU General Public License version 2 only, as
558.10 - * published by the Free Software Foundation.
558.11 - *
558.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
558.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
558.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
558.15 - * version 2 for more details (a copy is included in the LICENSE file that
558.16 - * accompanied this code).
558.17 - *
558.18 - * You should have received a copy of the GNU General Public License version
558.19 - * 2 along with this work; if not, write to the Free Software Foundation,
558.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
558.21 - *
558.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
558.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
558.24 - * have any questions.
558.25 - */
558.26 -
558.27 -/*
558.28 - * @test
558.29 - * @bug 5108776 5072476
558.30 - * @summary Test the properties use case for Virtual MBeans that is documented
558.31 - * in MBeanServerSupport.
558.32 - * @author Eamonn McManus
558.33 - */
558.34 -
558.35 -import java.lang.management.ManagementFactory;
558.36 -import java.util.Properties;
558.37 -import java.util.Set;
558.38 -import java.util.TreeSet;
558.39 -import java.util.concurrent.ArrayBlockingQueue;
558.40 -import java.util.concurrent.BlockingQueue;
558.41 -import java.util.concurrent.TimeUnit;
558.42 -import javax.management.DynamicMBean;
558.43 -import javax.management.InstanceNotFoundException;
558.44 -import javax.management.JMX;
558.45 -import javax.management.MBeanServer;
558.46 -import javax.management.MalformedObjectNameException;
558.47 -import javax.management.Notification;
558.48 -import javax.management.NotificationEmitter;
558.49 -import javax.management.NotificationListener;
558.50 -import javax.management.ObjectName;
558.51 -import javax.management.StandardMBean;
558.52 -import javax.management.namespace.JMXNamespace;
558.53 -import javax.management.namespace.JMXNamespaces;
558.54 -import javax.management.namespace.VirtualEventManager;
558.55 -import javax.management.namespace.MBeanServerSupport;
558.56 -
558.57 -public class VirtualPropsTest {
558.58 - public static interface PropertyMBean {
558.59 - public String getValue();
558.60 - }
558.61 -
558.62 - public static class PropsMBS extends MBeanServerSupport {
558.63 - private static ObjectName newObjectName(String name) {
558.64 - try {
558.65 - return new ObjectName(name);
558.66 - } catch (MalformedObjectNameException e) {
558.67 - throw new AssertionError(e);
558.68 - }
558.69 - }
558.70 -
558.71 - public static class PropertyImpl implements PropertyMBean {
558.72 - private final String name;
558.73 -
558.74 - public PropertyImpl(String name) {
558.75 - this.name = name;
558.76 - }
558.77 -
558.78 - public String getValue() {
558.79 - return System.getProperty(name);
558.80 - }
558.81 - }
558.82 -
558.83 - @Override
558.84 - public DynamicMBean getDynamicMBeanFor(ObjectName name)
558.85 - throws InstanceNotFoundException {
558.86 - ObjectName namePattern = newObjectName(
558.87 - "com.example:type=Property,name=\"*\"");
558.88 - if (!namePattern.apply(name))
558.89 - throw new InstanceNotFoundException(name);
558.90 -
558.91 - String propName = ObjectName.unquote(name.getKeyProperty("name"));
558.92 - if (System.getProperty(propName) == null)
558.93 - throw new InstanceNotFoundException(name);
558.94 - PropertyMBean propMBean = new PropertyImpl(propName);
558.95 - return new StandardMBean(propMBean, PropertyMBean.class, false);
558.96 - }
558.97 -
558.98 - @Override
558.99 - protected Set<ObjectName> getNames() {
558.100 - Set<ObjectName> names = new TreeSet<ObjectName>();
558.101 - Properties props = System.getProperties();
558.102 - for (String propName : props.stringPropertyNames()) {
558.103 - ObjectName objectName = newObjectName(
558.104 - "com.example:type=Property,name=" +
558.105 - ObjectName.quote(propName));
558.106 - names.add(objectName);
558.107 - }
558.108 - return names;
558.109 - }
558.110 -
558.111 - private final VirtualEventManager vem = new VirtualEventManager();
558.112 -
558.113 - @Override
558.114 - public NotificationEmitter getNotificationEmitterFor(
558.115 - ObjectName name) throws InstanceNotFoundException {
558.116 - getDynamicMBeanFor(name); // check that the name is valid
558.117 - return vem.getNotificationEmitterFor(name);
558.118 - }
558.119 -
558.120 - public void propertyChanged(String name, String newValue) {
558.121 - ObjectName objectName = newObjectName(
558.122 - "com.example:type=Property,name=" + ObjectName.quote(name));
558.123 - Notification n = new Notification(
558.124 - "com.example.property.changed", objectName, 0L,
558.125 - "Property " + name + " changed");
558.126 - n.setUserData(newValue);
558.127 - vem.publish(objectName, n);
558.128 - }
558.129 - }
558.130 -
558.131 - static class QueueListener implements NotificationListener {
558.132 - BlockingQueue<Notification> q = new ArrayBlockingQueue<Notification>(10);
558.133 - public void handleNotification(Notification notification,
558.134 - Object handback) {
558.135 - q.add(notification);
558.136 - }
558.137 - }
558.138 -
558.139 - public static void main(String[] args) throws Exception {
558.140 - MBeanServer mmbs = ManagementFactory.getPlatformMBeanServer();
558.141 - String namespace = "props";
558.142 - PropsMBS pmbs = new PropsMBS();
558.143 - Object namespaceMBean = new JMXNamespace(pmbs);
558.144 - mmbs.registerMBean(namespaceMBean, new ObjectName(
558.145 - namespace + "//:type=JMXNamespace"));
558.146 - MBeanServer mbs = JMXNamespaces.narrowToNamespace(mmbs, namespace);
558.147 -
558.148 - Properties props = System.getProperties();
558.149 -
558.150 - int nprops = props.stringPropertyNames().size();
558.151 - if (nprops != mbs.getMBeanCount()) {
558.152 - throw new Exception(String.format("Properties: %d; MBeans: %d",
558.153 - nprops, mbs.getMBeanCount()));
558.154 - }
558.155 -
558.156 - for (String propName : props.stringPropertyNames()) {
558.157 - ObjectName propObjectName = new ObjectName(
558.158 - "com.example:type=Property,name=" + ObjectName.quote(propName));
558.159 - PropertyMBean propProx = JMX.newMBeanProxy(
558.160 - mbs, propObjectName, PropertyMBean.class);
558.161 - String propValue = propProx.getValue();
558.162 - String realPropValue = props.getProperty(propName);
558.163 - if (!realPropValue.equals(propValue)) {
558.164 - throw new Exception(String.format("Property %s: value is \"%s\"; " +
558.165 - "mbean says \"%s\"", propName, realPropValue, propValue));
558.166 - }
558.167 - }
558.168 -
558.169 - ObjectName fooPropObjectName =
558.170 - new ObjectName("com.example:type=Property,name=\"java.home\"");
558.171 - QueueListener ql = new QueueListener();
558.172 - mbs.addNotificationListener(fooPropObjectName, ql, null, null);
558.173 - pmbs.propertyChanged("java.home", "bar");
558.174 - Notification n = ql.q.poll(1, TimeUnit.SECONDS);
558.175 - if (n == null)
558.176 - throw new Exception("Notif didn't arrive");
558.177 - if (!"bar".equals(n.getUserData()))
558.178 - throw new Exception("Bad user data: " + n.getUserData());
558.179 -
558.180 - System.out.println("TEST PASSED");
558.181 - }
558.182 -}
559.1 --- a/test/javax/management/namespace/Wombat.java Mon Nov 23 10:04:47 2009 +0000
559.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
559.3 @@ -1,259 +0,0 @@
559.4 -/*
559.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
559.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
559.7 - *
559.8 - * This code is free software; you can redistribute it and/or modify it
559.9 - * under the terms of the GNU General Public License version 2 only, as
559.10 - * published by the Free Software Foundation.
559.11 - *
559.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
559.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
559.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
559.15 - * version 2 for more details (a copy is included in the LICENSE file that
559.16 - * accompanied this code).
559.17 - *
559.18 - * You should have received a copy of the GNU General Public License version
559.19 - * 2 along with this work; if not, write to the Free Software Foundation,
559.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
559.21 - *
559.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
559.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
559.24 - * have any questions.
559.25 - */
559.26 -
559.27 -import java.util.Random;
559.28 -import java.util.Set;
559.29 -import javax.management.AttributeChangeNotification;
559.30 -import javax.management.ListenerNotFoundException;
559.31 -import javax.management.MBeanAttributeInfo;
559.32 -import javax.management.MBeanInfo;
559.33 -import javax.management.MBeanNotificationInfo;
559.34 -import javax.management.MBeanOperationInfo;
559.35 -import javax.management.MBeanParameterInfo;
559.36 -import javax.management.MBeanRegistration;
559.37 -import javax.management.MBeanServer;
559.38 -import javax.management.NotCompliantMBeanException;
559.39 -import javax.management.NotificationBroadcasterSupport;
559.40 -import javax.management.NotificationEmitter;
559.41 -import javax.management.NotificationFilter;
559.42 -import javax.management.NotificationListener;
559.43 -import javax.management.ObjectName;
559.44 -import javax.management.StandardMBean;
559.45 -
559.46 -
559.47 -/**
559.48 - * Dynamic MBean based on StandardMBean
559.49 - * Class Wombat
559.50 - * Wombat Description
559.51 - * @author dfuchs
559.52 - */
559.53 -public class Wombat extends StandardMBean
559.54 - implements WombatMBean, NotificationEmitter, MBeanRegistration {
559.55 -
559.56 - /**
559.57 - * Attribute : Caption
559.58 - */
559.59 - private String caption = "I'm a wombat";
559.60 -
559.61 - private final long MAX_SEED = 36000;
559.62 - private final long seed;
559.63 - private final long period;
559.64 - private volatile int mood = 0;
559.65 -
559.66 - public int getMood() {
559.67 - final long degree = seed + (System.currentTimeMillis()/period)%MAX_SEED;
559.68 - final double angle = ((double)degree)/100;
559.69 - mood = (int)(100.0*Math.sin(angle));
559.70 - return mood;
559.71 - }
559.72 -
559.73 - public Wombat() throws NotCompliantMBeanException {
559.74 - this(WombatMBean.class);
559.75 - }
559.76 -
559.77 - public Wombat(Class<? extends WombatMBean> clazz)
559.78 - throws NotCompliantMBeanException {
559.79 - super(clazz);
559.80 - final Random r = new Random();
559.81 - seed = ((r.nextLong() % MAX_SEED) + MAX_SEED)%MAX_SEED;
559.82 - period = 200 + (((r.nextLong()%80)+80)%80)*10;
559.83 - }
559.84 -
559.85 - /**
559.86 - * Next are the methods to compute MBeanInfo.
559.87 - * You shouldn't update these methods.
559.88 - */
559.89 - @Override
559.90 - protected String getDescription(MBeanInfo info) {
559.91 - return "Wombats are strange beasts. You will find them down under " +
559.92 - "and in some computer programms.";
559.93 - }
559.94 -
559.95 - @Override
559.96 - protected String getDescription(MBeanAttributeInfo info) {
559.97 - String description = null;
559.98 - if (info.getName().equals("Caption")) {
559.99 - description = "A simple caption to describe a wombat";
559.100 - }
559.101 - if (info.getName().equals("Mood")) {
559.102 - description = "This Wombat's mood on a [-100,+100] scale."+
559.103 - " -100 means that this wombat is very angry.";
559.104 - }
559.105 - return description;
559.106 - }
559.107 -
559.108 - @Override
559.109 - protected String getDescription(MBeanOperationInfo op,
559.110 - MBeanParameterInfo param,
559.111 - int sequence) {
559.112 - return null;
559.113 - }
559.114 -
559.115 - @Override
559.116 - protected String getParameterName(MBeanOperationInfo op,
559.117 - MBeanParameterInfo param,
559.118 - int sequence) {
559.119 - return null;
559.120 - }
559.121 -
559.122 - @Override
559.123 - protected String getDescription(MBeanOperationInfo info) {
559.124 - String description = null;
559.125 - return description;
559.126 - }
559.127 -
559.128 - @Override
559.129 - public MBeanInfo getMBeanInfo() {
559.130 - MBeanInfo mbinfo = super.getMBeanInfo();
559.131 - return new MBeanInfo(mbinfo.getClassName(),
559.132 - mbinfo.getDescription(),
559.133 - mbinfo.getAttributes(),
559.134 - mbinfo.getConstructors(),
559.135 - mbinfo.getOperations(),
559.136 - getNotificationInfo());
559.137 - }
559.138 -
559.139 - /**
559.140 - * Get A simple caption to describe a wombat
559.141 - */
559.142 - public synchronized String getCaption() {
559.143 - return caption;
559.144 - }
559.145 -
559.146 - /**
559.147 - * Set A simple caption to describe a wombat
559.148 - */
559.149 - public void setCaption(String value) {
559.150 - final String oldValue;
559.151 - synchronized (this) {
559.152 - oldValue = caption;
559.153 - caption = value;
559.154 - }
559.155 - final AttributeChangeNotification notif =
559.156 - new AttributeChangeNotification(objectName,
559.157 - getNextSeqNumber(),
559.158 - System.currentTimeMillis(),
559.159 - "Caption changed","Caption",
559.160 - String.class.getName(),oldValue,value);
559.161 - broadcaster.sendNotification(notif);
559.162 - }
559.163 -
559.164 - /**
559.165 - * MBeanNotification support
559.166 - * You shouldn't update these methods
559.167 - */
559.168 - public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws IllegalArgumentException {
559.169 - broadcaster.addNotificationListener(listener, filter, handback);
559.170 - }
559.171 -
559.172 - public MBeanNotificationInfo[] getNotificationInfo() {
559.173 - return new MBeanNotificationInfo[] {
559.174 - new MBeanNotificationInfo(new String[] {
559.175 - AttributeChangeNotification.ATTRIBUTE_CHANGE},
559.176 - javax.management.AttributeChangeNotification.class.getName(),
559.177 - "Sent when the caption changes")
559.178 - };
559.179 - }
559.180 -
559.181 - public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException {
559.182 - broadcaster.removeNotificationListener(listener);
559.183 - }
559.184 -
559.185 - public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException {
559.186 - broadcaster.removeNotificationListener(listener, filter, handback);
559.187 - }
559.188 -
559.189 - private synchronized long getNextSeqNumber() {
559.190 - return seqNumber++;
559.191 - }
559.192 -
559.193 - private long seqNumber;
559.194 -
559.195 - private final NotificationBroadcasterSupport broadcaster = new NotificationBroadcasterSupport();
559.196 -
559.197 - /**
559.198 - * Allows the MBean to perform any operations it needs before being
559.199 - * registered in the MBean server. If the name of the MBean is not
559.200 - * specified, the MBean can provide a name for its registration. If
559.201 - * any exception is raised, the MBean will not be registered in the
559.202 - * MBean server.
559.203 - * @param server The MBean server in which the MBean will be registered.
559.204 - * @param name The object name of the MBean. This name is null if the
559.205 - * name parameter to one of the createMBean or registerMBean methods in
559.206 - * the MBeanServer interface is null. In that case, this method must
559.207 - * return a non-null ObjectName for the new MBean.
559.208 - * @return The name under which the MBean is to be registered. This value
559.209 - * must not be null. If the name parameter is not null, it will usually
559.210 - * but not necessarily be the returned value.
559.211 - * @throws Exception This exception will be caught by the MBean server and
559.212 - * re-thrown as an MBeanRegistrationException.
559.213 - */
559.214 - @Override
559.215 - public ObjectName preRegister(MBeanServer server, ObjectName name)
559.216 - throws Exception {
559.217 - objectName = name;
559.218 - mbeanServer = server;
559.219 - return super.preRegister(server, name);
559.220 - }
559.221 -
559.222 - /**
559.223 - * Allows the MBean to perform any operations needed after having
559.224 - * been registered in the MBean server or after the registration has
559.225 - * failed.
559.226 - * @param registrationDone Indicates wether or not the MBean has been
559.227 - * successfully registered in the MBean server. The value false means
559.228 - * that the registration has failed.
559.229 - */
559.230 - @Override
559.231 - public void postRegister(Boolean registrationDone) {
559.232 - super.postRegister(registrationDone);
559.233 - }
559.234 -
559.235 - /**
559.236 - * Allows the MBean to perform any operations it needs before being
559.237 - * unregistered by the MBean server.
559.238 - * @throws Exception This exception will be caught by the MBean server and
559.239 - * re-thrown as an MBeanRegistrationException.
559.240 - */
559.241 - @Override
559.242 - public void preDeregister() throws Exception {
559.243 - super.preDeregister();
559.244 - }
559.245 -
559.246 - /**
559.247 - * Allows the MBean to perform any operations needed after having been
559.248 - * unregistered in the MBean server.
559.249 - */
559.250 - @Override
559.251 - public void postDeregister() {
559.252 - super.postDeregister();
559.253 - }
559.254 -
559.255 - public Set<ObjectName> listMatching(ObjectName pattern) {
559.256 - return mbeanServer.queryNames(pattern, null);
559.257 - }
559.258 -
559.259 - private MBeanServer mbeanServer;
559.260 -
559.261 - private ObjectName objectName;
559.262 -}
560.1 --- a/test/javax/management/namespace/WombatMBean.java Mon Nov 23 10:04:47 2009 +0000
560.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
560.3 @@ -1,59 +0,0 @@
560.4 -
560.5 -/*
560.6 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
560.7 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
560.8 - *
560.9 - * This code is free software; you can redistribute it and/or modify it
560.10 - * under the terms of the GNU General Public License version 2 only, as
560.11 - * published by the Free Software Foundation.
560.12 - *
560.13 - * This code is distributed in the hope that it will be useful, but WITHOUT
560.14 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
560.15 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
560.16 - * version 2 for more details (a copy is included in the LICENSE file that
560.17 - * accompanied this code).
560.18 - *
560.19 - * You should have received a copy of the GNU General Public License version
560.20 - * 2 along with this work; if not, write to the Free Software Foundation,
560.21 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
560.22 - *
560.23 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
560.24 - * CA 95054 USA or visit www.sun.com if you need additional information or
560.25 - * have any questions.
560.26 - */
560.27 -
560.28 -import java.util.Set;
560.29 -import javax.management.ObjectName;
560.30 -
560.31 -/**
560.32 - * Interface WombatMBean
560.33 - * Wombat Description
560.34 - * @author dfuchs
560.35 - */
560.36 -public interface WombatMBean
560.37 -{
560.38 - /**
560.39 - * This Wombat's mood on a [-100,+100] scale.
560.40 - * -100 means that this wombat is very angry.
560.41 - * @return The wombat's mood.
560.42 - */
560.43 - public int getMood();
560.44 -
560.45 - /**
560.46 - * Get A simple caption to describe a wombat
560.47 - */
560.48 - public String getCaption();
560.49 -
560.50 - /**
560.51 - * Set A simple caption to describe a wombat
560.52 - */
560.53 - public void setCaption(String value);
560.54 -
560.55 - /**
560.56 - * List matching MBeans in the same server.
560.57 - * @param pattern an ObjectName pattern or null.
560.58 - * @return A list of matching MBeans.
560.59 - */
560.60 - public Set<ObjectName> listMatching(ObjectName pattern);
560.61 -
560.62 -}
561.1 --- a/test/javax/management/namespace/namespace.policy Mon Nov 23 10:04:47 2009 +0000
561.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
561.3 @@ -1,85 +0,0 @@
561.4 -grant codebase "file:/-" {
561.5 - permission java.util.PropertyPermission "jmx.wait", "read";
561.6 - permission java.util.PropertyPermission "jmx.rmi.port", "read";
561.7 - permission java.net.SocketPermission "*", "accept,connect,resolve";
561.8 - permission java.security.SecurityPermission "*";
561.9 -
561.10 - // Attribute Caption: allow get everywhere
561.11 - // ==================
561.12 -
561.13 - // allow getAttribute(*:*,Caption) in all MBeanServers
561.14 - permission javax.management.MBeanPermission "#Caption", "getAttribute";
561.15 - // allow getAttribute(*:*,Caption) in all namespaces recursively.
561.16 - permission javax.management.namespace.JMXNamespacePermission "Caption",
561.17 - "getAttribute";
561.18 -
561.19 - // Attribute Mood: allow get only in MBeanServers named rmi*
561.20 - // ===============
561.21 -
561.22 - // allow to get attribute Mood of Wombat MBeans only in namespaces
561.23 - // whose name match rmi*, wherever they are.
561.24 - // for this we need two permissions:
561.25 - permission javax.management.namespace.JMXNamespacePermission
561.26 - "*::Mood[**//rmi*//wombat:*]",
561.27 - "getAttribute";
561.28 - permission javax.management.namespace.JMXNamespacePermission
561.29 - "*::Mood[rmi*//wombat:*]",
561.30 - "getAttribute";
561.31 -
561.32 - // allow to get attribute mood in any MBeanServer whose name starts with
561.33 - // rmi
561.34 - permission javax.management.MBeanPermission "rmi*::#Mood",
561.35 - "getAttribute";
561.36 -
561.37 - // Attribute UUID:
561.38 - // ===============
561.39 -
561.40 - // allow to get attribute "UUID" everywhere.
561.41 - permission javax.management.namespace.JMXNamespacePermission
561.42 - "*::UUID[*//**//:*]",
561.43 - "getAttribute";
561.44 - permission javax.management.MBeanPermission
561.45 - "#UUID[*//:*]",
561.46 - "getAttribute";
561.47 -
561.48 -
561.49 -
561.50 - // Let getMBeanInfo and queryNames through everywhere...
561.51 - //
561.52 - permission javax.management.namespace.JMXNamespacePermission "[]",
561.53 - "getMBeanInfo,queryNames";
561.54 - permission javax.management.MBeanPermission "*",
561.55 - "getMBeanInfo,queryNames";
561.56 -
561.57 - // special permission for all wombats:
561.58 - //
561.59 - permission javax.management.namespace.JMXNamespacePermission
561.60 - "[**//*:type=Wombat,*]",
561.61 - "getObjectInstance,isInstanceOf,queryMBeans";
561.62 - permission javax.management.MBeanPermission "[*:type=Wombat,*]",
561.63 - "getObjectInstance,isInstanceOf,queryMBeans";
561.64 -
561.65 - // allow JMXNamespace::getDefaultDomain
561.66 - permission javax.management.namespace.JMXNamespacePermission
561.67 - "*::DefaultDomain",
561.68 - "getAttribute";
561.69 -
561.70 - // These permissions are required to connect visualvm.
561.71 - //
561.72 - permission javax.management.MBeanPermission "default::[java.lang:*]",
561.73 - "getObjectInstance,isInstanceOf,getAttribute,getMBeanInfo,queryNames,queryMBeans";
561.74 - permission javax.management.MBeanPermission "root::",
561.75 - "isInstanceOf,queryNames,queryMBeans,getAttribute,getMBeanInfo,getObjectInstance,getDomains";
561.76 - permission javax.management.namespace.JMXNamespacePermission
561.77 - "[**//JMImplementation:type=MBeanServerDelegate]",
561.78 - "addNotificationListener,removeNotificationListener,isInstanceOf,queryNames,queryMBeans,getAttribute,getMBeanInfo,getObjectInstance";
561.79 - permission javax.management.MBeanPermission
561.80 - "javax.management.MBeanServerDelegate",
561.81 - "addNotificationListener,removeNotificationListener,isInstanceOf,queryNames,queryMBeans,getAttribute,getMBeanInfo,getObjectInstance";
561.82 -
561.83 - // Thread monitoring
561.84 - permission java.lang.management.ManagementPermission "monitor";
561.85 - permission javax.management.MBeanPermission "*::sun.management.*#*[java.lang:*]", "invoke";
561.86 -};
561.87 -
561.88 -
562.1 --- a/test/javax/management/notification/SupportClearTest.java Mon Nov 23 10:04:47 2009 +0000
562.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
562.3 @@ -1,80 +0,0 @@
562.4 -/*
562.5 - * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
562.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
562.7 - *
562.8 - * This code is free software; you can redistribute it and/or modify it
562.9 - * under the terms of the GNU General Public License version 2 only, as
562.10 - * published by the Free Software Foundation.
562.11 - *
562.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
562.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
562.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
562.15 - * version 2 for more details (a copy is included in the LICENSE file that
562.16 - * accompanied this code).
562.17 - *
562.18 - * You should have received a copy of the GNU General Public License version
562.19 - * 2 along with this work; if not, write to the Free Software Foundation,
562.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
562.21 - *
562.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
562.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
562.24 - * have any questions.
562.25 - */
562.26 -
562.27 -/*
562.28 - * @test
562.29 - * @bug 6336980
562.30 - * @summary test 2 new methods: isListenedTo() and clear()
562.31 - * @author Shanliang JIANG
562.32 - * @run clean SupportClearTest
562.33 - * @run build SupportClearTest
562.34 - * @run main SupportClearTest
562.35 - */
562.36 -
562.37 -import javax.management.*;
562.38 -
562.39 -public class SupportClearTest {
562.40 - private static boolean received = false;
562.41 -
562.42 - public static void main(String[] args) throws Exception {
562.43 - System.out.println(">>> test 2 new methods: isListenedTo() and clear().");
562.44 -
562.45 - final NotificationListener listener = new NotificationListener() {
562.46 - public void handleNotification(Notification n, Object hb) {
562.47 - received = true;
562.48 - }
562.49 - };
562.50 -
562.51 - final NotificationBroadcasterSupport broadcaster =
562.52 - new NotificationBroadcasterSupport();
562.53 -
562.54 - System.out.println(">>> testing the method \"isListenedTo\"...");
562.55 - if (broadcaster.isListenedTo()) {
562.56 - throw new RuntimeException(
562.57 - "Bad implementation of the method \"isListenedTo\"!");
562.58 - }
562.59 -
562.60 - broadcaster.addNotificationListener(listener, null, null);
562.61 -
562.62 - if (!broadcaster.isListenedTo()) {
562.63 - throw new RuntimeException(
562.64 - "Bad implementation of the method \"isListenedTo\"!");
562.65 - }
562.66 -
562.67 - System.out.println(">>> testing the method \"clear\"...");
562.68 - broadcaster.removeAllNotificationListeners();
562.69 - if (broadcaster.isListenedTo()) {
562.70 - throw new RuntimeException(
562.71 - "Bad implementation of the method \"clear\"!");
562.72 - }
562.73 -
562.74 - broadcaster.sendNotification(new Notification("", "", 1L));
562.75 -
562.76 - if (received) {
562.77 - throw new RuntimeException(
562.78 - "Bad implementation of the method \"clear\"!");
562.79 - }
562.80 -
562.81 - System.out.println(">>> PASSED!");
562.82 - }
562.83 -}
563.1 --- a/test/javax/management/openmbean/CompositeDataToMapTest.java Mon Nov 23 10:04:47 2009 +0000
563.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
563.3 @@ -1,116 +0,0 @@
563.4 -/*
563.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
563.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
563.7 - *
563.8 - * This code is free software; you can redistribute it and/or modify it
563.9 - * under the terms of the GNU General Public License version 2 only, as
563.10 - * published by the Free Software Foundation.
563.11 - *
563.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
563.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
563.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
563.15 - * version 2 for more details (a copy is included in the LICENSE file that
563.16 - * accompanied this code).
563.17 - *
563.18 - * You should have received a copy of the GNU General Public License version
563.19 - * 2 along with this work; if not, write to the Free Software Foundation,
563.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
563.21 - *
563.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
563.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
563.24 - * have any questions.
563.25 - */
563.26 -
563.27 -/*
563.28 - * @test
563.29 - * @bug 6750472 6752563
563.30 - * @summary Test CompositeDataSupport.toMap.
563.31 - * @author Eamonn McManus
563.32 - * @run main/othervm -ea CompositeDataToMapTest
563.33 - */
563.34 -
563.35 -import java.lang.reflect.InvocationHandler;
563.36 -import java.lang.reflect.InvocationTargetException;
563.37 -import java.lang.reflect.Method;
563.38 -import java.lang.reflect.Proxy;
563.39 -import java.util.Collections;
563.40 -import java.util.HashMap;
563.41 -import java.util.Map;
563.42 -import javax.management.openmbean.CompositeData;
563.43 -import javax.management.openmbean.CompositeDataSupport;
563.44 -import javax.management.openmbean.CompositeType;
563.45 -import javax.management.openmbean.OpenType;
563.46 -import javax.management.openmbean.SimpleType;
563.47 -
563.48 -public class CompositeDataToMapTest {
563.49 - private static class IdentityInvocationHandler implements InvocationHandler {
563.50 - private final Object wrapped;
563.51 -
563.52 - public IdentityInvocationHandler(Object wrapped) {
563.53 - this.wrapped = wrapped;
563.54 - }
563.55 -
563.56 - public Object invoke(Object proxy, Method m, Object[] args)
563.57 - throws Throwable {
563.58 - try {
563.59 - return m.invoke(wrapped, args);
563.60 - } catch (InvocationTargetException e) {
563.61 - throw e.getCause();
563.62 - }
563.63 - }
563.64 - }
563.65 -
563.66 - private static <T> T wrap(T x, Class<T> intf) {
563.67 - InvocationHandler ih = new IdentityInvocationHandler(x);
563.68 - return intf.cast(Proxy.newProxyInstance(
563.69 - intf.getClassLoader(), new Class<?>[] {intf}, ih));
563.70 - }
563.71 -
563.72 - public static void main(String[] args) throws Exception {
563.73 - if (!CompositeDataToMapTest.class.desiredAssertionStatus())
563.74 - throw new AssertionError("Must be run with -ea");
563.75 -
563.76 - CompositeType emptyCT = new CompositeType(
563.77 - "empty", "empty", new String[0], new String[0], new OpenType<?>[0]);
563.78 - CompositeData emptyCD = new CompositeDataSupport(
563.79 - emptyCT, Collections.<String, Object>emptyMap());
563.80 - assert CompositeDataSupport.toMap(emptyCD).isEmpty() :
563.81 - "Empty CD produces empty Map";
563.82 -
563.83 - CompositeData emptyCD2 = new CompositeDataSupport(
563.84 - emptyCT, new String[0], new Object[0]);
563.85 - assert emptyCD.equals(emptyCD2) : "Empty CD can be constructed two ways";
563.86 -
563.87 - CompositeType namedNumberCT = new CompositeType(
563.88 - "NamedNumber", "NamedNumber",
563.89 - new String[] {"name", "number"},
563.90 - new String[] {"name", "number"},
563.91 - new OpenType<?>[] {SimpleType.STRING, SimpleType.INTEGER});
563.92 - Map<String, Object> namedNumberMap = new HashMap<String, Object>();
563.93 - namedNumberMap.put("name", "Deich");
563.94 - namedNumberMap.put("number", 10);
563.95 - CompositeData namedNumberCD = new CompositeDataSupport(
563.96 - namedNumberCT, namedNumberMap);
563.97 - assert CompositeDataSupport.toMap(namedNumberCD).equals(namedNumberMap) :
563.98 - "Map survives passage through CompositeData";
563.99 -
563.100 - namedNumberCD = wrap(namedNumberCD, CompositeData.class);
563.101 - assert CompositeDataSupport.toMap(namedNumberCD).equals(namedNumberMap) :
563.102 - "Map survives passage through wrapped CompositeData";
563.103 -
563.104 - namedNumberMap = CompositeDataSupport.toMap(namedNumberCD);
563.105 - namedNumberMap.put("name", "Ceathar");
563.106 - namedNumberMap.put("number", 4);
563.107 - namedNumberCD = new CompositeDataSupport(namedNumberCT, namedNumberMap);
563.108 - assert CompositeDataSupport.toMap(namedNumberCD).equals(namedNumberMap) :
563.109 - "Modified Map survives passage through CompositeData";
563.110 -
563.111 - try {
563.112 - namedNumberMap = CompositeDataSupport.toMap(null);
563.113 - assert false : "Null toMap arg provokes exception";
563.114 - } catch (Exception e) {
563.115 - assert e instanceof IllegalArgumentException :
563.116 - "Exception for null toMap arg is IllegalArgumentException";
563.117 - }
563.118 - }
563.119 -}
564.1 --- a/test/javax/management/openmbean/GenericMBeanExceptionTest.java Mon Nov 23 10:04:47 2009 +0000
564.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
564.3 @@ -1,278 +0,0 @@
564.4 -/*
564.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
564.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
564.7 - *
564.8 - * This code is free software; you can redistribute it and/or modify it
564.9 - * under the terms of the GNU General Public License version 2 only, as
564.10 - * published by the Free Software Foundation.
564.11 - *
564.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
564.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
564.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
564.15 - * version 2 for more details (a copy is included in the LICENSE file that
564.16 - * accompanied this code).
564.17 - *
564.18 - * You should have received a copy of the GNU General Public License version
564.19 - * 2 along with this work; if not, write to the Free Software Foundation,
564.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
564.21 - *
564.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
564.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
564.24 - * have any questions.
564.25 - */
564.26 -
564.27 -/*
564.28 - * @test
564.29 - * @bug 6456269
564.30 - * @summary Test GenericMBeanException
564.31 - * @author Eamonn McManus
564.32 - */
564.33 -
564.34 -import java.beans.ConstructorProperties;
564.35 -import java.lang.management.ManagementFactory;
564.36 -import java.lang.reflect.InvocationTargetException;
564.37 -import java.lang.reflect.Method;
564.38 -import javax.management.GenericMBeanException;
564.39 -import javax.management.JMX;
564.40 -import javax.management.MBeanServer;
564.41 -import javax.management.MBeanServerConnection;
564.42 -import javax.management.ObjectName;
564.43 -import javax.management.openmbean.CompositeData;
564.44 -import javax.management.openmbean.CompositeType;
564.45 -import javax.management.openmbean.MXBeanMapping;
564.46 -import javax.management.openmbean.MXBeanMappingFactory;
564.47 -import javax.management.remote.JMXConnector;
564.48 -import javax.management.remote.JMXConnectorFactory;
564.49 -import javax.management.remote.JMXConnectorServer;
564.50 -import javax.management.remote.JMXConnectorServerFactory;
564.51 -import javax.management.remote.JMXServiceURL;
564.52 -
564.53 -public class GenericMBeanExceptionTest {
564.54 - private static volatile String failure = null;
564.55 -
564.56 - public static interface ThrowerMBean {
564.57 - public void throwGeneric() throws GenericMBeanException;
564.58 - public void throwGeneric(Throwable cause) throws GenericMBeanException;
564.59 - public void throwGeneric(String errorCode) throws GenericMBeanException;
564.60 - public void throwGeneric(CompositeData userData) throws GenericMBeanException;
564.61 - public void throwGeneric(String errorCode, CompositeData userData)
564.62 - throws GenericMBeanException;
564.63 - public void throwGeneric(String errorCode, CompositeData userData, Throwable cause)
564.64 - throws GenericMBeanException;
564.65 - }
564.66 -
564.67 - public static class Thrower implements ThrowerMBean {
564.68 -
564.69 - public void throwGeneric() throws GenericMBeanException {
564.70 - throw new GenericMBeanException("Message");
564.71 - }
564.72 -
564.73 - public void throwGeneric(Throwable cause) throws GenericMBeanException {
564.74 - throw new GenericMBeanException("Message", cause);
564.75 - }
564.76 -
564.77 - public void throwGeneric(String errorCode) throws GenericMBeanException {
564.78 - throw new GenericMBeanException("Message", errorCode, null);
564.79 - }
564.80 -
564.81 - public void throwGeneric(CompositeData userData) throws GenericMBeanException {
564.82 - throw new GenericMBeanException("Message", null, userData);
564.83 - }
564.84 -
564.85 - public void throwGeneric(String errorCode, CompositeData userData)
564.86 - throws GenericMBeanException {
564.87 - throw new GenericMBeanException("Message", errorCode, userData);
564.88 - }
564.89 -
564.90 - public void throwGeneric(String errorCode, CompositeData userData,
564.91 - Throwable cause) throws GenericMBeanException {
564.92 - throw new GenericMBeanException("Message", errorCode, userData, cause);
564.93 - }
564.94 - }
564.95 -
564.96 - public static class Payload {
564.97 - private final int severity;
564.98 - private final String subsystem;
564.99 -
564.100 - @ConstructorProperties({"severity", "subsystem"})
564.101 - public Payload(int severity, String subsystem) {
564.102 - this.severity = severity;
564.103 - this.subsystem = subsystem;
564.104 - }
564.105 -
564.106 - public int getSeverity() {
564.107 - return severity;
564.108 - }
564.109 -
564.110 - public String getSubsystem() {
564.111 - return subsystem;
564.112 - }
564.113 -
564.114 - @Override
564.115 - public boolean equals(Object x) {
564.116 - if (!(x instanceof Payload))
564.117 - return false;
564.118 - Payload p = (Payload) x;
564.119 - return (severity == p.severity &&
564.120 - (subsystem == null) ?
564.121 - p.subsystem == null : subsystem.equals(p.subsystem));
564.122 - }
564.123 -
564.124 - @Override
564.125 - public int hashCode() {
564.126 - return severity + subsystem.hashCode();
564.127 - }
564.128 -
564.129 - @Override
564.130 - public String toString() {
564.131 - return "Payload{severity: " + severity + ", subsystem: " + subsystem + "}";
564.132 - }
564.133 - }
564.134 -
564.135 - public static void main(String[] args) throws Exception {
564.136 - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
564.137 - ObjectName name = new ObjectName("test:type=Thrower");
564.138 - Thrower thrower = new Thrower();
564.139 - mbs.registerMBean(thrower, name);
564.140 -
564.141 - if (args.length > 0) {
564.142 - System.out.println("Attach client now, hit return to exit");
564.143 - System.in.read();
564.144 - return;
564.145 - }
564.146 -
564.147 - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
564.148 - JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(
564.149 - url, null, mbs);
564.150 - cs.start();
564.151 - JMXServiceURL addr = cs.getAddress();
564.152 -
564.153 - JMXConnector cc = JMXConnectorFactory.connect(addr);
564.154 - MBeanServerConnection mbsc = cc.getMBeanServerConnection();
564.155 -
564.156 - ThrowerMBean throwerProxy = JMX.newMBeanProxy(mbsc, name, ThrowerMBean.class);
564.157 -
564.158 - Payload payload = new Payload(5, "modular modulizer");
564.159 - MXBeanMapping payloadMapping = MXBeanMappingFactory.DEFAULT.mappingForType(
564.160 - Payload.class, MXBeanMappingFactory.DEFAULT);
564.161 - CompositeData userData = (CompositeData)
564.162 - payloadMapping.toOpenValue(payload);
564.163 - Throwable cause = new IllegalArgumentException("Badness");
564.164 -
564.165 - Object[][] testCases = {
564.166 - {},
564.167 - {"code1"},
564.168 - {userData},
564.169 - {"code2", userData},
564.170 - {(String) null, userData},
564.171 - {"code99", userData, cause},
564.172 - {(String) null, userData, cause},
564.173 - };
564.174 -
564.175 - for (Object[] testCase : testCases) {
564.176 - System.out.println("Test case: " + testCaseString(testCase));
564.177 -
564.178 - // Find which ThrowerMBean method it corresponds to
564.179 - Method testMethod = null;
564.180 -search:
564.181 - for (Method m : ThrowerMBean.class.getMethods()) {
564.182 - Class<?>[] paramTypes = m.getParameterTypes();
564.183 - if (paramTypes.length != testCase.length)
564.184 - continue;
564.185 - for (int i = 0; i < paramTypes.length; i++) {
564.186 - if (testCase[i] != null && !paramTypes[i].isInstance(testCase[i]))
564.187 - continue search;
564.188 - }
564.189 - testMethod = m;
564.190 - }
564.191 -
564.192 - if (testMethod == null) {
564.193 - throw new Exception("TEST ERROR: no method corresponds: " +
564.194 - testCaseString(testCase));
564.195 - }
564.196 -
564.197 - try {
564.198 - testMethod.invoke(throwerProxy, testCase);
564.199 - fail("Did not throw exception", testCase);
564.200 - continue;
564.201 - } catch (InvocationTargetException e) {
564.202 - Throwable iteCause = e.getCause();
564.203 - if (!(iteCause instanceof GenericMBeanException)) {
564.204 - iteCause.printStackTrace(System.out);
564.205 - fail("Threw wrong exception " + iteCause, testCase);
564.206 - continue;
564.207 - }
564.208 - GenericMBeanException ge = (GenericMBeanException) iteCause;
564.209 - if (!ge.getMessage().equals("Message"))
564.210 - fail("Wrong message: " + ge.getMessage(), testCase);
564.211 -
564.212 - Class<?>[] paramTypes = testMethod.getParameterTypes();
564.213 - for (int i = 0; i < paramTypes.length; i++) {
564.214 - Class<?> paramType = paramTypes[i];
564.215 -
564.216 - if (paramType == Throwable.class) { // cause
564.217 - Throwable geCause = ge.getCause();
564.218 - if (!(geCause instanceof IllegalArgumentException))
564.219 - fail("Wrong cause: " + geCause, testCase);
564.220 - else if (!geCause.getMessage().equals("Badness"))
564.221 - fail("Wrong cause message: " + geCause.getMessage(), testCase);
564.222 - } else if (paramType == String.class) { // errorCode
564.223 - String errorCode = ge.getErrorCode();
564.224 - String expectedErrorCode =
564.225 - (testCase[i] == null) ? "" : (String) testCase[i];
564.226 - if (!expectedErrorCode.equals(errorCode))
564.227 - fail("Wrong error code: " + ge.getErrorCode(), testCase);
564.228 - } else if (paramType == CompositeData.class) { // userData
564.229 - CompositeData userData2 = ge.getUserData();
564.230 - if (!userData.equals(userData2))
564.231 - fail("Wrong userData: " + userData2, testCase);
564.232 - Payload payload2 = (Payload) payloadMapping.fromOpenValue(userData2);
564.233 - if (!payload.equals(payload2))
564.234 - fail("Wrong payload: " + payload2, testCase);
564.235 - } else
564.236 - throw new Exception("TEST ERROR: unknown parameter type: " + paramType);
564.237 - }
564.238 - }
564.239 - }
564.240 -
564.241 - if (failure == null)
564.242 - System.out.println("TEST PASSED");
564.243 - else
564.244 - throw new Exception("TEST FAILED: " + failure);
564.245 - }
564.246 -
564.247 - private static String testCaseString(Object[] testCase) {
564.248 - StringBuilder sb = new StringBuilder("[");
564.249 - String sep = "";
564.250 - for (Object x : testCase) {
564.251 - sb.append(sep);
564.252 - String xs = (x instanceof CompositeData) ?
564.253 - compositeDataString((CompositeData) x) : String.valueOf(x);
564.254 - sb.append(xs);
564.255 - sep = ", ";
564.256 - }
564.257 - sb.append("]");
564.258 - return sb.toString();
564.259 - }
564.260 -
564.261 - private static String compositeDataString(CompositeData cd) {
564.262 - StringBuilder sb = new StringBuilder("CompositeData{");
564.263 - CompositeType ct = cd.getCompositeType();
564.264 - String sep = "";
564.265 - for (String key : ct.keySet()) {
564.266 - sb.append(sep).append(key).append(": ").append(cd.get(key));
564.267 - sep = ", ";
564.268 - }
564.269 - sb.append("}");
564.270 - return sb.toString();
564.271 - }
564.272 -
564.273 - private static void fail(String why, Object[] testCase) {
564.274 - fail(testCaseString(testCase) + ": " + why);
564.275 - }
564.276 -
564.277 - private static void fail(String why) {
564.278 - failure = why;
564.279 - System.out.println("FAIL: " + why);
564.280 - }
564.281 -}
565.1 --- a/test/javax/management/query/QueryDottedAttrTest.java Mon Nov 23 10:04:47 2009 +0000
565.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
565.3 @@ -1,192 +0,0 @@
565.4 -/*
565.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
565.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
565.7 - *
565.8 - * This code is free software; you can redistribute it and/or modify it
565.9 - * under the terms of the GNU General Public License version 2 only, as
565.10 - * published by the Free Software Foundation.
565.11 - *
565.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
565.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
565.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
565.15 - * version 2 for more details (a copy is included in the LICENSE file that
565.16 - * accompanied this code).
565.17 - *
565.18 - * You should have received a copy of the GNU General Public License version
565.19 - * 2 along with this work; if not, write to the Free Software Foundation,
565.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
565.21 - *
565.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
565.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
565.24 - * have any questions.
565.25 - */
565.26 -
565.27 -/*
565.28 - * @test QueryDottedAttrTest
565.29 - * @bug 6602310
565.30 - * @summary Test that Query.attr can understand a.b etc.
565.31 - * @author Eamonn McManus
565.32 - */
565.33 -
565.34 -import java.beans.ConstructorProperties;
565.35 -import java.io.ByteArrayInputStream;
565.36 -import java.io.ByteArrayOutputStream;
565.37 -import java.io.ObjectInputStream;
565.38 -import java.io.ObjectOutputStream;
565.39 -import java.util.Collections;
565.40 -import java.util.Set;
565.41 -import javax.management.AttributeNotFoundException;
565.42 -import javax.management.MBeanException;
565.43 -import javax.management.MBeanServer;
565.44 -import javax.management.MBeanServerFactory;
565.45 -import javax.management.ObjectName;
565.46 -import javax.management.Query;
565.47 -import javax.management.QueryExp;
565.48 -import javax.management.ReflectionException;
565.49 -import javax.management.StandardMBean;
565.50 -
565.51 -public class QueryDottedAttrTest {
565.52 - public static class Complex {
565.53 - private final double re, im;
565.54 -
565.55 - @ConstructorProperties({"real", "imaginary"})
565.56 - public Complex(double re, double im) {
565.57 - this.re = re;
565.58 - this.im = im;
565.59 - }
565.60 -
565.61 - public double getRe() {
565.62 - return re;
565.63 - }
565.64 -
565.65 - public double getIm() {
565.66 - return im;
565.67 - }
565.68 - }
565.69 -
565.70 - public static interface Intf {
565.71 - Complex getComplex();
565.72 - int[] getIntArray();
565.73 - String[] getStringArray();
565.74 - }
565.75 -
565.76 - public static class Impl implements Intf {
565.77 - public Complex getComplex() {
565.78 - return new Complex(1.0, 1.0);
565.79 - }
565.80 -
565.81 - public int[] getIntArray() {
565.82 - return new int[] {1, 2, 3};
565.83 - }
565.84 -
565.85 - public String[] getStringArray() {
565.86 - return new String[] {"one", "two", "three"};
565.87 - }
565.88 - }
565.89 -
565.90 - public static interface TestMBean extends Intf {}
565.91 -
565.92 - public static class Test extends Impl implements TestMBean {}
565.93 -
565.94 - public static interface TestMXBean extends Intf {}
565.95 -
565.96 - public static class TestMX extends Impl implements TestMXBean {}
565.97 -
565.98 - public static class AttrWithDot extends StandardMBean {
565.99 - public <T> AttrWithDot(Object impl, Class<T> intf) {
565.100 - super(intf.cast(impl), intf, (intf == TestMXBean.class));
565.101 - }
565.102 -
565.103 - public Object getAttribute(String attribute)
565.104 - throws AttributeNotFoundException, MBeanException, ReflectionException {
565.105 - if (attribute.equals("Complex.re"))
565.106 - return 2.0;
565.107 - else
565.108 - return super.getAttribute(attribute);
565.109 - }
565.110 - }
565.111 -
565.112 - private static final boolean[] booleans = {false, true};
565.113 -
565.114 - private static final QueryExp[] alwaysTrueQueries = {
565.115 - Query.eq(Query.attr("IntArray.length"), Query.value(3)),
565.116 - Query.eq(Query.attr("StringArray.length"), Query.value(3)),
565.117 - Query.eq(Query.attr("Complex.im"), Query.value(1.0)),
565.118 - };
565.119 -
565.120 - private static final QueryExp[] alwaysFalseQueries = {
565.121 - Query.eq(Query.attr("IntArray.length"), Query.value("3")),
565.122 - Query.eq(Query.attr("IntArray.length"), Query.value(2)),
565.123 - Query.eq(Query.attr("Complex.im"), Query.value(-1.0)),
565.124 - Query.eq(Query.attr("Complex.xxx"), Query.value(0)),
565.125 - };
565.126 -
565.127 - private static final QueryExp[] attrWithDotTrueQueries = {
565.128 - Query.eq(Query.attr("Complex.re"), Query.value(2.0)),
565.129 - };
565.130 -
565.131 - private static final QueryExp[] attrWithDotFalseQueries = {
565.132 - Query.eq(Query.attr("Complex.re"), Query.value(1.0)),
565.133 - };
565.134 -
565.135 - private static String failure;
565.136 -
565.137 - public static void main(String[] args) throws Exception {
565.138 - ObjectName name = new ObjectName("a:b=c");
565.139 - for (boolean attrWithDot : booleans) {
565.140 - for (boolean mx : booleans) {
565.141 - String what =
565.142 - (mx ? "MXBean" : "Standard MBean") +
565.143 - (attrWithDot ? " having attribute with dot in its name" : "");
565.144 - System.out.println("Testing " + what);
565.145 - Class<?> intf = mx ? TestMXBean.class : TestMBean.class;
565.146 - Object impl = mx ? new TestMX() : new Test();
565.147 - if (attrWithDot)
565.148 - impl = new AttrWithDot(impl, intf);
565.149 - MBeanServer mbs = MBeanServerFactory.newMBeanServer();
565.150 - mbs.registerMBean(impl, name);
565.151 - boolean ismx = "true".equals(
565.152 - mbs.getMBeanInfo(name).getDescriptor().getFieldValue("mxbean"));
565.153 - if (mx != ismx)
565.154 - fail("MBean should " + (mx ? "" : "not ") + "be MXBean");
565.155 - test(mbs, name, alwaysTrueQueries, true);
565.156 - test(mbs, name, alwaysFalseQueries, false);
565.157 - test(mbs, name, attrWithDotTrueQueries, attrWithDot);
565.158 - test(mbs, name, attrWithDotFalseQueries, !attrWithDot);
565.159 - }
565.160 - }
565.161 - if (failure != null)
565.162 - throw new Exception("TEST FAILED: " + failure);
565.163 - }
565.164 -
565.165 - private static void test(
565.166 - MBeanServer mbs, ObjectName name, QueryExp[] queries, boolean expect)
565.167 - throws Exception {
565.168 - for (QueryExp query : queries) {
565.169 - // Serialize and deserialize the query to ensure that its
565.170 - // serialization is correct
565.171 - ByteArrayOutputStream bout = new ByteArrayOutputStream();
565.172 - ObjectOutputStream oout = new ObjectOutputStream(bout);
565.173 - oout.writeObject(query);
565.174 - oout.close();
565.175 - ByteArrayInputStream bin = new ByteArrayInputStream(bout.toByteArray());
565.176 - ObjectInputStream oin = new ObjectInputStream(bin);
565.177 - query = (QueryExp) oin.readObject();
565.178 - Set<ObjectName> names = mbs.queryNames(null, query);
565.179 - if (names.isEmpty()) {
565.180 - if (expect)
565.181 - fail("Query is false but should be true: " + query);
565.182 - } else if (names.equals(Collections.singleton(name))) {
565.183 - if (!expect)
565.184 - fail("Query is true but should be false: " + query);
565.185 - } else {
565.186 - fail("Query returned unexpected set: " + names);
565.187 - }
565.188 - }
565.189 - }
565.190 -
565.191 - private static void fail(String msg) {
565.192 - failure = msg;
565.193 - System.out.println("..." + msg);
565.194 - }
565.195 -}
566.1 --- a/test/javax/management/query/QueryExpStringTest.java Mon Nov 23 10:04:47 2009 +0000
566.2 +++ b/test/javax/management/query/QueryExpStringTest.java Wed Nov 25 11:08:25 2009 -0800
566.3 @@ -31,10 +31,6 @@
566.4 * @run main QueryExpStringTest
566.5 */
566.6
566.7 -// This test is mostly obsolete, since we now have Query.fromString.
566.8 -// The test includes its own parser, from which Query.fromString was derived.
566.9 -// The parsers are not identical and the one here is no longer maintained.
566.10 -
566.11 import java.util.*;
566.12 import javax.management.*;
566.13
567.1 --- a/test/javax/management/query/QueryNotifFilterTest.java Mon Nov 23 10:04:47 2009 +0000
567.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
567.3 @@ -1,347 +0,0 @@
567.4 -/*
567.5 - * Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
567.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
567.7 - *
567.8 - * This code is free software; you can redistribute it and/or modify it
567.9 - * under the terms of the GNU General Public License version 2 only, as
567.10 - * published by the Free Software Foundation.
567.11 - *
567.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
567.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
567.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
567.15 - * version 2 for more details (a copy is included in the LICENSE file that
567.16 - * accompanied this code).
567.17 - *
567.18 - * You should have received a copy of the GNU General Public License version
567.19 - * 2 along with this work; if not, write to the Free Software Foundation,
567.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
567.21 - *
567.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
567.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
567.24 - * have any questions.
567.25 - */
567.26 -
567.27 -/*
567.28 - * @test QueryNotifFilterTest
567.29 - * @bug 6610917
567.30 - * @summary Test the QueryNotificationFilter class
567.31 - * @author Eamonn McManus
567.32 - */
567.33 -
567.34 -import java.util.Arrays;
567.35 -import java.util.Collections;
567.36 -import java.util.HashSet;
567.37 -import java.util.List;
567.38 -import java.util.Set;
567.39 -import javax.management.Attribute;
567.40 -import javax.management.AttributeChangeNotification;
567.41 -import javax.management.MBeanAttributeInfo;
567.42 -import javax.management.MBeanInfo;
567.43 -import javax.management.MBeanServer;
567.44 -import javax.management.MalformedObjectNameException;
567.45 -import javax.management.Notification;
567.46 -import javax.management.NotificationFilter;
567.47 -import javax.management.ObjectInstance;
567.48 -import javax.management.ObjectName;
567.49 -import javax.management.Query;
567.50 -import javax.management.QueryEval;
567.51 -import javax.management.QueryExp;
567.52 -import javax.management.QueryNotificationFilter;
567.53 -
567.54 -public class QueryNotifFilterTest {
567.55 - private static class Case {
567.56 - final Notification notif;
567.57 - final QueryExp query;
567.58 - final boolean expect;
567.59 - final Class<? extends Notification> notifClass;
567.60 - Case(Notification notif, String query, boolean expect) {
567.61 - this(notif, query, notif.getClass(), expect);
567.62 - }
567.63 - Case(Notification notif, String query,
567.64 - Class<? extends Notification> notifClass, boolean expect) {
567.65 - this(notif, Query.fromString(query), notifClass, expect);
567.66 - }
567.67 - Case(Notification notif, QueryExp query, boolean expect) {
567.68 - this(notif, query, notif.getClass(), expect);
567.69 - }
567.70 - Case(Notification notif, QueryExp query,
567.71 - Class<? extends Notification> notifClass, boolean expect) {
567.72 - this.notif = notif;
567.73 - this.query = query;
567.74 - this.expect = expect;
567.75 - this.notifClass = notifClass;
567.76 - }
567.77 - }
567.78 -
567.79 - /* In principle users can create their own implementations of QueryExp
567.80 - * and use them with QueryNotificationFilter. If they do so, then
567.81 - * they can call any MBeanServer method. Not all of those methods
567.82 - * will work with the special MBeanServer we concoct to analyze a
567.83 - * Notification, but some will, including some that are not called
567.84 - * by the standard queries. So we check each of those cases too.
567.85 - */
567.86 - private static class ExoticCase {
567.87 - final Notification trueNotif;
567.88 - final Notification falseNotif;
567.89 - final QueryExp query;
567.90 - ExoticCase(Notification trueNotif, Notification falseNotif, QueryExp query) {
567.91 - this.trueNotif = trueNotif;
567.92 - this.falseNotif = falseNotif;
567.93 - this.query = query;
567.94 - }
567.95 - }
567.96 -
567.97 - private static abstract class ExoticQuery
567.98 - extends QueryEval implements QueryExp {
567.99 - private final String queryString;
567.100 - ExoticQuery(String queryString) {
567.101 - this.queryString = queryString;
567.102 - }
567.103 - abstract boolean apply(MBeanServer mbs, ObjectName name) throws Exception;
567.104 - //@Override - doesn't override in JDK5
567.105 - public boolean apply(ObjectName name) {
567.106 - try {
567.107 - return apply(getMBeanServer(), name);
567.108 - } catch (Exception e) {
567.109 - e.printStackTrace(System.out);
567.110 - return false;
567.111 - }
567.112 - }
567.113 - @Override
567.114 - public String toString() {
567.115 - return queryString;
567.116 - }
567.117 - }
567.118 -
567.119 - private static ObjectName makeObjectName(String s) {
567.120 - try {
567.121 - return new ObjectName(s);
567.122 - } catch (MalformedObjectNameException e) {
567.123 - throw new RuntimeException(e);
567.124 - }
567.125 - }
567.126 -
567.127 - public static class CustomNotification extends Notification {
567.128 - public CustomNotification(String type, Object source, long seqNo) {
567.129 - super(type, source, seqNo);
567.130 - }
567.131 -
567.132 - public String getName() {
567.133 - return "claude";
567.134 - }
567.135 -
567.136 - public boolean isInteresting() {
567.137 - return true;
567.138 - }
567.139 - }
567.140 -
567.141 - private static final Notification simpleNotif =
567.142 - new Notification("mytype", "source", 0L);
567.143 - private static final Notification attrChangeNotif =
567.144 - new AttributeChangeNotification(
567.145 - "x", 0L, 0L, "msg", "AttrName", "int", 2, 3);
567.146 - private static final ObjectName testObjectName = makeObjectName("a:b=c");
567.147 - private static final Notification sourcedNotif =
567.148 - new Notification("mytype", testObjectName, 0L);
567.149 - private static final Notification customNotif =
567.150 - new CustomNotification("mytype", testObjectName, 0L);
567.151 -
567.152 - private static final Case[] testCases = {
567.153 - new Case(simpleNotif, "Type = 'mytype'", true),
567.154 - new Case(simpleNotif, "Type = 'mytype'",
567.155 - Notification.class, true),
567.156 - new Case(simpleNotif, "Type = 'mytype'",
567.157 - AttributeChangeNotification.class, false),
567.158 - new Case(simpleNotif, "Type != 'mytype'", false),
567.159 - new Case(simpleNotif, "Type = 'somethingelse'", false),
567.160 - new Case(attrChangeNotif, "AttributeName = 'AttrName'", true),
567.161 - new Case(attrChangeNotif,
567.162 - "instanceof 'javax.management.AttributeChangeNotification'",
567.163 - true),
567.164 - new Case(attrChangeNotif,
567.165 - "instanceof 'javax.management.Notification'",
567.166 - true),
567.167 - new Case(attrChangeNotif,
567.168 - "instanceof 'javax.management.relation.MBeanServerNotification'",
567.169 - false),
567.170 - new Case(attrChangeNotif,
567.171 - "class = 'javax.management.AttributeChangeNotification'",
567.172 - true),
567.173 - new Case(attrChangeNotif,
567.174 - "javax.management.AttributeChangeNotification#AttributeName = 'AttrName'",
567.175 - true),
567.176 - new Case(sourcedNotif,
567.177 - testObjectName,
567.178 - true),
567.179 - new Case(sourcedNotif,
567.180 - makeObjectName("a*:b=*"),
567.181 - true),
567.182 - new Case(sourcedNotif,
567.183 - makeObjectName("a*:c=*"),
567.184 - false),
567.185 - new Case(customNotif, "Name = 'claude'", true),
567.186 - new Case(customNotif, "Name = 'tiddly'", false),
567.187 - new Case(customNotif, "Interesting = true", true),
567.188 - new Case(customNotif, "Interesting = false", false),
567.189 - };
567.190 -
567.191 - private static final ExoticCase[] exoticTestCases = {
567.192 - new ExoticCase(
567.193 - simpleNotif, new Notification("notmytype", "source", 0L),
567.194 - new ExoticQuery("getAttributes") {
567.195 - boolean apply(MBeanServer mbs, ObjectName name)
567.196 - throws Exception {
567.197 - List<Attribute> attrs = mbs.getAttributes(
567.198 - name, new String[] {"Type", "Source"}).asList();
567.199 - return (attrs.get(0).equals(new Attribute("Type", "mytype")) &&
567.200 - attrs.get(1).equals(new Attribute("Source", "source")));
567.201 - }
567.202 - }),
567.203 - new ExoticCase(
567.204 - new Notification("mytype", "source", 0L) {},
567.205 - simpleNotif,
567.206 - new ExoticQuery("getClassLoaderFor") {
567.207 - boolean apply(MBeanServer mbs, ObjectName name)
567.208 - throws Exception {
567.209 - return (mbs.getClassLoaderFor(name) ==
567.210 - this.getClass().getClassLoader());
567.211 - }
567.212 - }),
567.213 - new ExoticCase(
567.214 - sourcedNotif, simpleNotif,
567.215 - new ExoticQuery("getDomains") {
567.216 - boolean apply(MBeanServer mbs, ObjectName name)
567.217 - throws Exception {
567.218 - return Arrays.equals(mbs.getDomains(),
567.219 - new String[] {testObjectName.getDomain()});
567.220 - }
567.221 - }),
567.222 - new ExoticCase(
567.223 - simpleNotif, attrChangeNotif,
567.224 - new ExoticQuery("getMBeanInfo") {
567.225 - boolean apply(MBeanServer mbs, ObjectName name)
567.226 - throws Exception {
567.227 - MBeanInfo mbi = mbs.getMBeanInfo(name);
567.228 - // If we ever add a constructor to Notification then
567.229 - // we will have to change the 4 below.
567.230 - if (mbi.getOperations().length > 0 ||
567.231 - mbi.getConstructors().length != 4 ||
567.232 - mbi.getNotifications().length > 0)
567.233 - return false;
567.234 - Set<String> expect = new HashSet<String>(
567.235 - Arrays.asList(
567.236 - "Class", "Message", "SequenceNumber", "Source",
567.237 - "TimeStamp", "Type", "UserData"));
567.238 - Set<String> actual = new HashSet<String>();
567.239 - for (MBeanAttributeInfo mbai : mbi.getAttributes())
567.240 - actual.add(mbai.getName());
567.241 - return actual.equals(expect);
567.242 - }
567.243 - }),
567.244 - new ExoticCase(
567.245 - simpleNotif, attrChangeNotif,
567.246 - new ExoticQuery("getObjectInstance") {
567.247 - boolean apply(MBeanServer mbs, ObjectName name)
567.248 - throws Exception {
567.249 - ObjectInstance oi = mbs.getObjectInstance(name);
567.250 - return oi.getClassName().equals(Notification.class.getName());
567.251 - }
567.252 - }),
567.253 - new ExoticCase(
567.254 - sourcedNotif, simpleNotif,
567.255 - new ExoticQuery("queryNames") {
567.256 - boolean apply(MBeanServer mbs, ObjectName name)
567.257 - throws Exception {
567.258 - Set<ObjectName> names = mbs.queryNames(null,
567.259 - Query.eq(Query.attr("Type"), Query.value("mytype")));
567.260 - return names.equals(Collections.singleton(testObjectName));
567.261 - }
567.262 - }),
567.263 - new ExoticCase(
567.264 - sourcedNotif, simpleNotif,
567.265 - new ExoticQuery("queryMBeans") {
567.266 - boolean apply(MBeanServer mbs, ObjectName name)
567.267 - throws Exception {
567.268 - Set<ObjectInstance> insts = mbs.queryMBeans(null,
567.269 - Query.eq(Query.attr("Type"), Query.value("mytype")));
567.270 - if (insts.size() != 1)
567.271 - return false;
567.272 - ObjectInstance inst = insts.iterator().next();
567.273 - return (inst.getObjectName().equals(testObjectName) &&
567.274 - inst.getClassName().equals(Notification.class.getName()));
567.275 - }
567.276 - }),
567.277 - };
567.278 -
567.279 - private static enum Test {
567.280 - QUERY_EXP("query"), STRING("string"), STRING_PLUS_CLASS("string with class");
567.281 - private final String name;
567.282 - Test(String name) {
567.283 - this.name = name;
567.284 - }
567.285 - @Override
567.286 - public String toString() {
567.287 - return name;
567.288 - }
567.289 - }
567.290 -
567.291 - public static void main(String[] args) throws Exception {
567.292 - boolean allok = true;
567.293 - for (Case testCase : testCases) {
567.294 - for (Test test : Test.values()) {
567.295 - QueryNotificationFilter nf;
567.296 - String queryString;
567.297 - switch (test) {
567.298 - case QUERY_EXP: {
567.299 - QueryExp inst = Query.isInstanceOf(
567.300 - Query.value(testCase.notifClass.getName()));
567.301 - QueryExp and = Query.and(inst, testCase.query);
567.302 - queryString = Query.toString(and);
567.303 - nf = new QueryNotificationFilter(and);
567.304 - break;
567.305 - }
567.306 - case STRING: {
567.307 - String s = "instanceof '" + testCase.notifClass.getName() + "'";
567.308 - queryString = s + " and " + Query.toString(testCase.query);
567.309 - nf = new QueryNotificationFilter(queryString);
567.310 - break;
567.311 - }
567.312 - case STRING_PLUS_CLASS:
567.313 - queryString = null;
567.314 - nf = new QueryNotificationFilter(
567.315 - testCase.notifClass, Query.toString(testCase.query));
567.316 - break;
567.317 - default:
567.318 - throw new AssertionError();
567.319 - }
567.320 - boolean accept = nf.isNotificationEnabled(testCase.notif);
567.321 - if (queryString != null) {
567.322 - queryString = Query.toString(Query.fromString(queryString));
567.323 - if (!queryString.equals(Query.toString(nf.getQuery()))) {
567.324 - System.out.println("FAIL: query string mismatch: expected " +
567.325 - "\"" + queryString + "\", got \"" +
567.326 - Query.toString(nf.getQuery()));
567.327 - allok = false;
567.328 - }
567.329 - }
567.330 - boolean ok = (accept == testCase.expect);
567.331 - System.out.println((ok ? "pass" : "FAIL") + ": " +
567.332 - testCase.query + " (" + test + ")");
567.333 - allok &= ok;
567.334 - }
567.335 - }
567.336 - for (ExoticCase testCase : exoticTestCases) {
567.337 - NotificationFilter nf = new QueryNotificationFilter(testCase.query);
567.338 - for (boolean expect : new boolean[] {true, false}) {
567.339 - Notification n = expect ? testCase.trueNotif : testCase.falseNotif;
567.340 - boolean accept = nf.isNotificationEnabled(n);
567.341 - boolean ok = (accept == expect);
567.342 - System.out.println((ok ? "pass" : "FAIL") + ": " +
567.343 - testCase.query + ": " + n);
567.344 - allok &= ok;
567.345 - }
567.346 - }
567.347 - if (!allok)
567.348 - throw new Exception("TEST FAILED");
567.349 - }
567.350 -}
568.1 --- a/test/javax/management/query/QueryParseTest.java Mon Nov 23 10:04:47 2009 +0000
568.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
568.3 @@ -1,781 +0,0 @@
568.4 -/*
568.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
568.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
568.7 - *
568.8 - * This code is free software; you can redistribute it and/or modify it
568.9 - * under the terms of the GNU General Public License version 2 only, as
568.10 - * published by the Free Software Foundation.
568.11 - *
568.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
568.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
568.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
568.15 - * version 2 for more details (a copy is included in the LICENSE file that
568.16 - * accompanied this code).
568.17 - *
568.18 - * You should have received a copy of the GNU General Public License version
568.19 - * 2 along with this work; if not, write to the Free Software Foundation,
568.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
568.21 - *
568.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
568.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
568.24 - * have any questions.
568.25 - */
568.26 -
568.27 -/*
568.28 - * @test QueryParseTest
568.29 - * @bug 6602310 6604768
568.30 - * @summary Test Query.fromString and Query.toString.
568.31 - * @author Eamonn McManus
568.32 - */
568.33 -
568.34 -import java.util.Collections;
568.35 -import java.util.Set;
568.36 -import javax.management.Attribute;
568.37 -import javax.management.AttributeList;
568.38 -import javax.management.AttributeNotFoundException;
568.39 -import javax.management.DynamicMBean;
568.40 -import javax.management.MBeanAttributeInfo;
568.41 -import javax.management.MBeanInfo;
568.42 -import javax.management.MBeanServer;
568.43 -import javax.management.MBeanServerDelegate;
568.44 -import javax.management.MBeanServerFactory;
568.45 -import javax.management.ObjectName;
568.46 -import javax.management.Query;
568.47 -import javax.management.QueryExp;
568.48 -
568.49 -public class QueryParseTest {
568.50 - // In this table, each string constant corresponds to a test case.
568.51 - // The objects following the string up to the next string are MBeans.
568.52 - // Each MBean must implement ExpectedValue to return true or false
568.53 - // according as it should return that value for the query parsed
568.54 - // from the given string. The test will parse the string into a
568.55 - // a query and verify that the MBeans return the expected value
568.56 - // for that query. Then it will convert the query back into a string
568.57 - // and into a second query, and check that the MBeans return the
568.58 - // expected value for that query too. The reason we need to do all
568.59 - // this is that the spec talks about "equivalent queries", and gives
568.60 - // the implementation wide scope to rearrange queries. So we cannot
568.61 - // just compare string values.
568.62 - //
568.63 - // We could also write an implementation-dependent test that knew what
568.64 - // the strings look like, and that would have to be changed if the
568.65 - // implementation changed. But the approach here is cleaner.
568.66 - //
568.67 - // To simplify the creation of MBeans, most use the expectTrue or
568.68 - // expectFalse methods. The parameters of these methods end up in
568.69 - // attributes called "A", "B", "C", etc.
568.70 - private static final Object[] queryTests = {
568.71 - // RELATIONS
568.72 -
568.73 - "A < B",
568.74 - expectTrue(1, 2), expectTrue(1.0, 2.0), expectTrue("one", "two"),
568.75 - expectTrue(Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY),
568.76 - expectFalse(Double.POSITIVE_INFINITY, Double.NEGATIVE_INFINITY),
568.77 - expectFalse(1, 1), expectFalse(1.0, 1.0), expectFalse("one", "one"),
568.78 - expectFalse(2, 1), expectFalse(2.0, 1.0), expectFalse("two", "one"),
568.79 - expectFalse(Double.NaN, Double.NaN),
568.80 -
568.81 - "One = two",
568.82 - expectTrueOneTwo(1, 1), expectTrueOneTwo(1.0, 1.0),
568.83 - expectFalseOneTwo(1, 2), expectFalseOneTwo(2, 1),
568.84 -
568.85 - "A <= B",
568.86 - expectTrue(1, 1), expectTrue(1, 2), expectTrue("one", "one"),
568.87 - expectTrue("one", "two"),
568.88 - expectFalse(2, 1), expectFalse("two", "one"),
568.89 - expectFalse(Double.NaN, Double.NaN),
568.90 -
568.91 - "A >= B",
568.92 - expectTrue(1, 1), expectTrue(2, 1), expectTrue("two", "one"),
568.93 - expectFalse(1, 2), expectFalse("one", "two"),
568.94 -
568.95 - "A > B",
568.96 - expectTrue(2, 1), expectTrue("two", "one"),
568.97 - expectFalse(2, 2), expectFalse(1, 2), expectFalse(1.0, 2.0),
568.98 - expectFalse("one", "two"),
568.99 -
568.100 - "A <> B",
568.101 - expectTrue(1, 2), expectTrue("foo", "bar"),
568.102 - expectFalse(1, 1), expectFalse("foo", "foo"),
568.103 -
568.104 - "A != B",
568.105 - expectTrue(1, 2), expectTrue("foo", "bar"),
568.106 - expectFalse(1, 1), expectFalse("foo", "foo"),
568.107 -
568.108 - // PARENTHESES
568.109 -
568.110 - "(((A))) = (B)",
568.111 - expectTrue(1, 1), expectFalse(1, 2),
568.112 -
568.113 - "(A = B)",
568.114 - expectTrue(1, 1), expectFalse(1, 2),
568.115 -
568.116 - "(((A = (B))))",
568.117 - expectTrue(1, 1), expectFalse(1, 2),
568.118 -
568.119 - // INTEGER LITERALS
568.120 -
568.121 - "A = 1234567890123456789",
568.122 - expectTrue(1234567890123456789L), expectFalse(123456789L),
568.123 -
568.124 - "A = +1234567890123456789",
568.125 - expectTrue(1234567890123456789L), expectFalse(123456789L),
568.126 -
568.127 - "A = -1234567890123456789",
568.128 - expectTrue(-1234567890123456789L), expectFalse(-123456789L),
568.129 -
568.130 -
568.131 - "A = + 1234567890123456789",
568.132 - expectTrue(1234567890123456789L), expectFalse(123456789L),
568.133 -
568.134 - "A = - 1234567890123456789",
568.135 - expectTrue(-1234567890123456789L), expectFalse(-123456789L),
568.136 -
568.137 - "A = " + Long.MAX_VALUE,
568.138 - expectTrue(Long.MAX_VALUE), expectFalse(Long.MIN_VALUE),
568.139 -
568.140 - "A = " + Long.MIN_VALUE,
568.141 - expectTrue(Long.MIN_VALUE), expectFalse(Long.MAX_VALUE),
568.142 -
568.143 - // DOUBLE LITERALS
568.144 -
568.145 - "A = 0.0",
568.146 - expectTrue(0.0), expectFalse(1.0),
568.147 -
568.148 - "A = 0.0e23",
568.149 - expectTrue(0.0), expectFalse(1.0),
568.150 -
568.151 - "A = 1.2e3",
568.152 - expectTrue(1.2e3), expectFalse(1.2),
568.153 -
568.154 - "A = +1.2",
568.155 - expectTrue(1.2), expectFalse(-1.2),
568.156 -
568.157 - "A = 1.2e+3",
568.158 - expectTrue(1.2e3), expectFalse(1.2),
568.159 -
568.160 - "A = 1.2e-3",
568.161 - expectTrue(1.2e-3), expectFalse(1.2),
568.162 -
568.163 - "A = 1.2E3",
568.164 - expectTrue(1.2e3), expectFalse(1.2),
568.165 -
568.166 - "A = -1.2e3",
568.167 - expectTrue(-1.2e3), expectFalse(1.2),
568.168 -
568.169 - "A = " + Double.MAX_VALUE,
568.170 - expectTrue(Double.MAX_VALUE), expectFalse(Double.MIN_VALUE),
568.171 -
568.172 - "A = " + -Double.MAX_VALUE,
568.173 - expectTrue(-Double.MAX_VALUE), expectFalse(-Double.MIN_VALUE),
568.174 -
568.175 - "A = " + Double.MIN_VALUE,
568.176 - expectTrue(Double.MIN_VALUE), expectFalse(Double.MAX_VALUE),
568.177 -
568.178 - "A = " + -Double.MIN_VALUE,
568.179 - expectTrue(-Double.MIN_VALUE), expectFalse(-Double.MAX_VALUE),
568.180 -
568.181 - Query.toString( // A = Infinity -> A = (1.0/0.0)
568.182 - Query.eq(Query.attr("A"), Query.value(Double.POSITIVE_INFINITY))),
568.183 - expectTrue(Double.POSITIVE_INFINITY),
568.184 - expectFalse(0.0), expectFalse(Double.NEGATIVE_INFINITY),
568.185 -
568.186 - Query.toString( // A = -Infinity -> A = (-1.0/0.0)
568.187 - Query.eq(Query.attr("A"), Query.value(Double.NEGATIVE_INFINITY))),
568.188 - expectTrue(Double.NEGATIVE_INFINITY),
568.189 - expectFalse(0.0), expectFalse(Double.POSITIVE_INFINITY),
568.190 -
568.191 - Query.toString( // A < NaN -> A < (0.0/0.0)
568.192 - Query.lt(Query.attr("A"), Query.value(Double.NaN))),
568.193 - expectFalse(0.0), expectFalse(Double.NEGATIVE_INFINITY),
568.194 - expectFalse(Double.POSITIVE_INFINITY), expectFalse(Double.NaN),
568.195 -
568.196 - Query.toString( // A >= NaN -> A < (0.0/0.0)
568.197 - Query.geq(Query.attr("A"), Query.value(Double.NaN))),
568.198 - expectFalse(0.0), expectFalse(Double.NEGATIVE_INFINITY),
568.199 - expectFalse(Double.POSITIVE_INFINITY), expectFalse(Double.NaN),
568.200 -
568.201 - // STRING LITERALS
568.202 -
568.203 - "A = 'blim'",
568.204 - expectTrue("blim"), expectFalse("blam"),
568.205 -
568.206 - "A = 'can''t'",
568.207 - expectTrue("can't"), expectFalse("cant"), expectFalse("can''t"),
568.208 -
568.209 - "A = '''blim'''",
568.210 - expectTrue("'blim'"), expectFalse("'blam'"),
568.211 -
568.212 - "A = ''",
568.213 - expectTrue(""), expectFalse((Object) null),
568.214 -
568.215 - // BOOLEAN LITERALS
568.216 -
568.217 - "A = true",
568.218 - expectTrue(true), expectFalse(false), expectFalse((Object) null),
568.219 -
568.220 - "A = TRUE",
568.221 - expectTrue(true), expectFalse(false),
568.222 -
568.223 - "A = TrUe",
568.224 - expectTrue(true), expectFalse(false),
568.225 -
568.226 - "A = false",
568.227 - expectTrue(false), expectFalse(true),
568.228 -
568.229 - "A = fAlSe",
568.230 - expectTrue(false), expectFalse(true),
568.231 -
568.232 - "A = \"true\"", // An attribute called "true"
568.233 - expectFalse(true), expectFalse(false), expectFalse("\"true\""),
568.234 - newTester(new String[] {"A", "true"}, new Object[] {2.2, 2.2}, true),
568.235 - newTester(new String[] {"A", "true"}, new Object[] {2.2, 2.3}, false),
568.236 -
568.237 - "A = \"False\"",
568.238 - expectFalse(true), expectFalse(false), expectFalse("\"False\""),
568.239 - newTester(new String[] {"A", "False"}, new Object[] {2.2, 2.2}, true),
568.240 - newTester(new String[] {"A", "False"}, new Object[] {2.2, 2.3}, false),
568.241 -
568.242 - // ARITHMETIC
568.243 -
568.244 - "A + B = 10",
568.245 - expectTrue(4, 6), expectFalse(3, 8),
568.246 -
568.247 - "A + B = 'blim'",
568.248 - expectTrue("bl", "im"), expectFalse("bl", "am"),
568.249 -
568.250 - "A - B = 10",
568.251 - expectTrue(16, 6), expectFalse(16, 3),
568.252 -
568.253 - "A * B = 10",
568.254 - expectTrue(2, 5), expectFalse(3, 3),
568.255 -
568.256 - "A / B = 10",
568.257 - expectTrue(70, 7), expectTrue(70.0, 7), expectFalse(70.01, 7),
568.258 -
568.259 - "A + B + C = 10",
568.260 - expectTrue(2, 3, 5), expectFalse(2, 4, 8),
568.261 -
568.262 - "A+B+C=10",
568.263 - expectTrue(2, 3, 5), expectFalse(2, 4, 8),
568.264 -
568.265 - "A + B + C + D = 10",
568.266 - expectTrue(1, 2, 3, 4), expectFalse(2, 3, 4, 5),
568.267 -
568.268 - "A + (B + C) = 10",
568.269 - expectTrue(2, 3, 5), expectFalse(2, 4, 8),
568.270 -
568.271 - // It is not correct to rearrange A + (B + C) as A + B + C
568.272 - // (which means (A + B) + C), because of overflow.
568.273 - // In particular Query.toString must not do this.
568.274 - "A + (B + C) = " + Double.MAX_VALUE, // ensure no false associativity
568.275 - expectTrue(Double.MAX_VALUE, Double.MAX_VALUE, -Double.MAX_VALUE),
568.276 - expectFalse(-Double.MAX_VALUE, Double.MAX_VALUE, Double.MAX_VALUE),
568.277 -
568.278 - "A * (B * C) < " + Double.MAX_VALUE, // same test for multiplication
568.279 - expectTrue(Double.MAX_VALUE, Double.MAX_VALUE, Double.MIN_VALUE),
568.280 - expectFalse(Double.MIN_VALUE, Double.MAX_VALUE, Double.MAX_VALUE),
568.281 -
568.282 - "A * B + C = 10",
568.283 - expectTrue(3, 3, 1), expectTrue(2, 4, 2), expectFalse(1, 2, 3),
568.284 -
568.285 - "A*B+C=10",
568.286 - expectTrue(3, 3, 1), expectTrue(2, 4, 2), expectFalse(1, 2, 3),
568.287 -
568.288 - "(A * B) + C = 10",
568.289 - expectTrue(3, 3, 1), expectTrue(2, 4, 2), expectFalse(1, 2, 3),
568.290 -
568.291 - "A + B * C = 10",
568.292 - expectTrue(1, 3, 3), expectTrue(2, 2, 4), expectFalse(1, 2, 3),
568.293 -
568.294 - "A - B * C = 10",
568.295 - expectTrue(16, 2, 3), expectFalse(15, 2, 2),
568.296 -
568.297 - "A + B / C = 10",
568.298 - expectTrue(5, 15, 3), expectFalse(5, 16, 4),
568.299 -
568.300 - "A - B / C = 10",
568.301 - expectTrue(16, 12, 2), expectFalse(15, 10, 3),
568.302 -
568.303 - "A * (B + C) = 10",
568.304 - expectTrue(2, 2, 3), expectFalse(1, 2, 3),
568.305 -
568.306 - "A / (B + C) = 10",
568.307 - expectTrue(70, 4, 3), expectFalse(70, 3, 5),
568.308 -
568.309 - "A * (B - C) = 10",
568.310 - expectTrue(2, 8, 3), expectFalse(2, 3, 8),
568.311 -
568.312 - "A / (B - C) = 10",
568.313 - expectTrue(70, 11, 4), expectFalse(70, 4, 11),
568.314 -
568.315 - "A / B / C = 10",
568.316 - expectTrue(140, 2, 7), expectFalse(100, 5, 5),
568.317 -
568.318 - "A / (B / C) = 10",
568.319 - expectTrue(70, 14, 2), expectFalse(70, 10, 7),
568.320 -
568.321 - // LOGIC
568.322 -
568.323 - "A = B or C = D",
568.324 - expectTrue(1, 1, 2, 3), expectTrue(1, 2, 3, 3), expectTrue(1, 1, 2, 2),
568.325 - expectFalse(1, 2, 3, 4), expectFalse("!", "!!", "?", "??"),
568.326 -
568.327 - "A = B and C = D",
568.328 - expectTrue(1, 1, 2, 2),
568.329 - expectFalse(1, 1, 2, 3), expectFalse(1, 2, 3, 3),
568.330 -
568.331 - "A = 1 and B = 2 and C = 3",
568.332 - expectTrue(1, 2, 3), expectFalse(1, 2, 4),
568.333 -
568.334 - "A = 1 or B = 2 or C = 3",
568.335 - expectTrue(1, 2, 3), expectTrue(1, 0, 0), expectTrue(0, 0, 3),
568.336 - expectFalse(2, 3, 4),
568.337 -
568.338 - // grouped as (a and b) or (c and d)
568.339 - "A = 1 AND B = 2 OR C = 3 AND D = 4",
568.340 - expectTrue(1, 2, 3, 4), expectTrue(1, 2, 1, 2), expectTrue(3, 4, 3, 4),
568.341 - expectFalse(3, 4, 1, 2), expectFalse(1, 1, 1, 1),
568.342 -
568.343 - "(A = 1 AND B = 2) OR (C = 3 AND D = 4)",
568.344 - expectTrue(1, 2, 3, 4), expectTrue(1, 2, 1, 2), expectTrue(3, 4, 3, 4),
568.345 - expectFalse(3, 4, 1, 2), expectFalse(1, 1, 1, 1),
568.346 -
568.347 - "(A = 1 or B = 2) AND (C = 3 or C = 4)",
568.348 - expectTrue(1, 1, 3, 3), expectTrue(2, 2, 4, 4), expectTrue(1, 2, 3, 4),
568.349 - expectFalse(1, 2, 1, 2), expectFalse(3, 4, 3, 4),
568.350 -
568.351 - // LIKE
568.352 -
568.353 - "A like 'b*m'",
568.354 - expectTrue("blim"), expectTrue("bm"),
568.355 - expectFalse(""), expectFalse("blimmo"), expectFalse("mmm"),
568.356 -
568.357 - "A not like 'b*m'",
568.358 - expectFalse("blim"), expectFalse("bm"),
568.359 - expectTrue(""), expectTrue("blimmo"), expectTrue("mmm"),
568.360 -
568.361 - "A like 'b?m'",
568.362 - expectTrue("bim"), expectFalse("blim"),
568.363 -
568.364 - "A like '*can''t*'",
568.365 - expectTrue("can't"),
568.366 - expectTrue("I'm sorry Dave, I'm afraid I can't do that"),
568.367 - expectFalse("cant"), expectFalse("can''t"),
568.368 -
568.369 - "A like '\\**\\*'",
568.370 - expectTrue("*blim*"), expectTrue("**"),
568.371 - expectFalse("blim"), expectFalse("*asdf"), expectFalse("asdf*"),
568.372 -
568.373 - "A LIKE '%*_?'",
568.374 - expectTrue("%blim_?"), expectTrue("%_?"), expectTrue("%blim_!"),
568.375 - expectFalse("blim"), expectFalse("blim_"),
568.376 - expectFalse("_%"), expectFalse("??"), expectFalse(""), expectFalse("?"),
568.377 -
568.378 - Query.toString(
568.379 - Query.initialSubString(Query.attr("A"), Query.value("*?%_"))),
568.380 - expectTrue("*?%_tiddly"), expectTrue("*?%_"),
568.381 - expectFalse("?%_tiddly"), expectFalse("*!%_"), expectFalse("*??_"),
568.382 - expectFalse("*?%!"), expectFalse("*?%!tiddly"),
568.383 -
568.384 - Query.toString(
568.385 - Query.finalSubString(Query.attr("A"), Query.value("*?%_"))),
568.386 - expectTrue("tiddly*?%_"), expectTrue("*?%_"),
568.387 - expectFalse("tiddly?%_"), expectFalse("*!%_"), expectFalse("*??_"),
568.388 - expectFalse("*?%!"), expectFalse("tiddly*?%!"),
568.389 -
568.390 - // BETWEEN
568.391 -
568.392 - "A between B and C",
568.393 - expectTrue(1, 1, 2), expectTrue(2, 1, 2), expectTrue(2, 1, 3),
568.394 - expectFalse(3, 1, 2), expectFalse(0, 1, 2), expectFalse(2, 3, 1),
568.395 - expectTrue(1.0, 0.0, 2.0), expectFalse(2.0, 0.0, 1.0),
568.396 - expectTrue(0.0, 0.0, 0.0), expectTrue(1.0, 0.0, 1.0),
568.397 - expectTrue(1.0, 0.0, Double.POSITIVE_INFINITY),
568.398 - expectFalse(1.0, Double.NEGATIVE_INFINITY, 0.0),
568.399 - expectFalse(false, false, true), expectFalse(true, false, true),
568.400 - expectTrue("jim", "fred", "sheila"), expectFalse("fred", "jim", "sheila"),
568.401 -
568.402 - "A between B and C and 1+2=3",
568.403 - expectTrue(2, 1, 3), expectFalse(2, 3, 1),
568.404 -
568.405 - "A not between B and C",
568.406 - expectTrue(1, 2, 3), expectFalse(2, 1, 3),
568.407 -
568.408 - // IN
568.409 -
568.410 - "A in (1, 2, 3)",
568.411 - expectTrue(1), expectTrue(2), expectTrue(3),
568.412 - expectFalse(0), expectFalse(4),
568.413 -
568.414 - "A in (1)",
568.415 - expectTrue(1), expectFalse(0),
568.416 -
568.417 - "A in (1.2, 3.4)",
568.418 - expectTrue(1.2), expectTrue(3.4), expectFalse(0.0),
568.419 -
568.420 - "A in ('foo', 'bar')",
568.421 - expectTrue("foo"), expectTrue("bar"), expectFalse("baz"),
568.422 -
568.423 - "A in ('foo', 'bar') and 'bl'+'im'='blim'",
568.424 - expectTrue("foo"), expectTrue("bar"), expectFalse("baz"),
568.425 -
568.426 - "A in (B, C, D)", // requires fix for CR 6604768
568.427 - expectTrue(1, 1, 2, 3), expectFalse(1, 2, 3, 4),
568.428 -
568.429 - "A not in (B, C, D)",
568.430 - expectTrue(1, 2, 3, 4), expectFalse(1, 1, 2, 3),
568.431 -
568.432 - // QUOTING
568.433 -
568.434 - "\"LIKE\" = 1 and \"NOT\" = 2 and \"INSTANCEOF\" = 3 and " +
568.435 - "\"TRUE\" = 4 and \"FALSE\" = 5",
568.436 - newTester(
568.437 - new String[] {"LIKE", "NOT", "INSTANCEOF", "TRUE", "FALSE"},
568.438 - new Object[] {1, 2, 3, 4, 5},
568.439 - true),
568.440 - newTester(
568.441 - new String[] {"LIKE", "NOT", "INSTANCEOF", "TRUE", "FALSE"},
568.442 - new Object[] {5, 4, 3, 2, 1},
568.443 - false),
568.444 -
568.445 - "\"\"\"woo\"\"\" = 5",
568.446 - newTester(new String[] {"\"woo\""}, new Object[] {5}, true),
568.447 - newTester(new String[] {"\"woo\""}, new Object[] {4}, false),
568.448 - expectFalse(),
568.449 -
568.450 - // INSTANCEOF
568.451 -
568.452 - "instanceof '" + Tester.class.getName() + "'",
568.453 - expectTrue(),
568.454 -
568.455 - "instanceof '" + String.class.getName() + "'",
568.456 - expectFalse(),
568.457 -
568.458 - // LIKE OBJECTNAME
568.459 -
568.460 - // The test MBean is registered as a:b=c
568.461 - "like 'a:b=c'", expectTrue(),
568.462 - "like 'a:*'", expectTrue(),
568.463 - "like '*:b=c'", expectTrue(),
568.464 - "like 'a:b=*'", expectTrue(),
568.465 - "like 'a:b=?'", expectTrue(),
568.466 - "like 'd:b=c'", expectFalse(),
568.467 - "like 'a:b=??*'", expectFalse(),
568.468 - "like 'a:b=\"can''t\"'", expectFalse(),
568.469 -
568.470 - // QUALIFIED ATTRIBUTE
568.471 -
568.472 - Tester.class.getName() + "#A = 5",
568.473 - expectTrue(5), expectFalse(4),
568.474 -
568.475 - Tester.class.getName() + " # A = 5",
568.476 - expectTrue(5), expectFalse(4),
568.477 -
568.478 - Tester.class.getSuperclass().getName() + "#A = 5",
568.479 - expectFalse(5),
568.480 -
568.481 - DynamicMBean.class.getName() + "#A = 5",
568.482 - expectFalse(5),
568.483 -
568.484 - Tester.class.getName() + "#A = 5",
568.485 - new Tester(new String[] {"A"}, new Object[] {5}, false) {},
568.486 - // note the little {} at the end which means this is a subclass
568.487 - // and therefore QualifiedAttributeValue should return false.
568.488 -
568.489 - MBeanServerDelegate.class.getName() + "#SpecificationName LIKE '*'",
568.490 - new Wrapped(new MBeanServerDelegate(), true),
568.491 - new Tester(new String[] {"SpecificationName"}, new Object[] {"JMX"}, false),
568.492 -
568.493 - // DOTTED ATTRIBUTE
568.494 -
568.495 - "A.canonicalName = '" +
568.496 - MBeanServerDelegate.DELEGATE_NAME.getCanonicalName() + "'",
568.497 - expectTrue(MBeanServerDelegate.DELEGATE_NAME),
568.498 - expectFalse(ObjectName.WILDCARD),
568.499 -
568.500 - "A.class.name = 'java.lang.String'",
568.501 - expectTrue("blim"), expectFalse(95), expectFalse((Object) null),
568.502 -
568.503 - "A.canonicalName like 'JMImpl*:*'",
568.504 - expectTrue(MBeanServerDelegate.DELEGATE_NAME),
568.505 - expectFalse(ObjectName.WILDCARD),
568.506 -
568.507 - "A.true = 'blim'",
568.508 - new Tester(new String[] {"A.true"}, new Object[] {"blim"}, true),
568.509 - new Tester(new String[] {"A.true"}, new Object[] {"blam"}, false),
568.510 -
568.511 - "\"A.true\" = 'blim'",
568.512 - new Tester(new String[] {"A.true"}, new Object[] {"blim"}, true),
568.513 - new Tester(new String[] {"A.true"}, new Object[] {"blam"}, false),
568.514 -
568.515 - MBeanServerDelegate.class.getName() +
568.516 - "#SpecificationName.class.name = 'java.lang.String'",
568.517 - new Wrapped(new MBeanServerDelegate(), true),
568.518 - new Tester(new String[] {"SpecificationName"}, new Object[] {"JMX"}, false),
568.519 -
568.520 - MBeanServerDelegate.class.getName() +
568.521 - " # SpecificationName.class.name = 'java.lang.String'",
568.522 - new Wrapped(new MBeanServerDelegate(), true),
568.523 - new Tester(new String[] {"SpecificationName"}, new Object[] {"JMX"}, false),
568.524 -
568.525 - // CLASS
568.526 -
568.527 - "class = '" + Tester.class.getName() + "'",
568.528 - expectTrue(),
568.529 - new Wrapped(new MBeanServerDelegate(), false),
568.530 -
568.531 - "Class = '" + Tester.class.getName() + "'",
568.532 - expectTrue(),
568.533 - new Wrapped(new MBeanServerDelegate(), false),
568.534 - };
568.535 -
568.536 - private static final String[] incorrectQueries = {
568.537 - "", " ", "25", "()", "(a = b", "a = b)", "a.3 = 5",
568.538 - "a = " + Long.MAX_VALUE + "0",
568.539 - "a = " + Double.MAX_VALUE + "0",
568.540 - "a = " + Double.MIN_VALUE + "0",
568.541 - "a = 12a5", "a = 12e5e5", "a = 12.23.34",
568.542 - "a = 'can't'", "a = 'unterminated", "a = 'asdf''",
568.543 - "a = \"oops", "a = \"oops\"\"",
568.544 - "a like 5", "true or false",
568.545 - "a ! b", "? = 3", "a = @", "a##b",
568.546 - "a between b , c", "a between and c",
568.547 - "a in b, c", "a in 23", "a in (2, 3", "a in (2, 3x)",
568.548 - "a like \"foo\"", "a like b", "a like 23",
568.549 - "like \"foo\"", "like b", "like 23", "like 'a:b'",
568.550 - "5 like 'a'", "'a' like '*'",
568.551 - "a not= b", "a not = b", "a not b", "a not b c",
568.552 - "a = +b", "a = +'b'", "a = +true", "a = -b", "a = -'b'",
568.553 - "a#5 = b", "a#'b' = c",
568.554 - "a instanceof b", "a instanceof 17", "a instanceof",
568.555 - // "a like 'oops\\'", "a like '[oops'",
568.556 - // We don't check the above because Query.match doesn't. If LIKE
568.557 - // rejected bad patterns then there would be some QueryExp values
568.558 - // that could not be converted to a string and back.
568.559 -
568.560 - // Check that -Long.MIN_VALUE is an illegal constant. This is one more
568.561 - // than Long.MAX_VALUE and, like the Java language, we only allow it
568.562 - // if it is the operand of unary minus.
568.563 - "a = " + Long.toString(Long.MIN_VALUE).substring(1),
568.564 - };
568.565 -
568.566 - public static void main(String[] args) throws Exception {
568.567 - int nexti;
568.568 - String failed = null;
568.569 -
568.570 - System.out.println("TESTING CORRECT QUERY STRINGS");
568.571 - for (int i = 0; i < queryTests.length; i = nexti) {
568.572 - for (nexti = i + 1; nexti < queryTests.length; nexti++) {
568.573 - if (queryTests[nexti] instanceof String)
568.574 - break;
568.575 - }
568.576 - if (!(queryTests[i] instanceof String))
568.577 - throw new Exception("Test bug: should be string: " + queryTests[i]);
568.578 -
568.579 - String qs = (String) queryTests[i];
568.580 - System.out.println("Test: " + qs);
568.581 -
568.582 - QueryExp qe = Query.fromString(qs);
568.583 - String qes = Query.toString(qe);
568.584 - System.out.println("...parses to: " + qes);
568.585 - final QueryExp[] queries;
568.586 - if (qes.equals(qs))
568.587 - queries = new QueryExp[] {qe};
568.588 - else {
568.589 - QueryExp qe2 = Query.fromString(qes);
568.590 - String qes2 = Query.toString(qe2);
568.591 - System.out.println("...which parses to: " + qes2);
568.592 - if (qes.equals(qes2))
568.593 - queries = new QueryExp[] {qe};
568.594 - else
568.595 - queries = new QueryExp[] {qe, qe2};
568.596 - }
568.597 -
568.598 - for (int j = i + 1; j < nexti; j++) {
568.599 - Object mbean;
568.600 - if (queryTests[j] instanceof Wrapped)
568.601 - mbean = ((Wrapped) queryTests[j]).mbean();
568.602 - else
568.603 - mbean = queryTests[j];
568.604 - boolean expect = ((ExpectedValue) queryTests[j]).expectedValue();
568.605 - for (QueryExp qet : queries) {
568.606 - boolean actual = runQuery(qet, mbean);
568.607 - boolean ok = (expect == actual);
568.608 - System.out.println(
568.609 - "..." + mbean + " -> " + actual +
568.610 - (ok ? " (OK)" : " ####INCORRECT####"));
568.611 - if (!ok)
568.612 - failed = qs;
568.613 - }
568.614 - }
568.615 - }
568.616 -
568.617 - System.out.println();
568.618 - System.out.println("TESTING INCORRECT QUERY STRINGS");
568.619 - for (String s : incorrectQueries) {
568.620 - try {
568.621 - QueryExp qe = Query.fromString(s);
568.622 - System.out.println("###DID NOT GET ERROR:### \"" + s + "\"");
568.623 - failed = s;
568.624 - } catch (IllegalArgumentException e) {
568.625 - String es = (e.getClass() == IllegalArgumentException.class) ?
568.626 - e.getMessage() : e.toString();
568.627 - System.out.println("OK: exception for \"" + s + "\": " + es);
568.628 - }
568.629 - }
568.630 -
568.631 - if (failed == null)
568.632 - System.out.println("TEST PASSED");
568.633 - else
568.634 - throw new Exception("TEST FAILED: Last failure: " + failed);
568.635 - }
568.636 -
568.637 - private static boolean runQuery(QueryExp qe, Object mbean)
568.638 - throws Exception {
568.639 - MBeanServer mbs = MBeanServerFactory.newMBeanServer();
568.640 - ObjectName name = new ObjectName("a:b=c");
568.641 - mbs.registerMBean(mbean, name);
568.642 - Set<ObjectName> names = mbs.queryNames(new ObjectName("a:*"), qe);
568.643 - if (names.isEmpty())
568.644 - return false;
568.645 - if (names.equals(Collections.singleton(name)))
568.646 - return true;
568.647 - throw new Exception("Unexpected query result set: " + names);
568.648 - }
568.649 -
568.650 - private static interface ExpectedValue {
568.651 - public boolean expectedValue();
568.652 - }
568.653 -
568.654 - private static class Wrapped implements ExpectedValue {
568.655 - private final Object mbean;
568.656 - private final boolean expect;
568.657 -
568.658 - Wrapped(Object mbean, boolean expect) {
568.659 - this.mbean = mbean;
568.660 - this.expect = expect;
568.661 - }
568.662 -
568.663 - Object mbean() {
568.664 - return mbean;
568.665 - }
568.666 -
568.667 - public boolean expectedValue() {
568.668 - return expect;
568.669 - }
568.670 - }
568.671 -
568.672 - private static class Tester implements DynamicMBean, ExpectedValue {
568.673 - private final AttributeList attributes;
568.674 - private final boolean expectedValue;
568.675 -
568.676 - Tester(AttributeList attributes, boolean expectedValue) {
568.677 - this.attributes = attributes;
568.678 - this.expectedValue = expectedValue;
568.679 - }
568.680 -
568.681 - Tester(String[] names, Object[] values, boolean expectedValue) {
568.682 - this(makeAttributeList(names, values), expectedValue);
568.683 - }
568.684 -
568.685 - private static AttributeList makeAttributeList(
568.686 - String[] names, Object[] values) {
568.687 - if (names.length != values.length)
568.688 - throw new Error("Test bug: names and values different length");
568.689 - AttributeList list = new AttributeList();
568.690 - for (int i = 0; i < names.length; i++)
568.691 - list.add(new Attribute(names[i], values[i]));
568.692 - return list;
568.693 - }
568.694 -
568.695 - public Object getAttribute(String attribute)
568.696 - throws AttributeNotFoundException {
568.697 - for (Attribute a : attributes.asList()) {
568.698 - if (a.getName().equals(attribute))
568.699 - return a.getValue();
568.700 - }
568.701 - throw new AttributeNotFoundException(attribute);
568.702 - }
568.703 -
568.704 - public void setAttribute(Attribute attribute) {
568.705 - throw new UnsupportedOperationException();
568.706 - }
568.707 -
568.708 - public AttributeList getAttributes(String[] attributes) {
568.709 - AttributeList list = new AttributeList();
568.710 - for (String attribute : attributes) {
568.711 - try {
568.712 - list.add(new Attribute(attribute, getAttribute(attribute)));
568.713 - } catch (AttributeNotFoundException e) {
568.714 - // OK: ignore, per semantics of getAttributes
568.715 - }
568.716 - }
568.717 - return list;
568.718 - }
568.719 -
568.720 - public AttributeList setAttributes(AttributeList attributes) {
568.721 - throw new UnsupportedOperationException();
568.722 - }
568.723 -
568.724 - public Object invoke(String actionName, Object[] params, String[] signature) {
568.725 - throw new UnsupportedOperationException();
568.726 - }
568.727 -
568.728 - public MBeanInfo getMBeanInfo() {
568.729 - MBeanAttributeInfo mbais[] = new MBeanAttributeInfo[attributes.size()];
568.730 - for (int i = 0; i < mbais.length; i++) {
568.731 - Attribute attr = attributes.asList().get(i);
568.732 - String name = attr.getName();
568.733 - Object value = attr.getValue();
568.734 - String type =
568.735 - ((value == null) ? new Object() : value).getClass().getName();
568.736 - mbais[i] = new MBeanAttributeInfo(
568.737 - name, type, name, true, false, false);
568.738 - }
568.739 - return new MBeanInfo(
568.740 - getClass().getName(), "descr", mbais, null, null, null);
568.741 - }
568.742 -
568.743 - public boolean expectedValue() {
568.744 - return expectedValue;
568.745 - }
568.746 -
568.747 - @Override
568.748 - public String toString() {
568.749 - return attributes.toString();
568.750 - }
568.751 - }
568.752 -
568.753 - // Method rather than field, to avoid circular init dependencies
568.754 - private static String[] abcd() {
568.755 - return new String[] {"A", "B", "C", "D"};
568.756 - }
568.757 -
568.758 - private static String[] onetwo() {
568.759 - return new String[] {"One", "two"};
568.760 - }
568.761 -
568.762 - private static Object expectTrue(Object... attrs) {
568.763 - return newTester(abcd(), attrs, true);
568.764 - }
568.765 -
568.766 - private static Object expectFalse(Object... attrs) {
568.767 - return newTester(abcd(), attrs, false);
568.768 - }
568.769 -
568.770 - private static Object expectTrueOneTwo(Object... attrs) {
568.771 - return newTester(onetwo(), attrs, true);
568.772 - }
568.773 -
568.774 - private static Object expectFalseOneTwo(Object... attrs) {
568.775 - return newTester(onetwo(), attrs, false);
568.776 - }
568.777 -
568.778 - private static Object newTester(String[] names, Object[] attrs, boolean expect) {
568.779 - AttributeList list = new AttributeList();
568.780 - for (int i = 0; i < attrs.length; i++)
568.781 - list.add(new Attribute(names[i], attrs[i]));
568.782 - return new Tester(list, expect);
568.783 - }
568.784 -}
569.1 --- a/test/javax/management/remote/mandatory/connection/CloseServerTest.java Mon Nov 23 10:04:47 2009 +0000
569.2 +++ b/test/javax/management/remote/mandatory/connection/CloseServerTest.java Wed Nov 25 11:08:25 2009 -0800
569.3 @@ -1,5 +1,5 @@
569.4 /*
569.5 - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
569.6 + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
569.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
569.8 *
569.9 * This code is free software; you can redistribute it and/or modify it
569.10 @@ -31,16 +31,11 @@
569.11 * @run main CloseServerTest
569.12 */
569.13
569.14 -import com.sun.jmx.remote.util.EnvHelp;
569.15 import java.net.MalformedURLException;
569.16 +import java.io.IOException;
569.17
569.18 -import java.util.Arrays;
569.19 -import java.util.Collections;
569.20 -import java.util.List;
569.21 -import java.util.Map;
569.22 import javax.management.*;
569.23 import javax.management.remote.*;
569.24 -import javax.management.remote.rmi.RMIConnectorServer;
569.25
569.26 public class CloseServerTest {
569.27 private static final String[] protocols = {"rmi", "iiop", "jmxmp"};
569.28 @@ -136,54 +131,40 @@
569.29
569.30 server.stop();
569.31
569.32 - List<Map<String, String>> envs = Arrays.asList(
569.33 - Collections.singletonMap(
569.34 - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, "false"),
569.35 - Collections.singletonMap(
569.36 - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, "true"));
569.37 + // with a client listener, but close the server first
569.38 + System.out.println(">>> Open, start a server, create a client, add a listener, close the server then the client.");
569.39 + server = JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs);
569.40 + server.start();
569.41
569.42 - for (Map<String, String> env : envs) {
569.43 - System.out.println(
569.44 - ">>>>>>>> " + RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE +
569.45 - " = " + env.get(RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE));
569.46 + addr = server.getAddress();
569.47 + client = JMXConnectorFactory.newJMXConnector(addr, null);
569.48 + client.connect(null);
569.49
569.50 - // with a client listener, but close the server first
569.51 - System.out.println(">>> Open, start a server, create a client, " +
569.52 - "add a listener, close the server then the client.");
569.53 - server = JMXConnectorServerFactory.newJMXConnectorServer(u, env, mbs);
569.54 - server.start();
569.55 + mserver = client.getMBeanServerConnection();
569.56 + mserver.addNotificationListener(delegateName, dummyListener, null, null);
569.57
569.58 - addr = server.getAddress();
569.59 - client = JMXConnectorFactory.newJMXConnector(addr, null);
569.60 - client.connect(null);
569.61 + server.stop();
569.62
569.63 - mserver = client.getMBeanServerConnection();
569.64 - mserver.addNotificationListener(delegateName, dummyListener, null, null);
569.65 + try {
569.66 + client.close();
569.67 + } catch (Exception e) {
569.68 + // ok, it is because the server has been closed.
569.69 + }
569.70
569.71 - server.stop();
569.72 + // with a client listener, but close the client first
569.73 + System.out.println(">>> Open, start a server, create a client, add a listener, close the client then the server.");
569.74 + server = JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs);
569.75 + server.start();
569.76
569.77 - try {
569.78 - client.close();
569.79 - } catch (Exception e) {
569.80 - // ok, it is because the server has been closed.
569.81 - }
569.82 + addr = server.getAddress();
569.83 + client = JMXConnectorFactory.newJMXConnector(addr, null);
569.84 + client.connect(null);
569.85
569.86 - // with a client listener, but close the client first
569.87 - System.out.println(">>> Open, start a server, create a client, " +
569.88 - "add a listener, close the client then the server.");
569.89 - server = JMXConnectorServerFactory.newJMXConnectorServer(u, env, mbs);
569.90 - server.start();
569.91 + mserver = client.getMBeanServerConnection();
569.92 + mserver.addNotificationListener(delegateName, dummyListener, null, null);
569.93
569.94 - addr = server.getAddress();
569.95 - client = JMXConnectorFactory.newJMXConnector(addr, null);
569.96 - client.connect(null);
569.97 -
569.98 - mserver = client.getMBeanServerConnection();
569.99 - mserver.addNotificationListener(delegateName, dummyListener, null, null);
569.100 -
569.101 - client.close();
569.102 - server.stop();
569.103 - }
569.104 + client.close();
569.105 + server.stop();
569.106 } catch (MalformedURLException e) {
569.107 System.out.println(">>> Skipping unsupported URL " + u);
569.108 return true;
570.1 --- a/test/javax/management/remote/mandatory/connection/DeadLockTest.java Mon Nov 23 10:04:47 2009 +0000
570.2 +++ b/test/javax/management/remote/mandatory/connection/DeadLockTest.java Wed Nov 25 11:08:25 2009 -0800
570.3 @@ -1,5 +1,5 @@
570.4 /*
570.5 - * Copyright 2004-2008 Sun Microsystems, Inc. All Rights Reserved.
570.6 + * Copyright 2004 Sun Microsystems, Inc. All Rights Reserved.
570.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
570.8 *
570.9 * This code is free software; you can redistribute it and/or modify it
570.10 @@ -37,7 +37,6 @@
570.11
570.12 import javax.management.*;
570.13 import javax.management.remote.*;
570.14 -import javax.management.remote.rmi.RMIConnectorServer;
570.15
570.16 public class DeadLockTest {
570.17 private static final String[] protocols = {"rmi", "iiop", "jmxmp"};
570.18 @@ -73,9 +72,6 @@
570.19 // disable the client ping
570.20 env.put("jmx.remote.x.client.connection.check.period", "0");
570.21
570.22 - // ensure we are not internally using the Event Service on the server
570.23 - env.put(RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, "false");
570.24 -
570.25 try {
570.26 u = new JMXServiceURL(proto, null, 0);
570.27 server = JMXConnectorServerFactory.newJMXConnectorServer(u, env, mbs);
571.1 --- a/test/javax/management/remote/mandatory/connection/IdleTimeoutTest.java Mon Nov 23 10:04:47 2009 +0000
571.2 +++ b/test/javax/management/remote/mandatory/connection/IdleTimeoutTest.java Wed Nov 25 11:08:25 2009 -0800
571.3 @@ -1,5 +1,5 @@
571.4 /*
571.5 - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
571.6 + * Copyright 2003-2006 Sun Microsystems, Inc. All Rights Reserved.
571.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
571.8 *
571.9 * This code is free software; you can redistribute it and/or modify it
571.10 @@ -50,8 +50,6 @@
571.11 import javax.management.remote.JMXConnectorServerFactory;
571.12 import javax.management.remote.JMXServiceURL;
571.13 import com.sun.jmx.remote.util.EnvHelp;
571.14 -import java.util.Collections;
571.15 -import javax.management.remote.rmi.RMIConnectorServer;
571.16
571.17 public class IdleTimeoutTest {
571.18 public static void main(String[] args) throws Exception {
571.19 @@ -90,13 +88,8 @@
571.20
571.21 private static long getIdleTimeout(MBeanServer mbs, JMXServiceURL url)
571.22 throws Exception {
571.23 - // If the connector server is using the Event Service, then connections
571.24 - // never time out. This is by design.
571.25 - Map<String, String> env =
571.26 - Collections.singletonMap(
571.27 - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, "false");
571.28 JMXConnectorServer server =
571.29 - JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
571.30 + JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
571.31 server.start();
571.32 try {
571.33 url = server.getAddress();
571.34 @@ -171,7 +164,6 @@
571.35
571.36 Map idleMap = new HashMap();
571.37 idleMap.put(EnvHelp.SERVER_CONNECTION_TIMEOUT, new Long(timeout));
571.38 - idleMap.put(RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, "false");
571.39 JMXConnectorServer server =
571.40 JMXConnectorServerFactory.newJMXConnectorServer(url,idleMap,mbs);
571.41
572.1 --- a/test/javax/management/remote/mandatory/connection/RMIExitTest.java Mon Nov 23 10:04:47 2009 +0000
572.2 +++ b/test/javax/management/remote/mandatory/connection/RMIExitTest.java Wed Nov 25 11:08:25 2009 -0800
572.3 @@ -35,8 +35,6 @@
572.4 import java.net.MalformedURLException;
572.5 import java.io.IOException;
572.6
572.7 -import java.util.Collections;
572.8 -import java.util.Map;
572.9 import javax.management.MBeanServerFactory;
572.10 import javax.management.MBeanServer;
572.11 import javax.management.ObjectName;
572.12 @@ -49,7 +47,6 @@
572.13 import javax.management.remote.JMXConnector;
572.14 import javax.management.remote.JMXConnectorServerFactory;
572.15 import javax.management.remote.JMXConnectorFactory;
572.16 -import javax.management.remote.rmi.RMIConnectorServer;
572.17
572.18 /**
572.19 * VM shutdown hook. Test that the hook is called less than 5 secs
572.20 @@ -85,15 +82,12 @@
572.21 public static void main(String[] args) {
572.22 System.out.println("Start test");
572.23 Runtime.getRuntime().addShutdownHook(new TimeChecker());
572.24 - test(false);
572.25 - test(true);
572.26 + test();
572.27 exitStartTime = System.currentTimeMillis();
572.28 System.out.println("End test");
572.29 }
572.30
572.31 - private static void test(boolean eventService) {
572.32 - System.out.println(
572.33 - "---testing with" + (eventService ? "" : "out") + " Event Service");
572.34 + private static void test() {
572.35 try {
572.36 JMXServiceURL u = new JMXServiceURL("rmi", null, 0);
572.37 JMXConnectorServer server;
572.38 @@ -112,11 +106,8 @@
572.39 }
572.40 };
572.41
572.42 - Map<String, String> env = Collections.singletonMap(
572.43 - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE,
572.44 - Boolean.toString(eventService));
572.45 server = JMXConnectorServerFactory.newJMXConnectorServer(u,
572.46 - env,
572.47 + null,
572.48 mbs);
572.49 server.start();
572.50
573.1 --- a/test/javax/management/remote/mandatory/connection/ReconnectTest.java Mon Nov 23 10:04:47 2009 +0000
573.2 +++ b/test/javax/management/remote/mandatory/connection/ReconnectTest.java Wed Nov 25 11:08:25 2009 -0800
573.3 @@ -1,5 +1,5 @@
573.4 /*
573.5 - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
573.6 + * Copyright 2003-2004 Sun Microsystems, Inc. All Rights Reserved.
573.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
573.8 *
573.9 * This code is free software; you can redistribute it and/or modify it
573.10 @@ -33,10 +33,10 @@
573.11
573.12 import java.util.*;
573.13 import java.net.MalformedURLException;
573.14 +import java.io.IOException;
573.15
573.16 import javax.management.*;
573.17 import javax.management.remote.*;
573.18 -import javax.management.remote.rmi.RMIConnectorServer;
573.19
573.20 public class ReconnectTest {
573.21 private static final String[] protocols = {"rmi", "iiop", "jmxmp"};
573.22 @@ -48,7 +48,6 @@
573.23 String timeout = "1000";
573.24 env.put("jmx.remote.x.server.connection.timeout", timeout);
573.25 env.put("jmx.remote.x.client.connection.check.period", timeout);
573.26 - env.put(RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, "false");
573.27 }
573.28
573.29 public static void main(String[] args) throws Exception {
574.1 --- a/test/javax/management/remote/mandatory/connectorServer/CloseConnectionTest.java Mon Nov 23 10:04:47 2009 +0000
574.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
574.3 @@ -1,217 +0,0 @@
574.4 -/*
574.5 - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
574.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
574.7 - *
574.8 - * This code is free software; you can redistribute it and/or modify it
574.9 - * under the terms of the GNU General Public License version 2 only, as
574.10 - * published by the Free Software Foundation.
574.11 - *
574.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
574.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
574.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
574.15 - * version 2 for more details (a copy is included in the LICENSE file that
574.16 - * accompanied this code).
574.17 - *
574.18 - * You should have received a copy of the GNU General Public License version
574.19 - * 2 along with this work; if not, write to the Free Software Foundation,
574.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
574.21 - *
574.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
574.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
574.24 - * have any questions.
574.25 - */
574.26 -
574.27 -
574.28 -/*
574.29 - * @test
574.30 - * @bug 6332907
574.31 - * @summary test the ability for connector server to close individual connections
574.32 - * @author Shanliang JIANG
574.33 - * @run clean CloseConnectionTest
574.34 - * @run build CloseConnectionTest
574.35 - * @run main CloseConnectionTest
574.36 - */
574.37 -import java.io.IOException;
574.38 -import java.util.ArrayList;
574.39 -import java.util.List;
574.40 -import javax.management.MBeanServerFactory;
574.41 -
574.42 -import javax.management.Notification;
574.43 -import javax.management.NotificationListener;
574.44 -import javax.management.remote.JMXConnectionNotification;
574.45 -import javax.management.remote.JMXConnector;
574.46 -import javax.management.remote.JMXConnectorFactory;
574.47 -import javax.management.remote.JMXServiceURL;
574.48 -import javax.management.remote.JMXConnectorServer;
574.49 -import javax.management.remote.JMXConnectorServerFactory;
574.50 -
574.51 -public class CloseConnectionTest {
574.52 -
574.53 - public static void main(String[] args) throws Exception {
574.54 - System.out.println(">>> Test the ability for connector server to close " +
574.55 - "individual connections.");
574.56 -
574.57 - final String[] protos = new String[]{"rmi", "iiop", "jmxmp"};
574.58 - for (String p : protos) {
574.59 - System.out.println("\n>>> Testing the protocol " + p);
574.60 - JMXServiceURL addr = new JMXServiceURL(p, null, 0);
574.61 - System.out.println(">>> Creating a JMXConnectorServer on " + addr);
574.62 - JMXConnectorServer server = null;
574.63 - try {
574.64 - server = JMXConnectorServerFactory.newJMXConnectorServer(addr,
574.65 - null,
574.66 - MBeanServerFactory.createMBeanServer());
574.67 - } catch (Exception e) {
574.68 - System.out.println(">>> Skip the protocol: " + p);
574.69 - continue;
574.70 - }
574.71 -
574.72 - test1(server);
574.73 - test2(server);
574.74 -
574.75 - server.stop();
574.76 - }
574.77 -
574.78 - System.out.println(">>> Bye bye!");
574.79 - }
574.80 -
574.81 - private static void test1(JMXConnectorServer server) throws Exception {
574.82 - try {
574.83 - server.closeConnection("toto");
574.84 - // not started, known id
574.85 - throw new RuntimeException("An IllegalArgumentException is not thrown.");
574.86 - } catch (IllegalStateException e) {
574.87 - System.out.println(">>> Test1: Got expected IllegalStateException: " + e);
574.88 - }
574.89 -
574.90 - server.start();
574.91 - System.out.println(">>>Test1 Started the server on " + server.getAddress());
574.92 -
574.93 - try {
574.94 - server.closeConnection("toto");
574.95 - throw new RuntimeException("An IllegalArgumentException is not thrown.");
574.96 - } catch (IllegalArgumentException e) {
574.97 - System.out.println(">> Test1: Got expected IllegalArgumentException: " + e);
574.98 - }
574.99 -
574.100 - MyListener listener = new MyListener();
574.101 - server.addNotificationListener(listener, null, null);
574.102 -
574.103 - System.out.println(">>> Test1: Connecting a client to the server ...");
574.104 - final JMXConnector conn = JMXConnectorFactory.connect(server.getAddress());
574.105 - conn.getMBeanServerConnection().getDefaultDomain();
574.106 - final String id1 = conn.getConnectionId();
574.107 -
574.108 - listener.wait(JMXConnectionNotification.OPENED, timeout);
574.109 -
574.110 - System.out.println(">>> Test1: Closing the connection: " + conn.getConnectionId());
574.111 - server.closeConnection(id1);
574.112 - listener.wait(JMXConnectionNotification.CLOSED, timeout);
574.113 -
574.114 - System.out.println(">>> Test1: Using again the connector whose connection " +
574.115 - "should be closed by the server, it should reconnect " +
574.116 - "automatically to the server and get a new connection id.");
574.117 - conn.getMBeanServerConnection().getDefaultDomain();
574.118 - final String id2 = conn.getConnectionId();
574.119 - listener.wait(JMXConnectionNotification.OPENED, timeout);
574.120 -
574.121 - if (id1.equals(id2)) {
574.122 - throw new RuntimeException("Failed, the first client connection is not closed.");
574.123 - }
574.124 -
574.125 - System.out.println(">>> Test1: Greate, we get a new connection id " + id2 +
574.126 - ", the first one is closed as expected.");
574.127 -
574.128 - System.out.println(">>> Test1: Closing the client.");
574.129 - conn.close();
574.130 - System.out.println(">>> Test1: Stopping the server.");
574.131 - server.removeNotificationListener(listener);
574.132 - }
574.133 -
574.134 - private static void test2(JMXConnectorServer server) throws Exception {
574.135 - System.out.println(">>> Test2 close a connection before " +
574.136 - "the client can use it...");
574.137 - final Killer killer = new Killer(server);
574.138 - server.addNotificationListener(killer, null, null);
574.139 -
574.140 - System.out.println(">>> Test2 Connecting a client to the server ...");
574.141 - final JMXConnector conn;
574.142 - try {
574.143 - conn = JMXConnectorFactory.connect(server.getAddress());
574.144 - throw new RuntimeException(">>> Failed, do not receive an " +
574.145 - "IOException telling the connection is refused.");
574.146 - } catch (IOException ioe) {
574.147 - System.out.println(">>> Test2 got expected IOException: "+ioe);
574.148 - }
574.149 - }
574.150 -
574.151 - private static class MyListener implements NotificationListener {
574.152 - public void handleNotification(Notification n, Object hb) {
574.153 - if (n instanceof JMXConnectionNotification) {
574.154 - synchronized (received) {
574.155 - received.add((JMXConnectionNotification) n);
574.156 - received.notify();
574.157 - }
574.158 - }
574.159 - }
574.160 -
574.161 - public JMXConnectionNotification wait(String type, long timeout)
574.162 - throws Exception {
574.163 - JMXConnectionNotification waited = null;
574.164 - long toWait = timeout;
574.165 - long deadline = System.currentTimeMillis() + timeout;
574.166 - synchronized (received) {
574.167 - while (waited == null && toWait > 0) {
574.168 - received.wait(toWait);
574.169 - for (JMXConnectionNotification n : received) {
574.170 - if (type.equals(n.getType())) {
574.171 - waited = n;
574.172 - break;
574.173 - }
574.174 - }
574.175 - received.clear();
574.176 - toWait = deadline - System.currentTimeMillis();
574.177 - }
574.178 - }
574.179 -
574.180 - if (waited == null) {
574.181 - throw new RuntimeException("Do not receive expected notification " + type);
574.182 - } else {
574.183 - System.out.println(">>> Received expected notif: "+type+
574.184 - " "+waited.getConnectionId());
574.185 - }
574.186 -
574.187 - return waited;
574.188 - }
574.189 -
574.190 - final List<JMXConnectionNotification> received =
574.191 - new ArrayList<JMXConnectionNotification>();
574.192 - }
574.193 -
574.194 - private static class Killer implements NotificationListener {
574.195 - public Killer(JMXConnectorServer server) {
574.196 - this.server = server;
574.197 - }
574.198 - public void handleNotification(Notification n, Object hb) {
574.199 - if (n instanceof JMXConnectionNotification) {
574.200 - if (JMXConnectionNotification.OPENED.equals(n.getType())) {
574.201 - final JMXConnectionNotification cn =
574.202 - (JMXConnectionNotification)n;
574.203 - try {
574.204 - System.out.println(">>> Killer: close the connection "+
574.205 - cn.getConnectionId());
574.206 - server.closeConnection(cn.getConnectionId());
574.207 - } catch (Exception e) {
574.208 - // impossible?
574.209 - e.printStackTrace();
574.210 - System.exit(1);
574.211 - }
574.212 - }
574.213 - }
574.214 - }
574.215 -
574.216 - private final JMXConnectorServer server;
574.217 - }
574.218 -
574.219 - private static final long timeout = 6000;
574.220 -}
575.1 --- a/test/javax/management/remote/mandatory/connectorServer/ForwarderChainTest.java Mon Nov 23 10:04:47 2009 +0000
575.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
575.3 @@ -1,279 +0,0 @@
575.4 -/*
575.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
575.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
575.7 - *
575.8 - * This code is free software; you can redistribute it and/or modify it
575.9 - * under the terms of the GNU General Public License version 2 only, as
575.10 - * published by the Free Software Foundation.
575.11 - *
575.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
575.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
575.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
575.15 - * version 2 for more details (a copy is included in the LICENSE file that
575.16 - * accompanied this code).
575.17 - *
575.18 - * You should have received a copy of the GNU General Public License version
575.19 - * 2 along with this work; if not, write to the Free Software Foundation,
575.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
575.21 - *
575.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
575.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
575.24 - * have any questions.
575.25 - */
575.26 -
575.27 -import java.util.NoSuchElementException;
575.28 -import java.util.Random;
575.29 -import javax.management.MBeanServer;
575.30 -import javax.management.MBeanServerConnection;
575.31 -import javax.management.MBeanServerFactory;
575.32 -import javax.management.remote.IdentityMBeanServerForwarder;
575.33 -import javax.management.remote.JMXConnector;
575.34 -import javax.management.remote.JMXConnectorFactory;
575.35 -import javax.management.remote.JMXConnectorServer;
575.36 -import javax.management.remote.JMXServiceURL;
575.37 -import javax.management.remote.MBeanServerForwarder;
575.38 -
575.39 -/*
575.40 - * @test
575.41 - * @bug 6218920
575.42 - * @summary Tests manipulation of MBeanServerForwarder chains.
575.43 - * @author Eamonn McManus
575.44 - */
575.45 -import javax.management.remote.rmi.RMIConnectorServer;
575.46 -
575.47 -public class ForwarderChainTest {
575.48 - private static final TestMBeanServerForwarder[] forwarders =
575.49 - new TestMBeanServerForwarder[10];
575.50 - static {
575.51 - for (int i = 0; i < forwarders.length; i++)
575.52 - forwarders[i] = new TestMBeanServerForwarder(i);
575.53 - }
575.54 -
575.55 - private static class TestMBeanServerForwarder
575.56 - extends IdentityMBeanServerForwarder {
575.57 - private final int index;
575.58 - volatile int defaultDomainCount;
575.59 -
575.60 - TestMBeanServerForwarder(int index) {
575.61 - this.index = index;
575.62 - }
575.63 -
575.64 - @Override
575.65 - public String getDefaultDomain() {
575.66 - defaultDomainCount++;
575.67 - return super.getDefaultDomain();
575.68 - }
575.69 -
575.70 - @Override
575.71 - public String toString() {
575.72 - return "forwarders[" + index + "]";
575.73 - }
575.74 - }
575.75 -
575.76 - private static String failure;
575.77 -
575.78 - public static void main(String[] args) throws Exception {
575.79 -
575.80 - System.out.println("===Test with newly created, unattached server===");
575.81 -
575.82 - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///");
575.83 - JMXConnectorServer cs = new RMIConnectorServer(url, null);
575.84 - test(cs, null);
575.85 -
575.86 - System.out.println("===Test with server attached to MBS===");
575.87 - MBeanServer mbs = MBeanServerFactory.newMBeanServer();
575.88 - cs = new RMIConnectorServer(url, null, mbs);
575.89 - test(cs, mbs);
575.90 -
575.91 - System.out.println("===Remove any leftover forwarders===");
575.92 - MBeanServerForwarder systemMBSF = cs.getSystemMBeanServerForwarder();
575.93 - // Real code would just do systemMBSF.setMBeanServer(mbs).
575.94 - while (true) {
575.95 - MBeanServer xmbs = systemMBSF.getMBeanServer();
575.96 - if (!(xmbs instanceof MBeanServerForwarder))
575.97 - break;
575.98 - cs.removeMBeanServerForwarder((MBeanServerForwarder) xmbs);
575.99 - }
575.100 - expectChain(cs, "U", mbs);
575.101 -
575.102 - System.out.println("===Ensure forwarders are called===");
575.103 - cs.setMBeanServerForwarder(forwarders[0]);
575.104 - systemMBSF.setMBeanServer(forwarders[1]);
575.105 - forwarders[1].setMBeanServer(forwarders[0]);
575.106 - expectChain(cs, "1U0", mbs);
575.107 - cs.start();
575.108 - if (forwarders[0].defaultDomainCount != 0 ||
575.109 - forwarders[1].defaultDomainCount != 0) {
575.110 - fail("defaultDomainCount not zero");
575.111 - }
575.112 - JMXServiceURL addr = cs.getAddress();
575.113 - JMXConnector cc = JMXConnectorFactory.connect(addr);
575.114 - MBeanServerConnection mbsc = cc.getMBeanServerConnection();
575.115 - mbsc.getDefaultDomain();
575.116 - cc.close();
575.117 - cs.stop();
575.118 - for (boolean system : new boolean[] {false, true}) {
575.119 - TestMBeanServerForwarder mbsf = system ? forwarders[1] : forwarders[0];
575.120 - if (mbsf.defaultDomainCount != 1) {
575.121 - fail((system ? "System" : "User") + " forwarder called " +
575.122 - mbsf.defaultDomainCount + " times");
575.123 - }
575.124 - }
575.125 -
575.126 - if (failure == null)
575.127 - System.out.println("TEST PASSED");
575.128 - else
575.129 - throw new Exception("TEST FAILED: " + failure);
575.130 - }
575.131 -
575.132 - private static void test(JMXConnectorServer cs, MBeanServer end) {
575.133 - // A newly-created connector server might have system forwarders,
575.134 - // so get rid of those.
575.135 - MBeanServerForwarder systemMBSF = cs.getSystemMBeanServerForwarder();
575.136 - systemMBSF.setMBeanServer(cs.getMBeanServer());
575.137 -
575.138 - expectChain(cs, "U", end);
575.139 -
575.140 - System.out.println("Add a user forwarder");
575.141 - cs.setMBeanServerForwarder(forwarders[0]);
575.142 - expectChain(cs, "U0", end);
575.143 -
575.144 - System.out.println("Add another user forwarder");
575.145 - cs.setMBeanServerForwarder(forwarders[1]);
575.146 - expectChain(cs, "U10", end);
575.147 -
575.148 - System.out.println("Add a system forwarder");
575.149 - forwarders[2].setMBeanServer(systemMBSF.getMBeanServer());
575.150 - systemMBSF.setMBeanServer(forwarders[2]);
575.151 - expectChain(cs, "2U10", end);
575.152 -
575.153 - System.out.println("Add another user forwarder");
575.154 - cs.setMBeanServerForwarder(forwarders[3]);
575.155 - expectChain(cs, "2U310", end);
575.156 -
575.157 - System.out.println("Add another system forwarder");
575.158 - forwarders[4].setMBeanServer(systemMBSF.getMBeanServer());
575.159 - systemMBSF.setMBeanServer(forwarders[4]);
575.160 - expectChain(cs, "42U310", end);
575.161 -
575.162 - System.out.println("Remove the first user forwarder");
575.163 - cs.removeMBeanServerForwarder(forwarders[3]);
575.164 - expectChain(cs, "42U10", end);
575.165 -
575.166 - System.out.println("Remove the last user forwarder");
575.167 - cs.removeMBeanServerForwarder(forwarders[0]);
575.168 - expectChain(cs, "42U1", end);
575.169 -
575.170 - System.out.println("Remove the first system forwarder");
575.171 - cs.removeMBeanServerForwarder(forwarders[4]);
575.172 - expectChain(cs, "2U1", end);
575.173 -
575.174 - System.out.println("Remove the last system forwarder");
575.175 - cs.removeMBeanServerForwarder(forwarders[2]);
575.176 - expectChain(cs, "U1", end);
575.177 -
575.178 - System.out.println("Remove the last forwarder");
575.179 - cs.removeMBeanServerForwarder(forwarders[1]);
575.180 - expectChain(cs, "U", end);
575.181 -
575.182 - System.out.println("---Doing random manipulations---");
575.183 - // In this loop we pick one of the forwarders at random each time.
575.184 - // If it is already in the chain, then we remove it. If it is not
575.185 - // in the chain, then we do one of three things: try to remove it
575.186 - // (expecting an exception); add it to the user chain; or add it
575.187 - // to the system chain.
575.188 - // A subtle point is that if there is no MBeanServer then
575.189 - // cs.setMBeanServerForwarder(mbsf) does not change mbsf.getMBeanServer().
575.190 - // Since we're recycling a random forwarder[i], we explicitly
575.191 - // call mbsf.setMBeanServer(null) in this case.
575.192 - String chain = "U";
575.193 - Random r = new Random();
575.194 - for (int i = 0; i < 50; i++) {
575.195 - int fwdi = r.nextInt(10);
575.196 - MBeanServerForwarder mbsf = forwarders[fwdi];
575.197 - char c = (char) ('0' + fwdi);
575.198 - int ci = chain.indexOf(c);
575.199 - if (ci >= 0) {
575.200 - System.out.println("Remove " + c);
575.201 - cs.removeMBeanServerForwarder(mbsf);
575.202 - chain = chain.substring(0, ci) + chain.substring(ci + 1);
575.203 - } else {
575.204 - switch (r.nextInt(3)) {
575.205 - case 0: { // try to remove it
575.206 - try {
575.207 - System.out.println("Try to remove absent " + c);
575.208 - cs.removeMBeanServerForwarder(mbsf);
575.209 - fail("Remove succeeded but should not have");
575.210 - return;
575.211 - } catch (NoSuchElementException e) {
575.212 - }
575.213 - break;
575.214 - }
575.215 - case 1: { // add it to the user chain
575.216 - System.out.println("Add " + c + " to user chain");
575.217 - if (cs.getMBeanServer() == null)
575.218 - mbsf.setMBeanServer(null);
575.219 - cs.setMBeanServerForwarder(mbsf);
575.220 - int postu = chain.indexOf('U') + 1;
575.221 - chain = chain.substring(0, postu) + c +
575.222 - chain.substring(postu);
575.223 - break;
575.224 - }
575.225 - case 2: { // add it to the system chain
575.226 - System.out.println("Add " + c + " to system chain");
575.227 - mbsf.setMBeanServer(systemMBSF.getMBeanServer());
575.228 - systemMBSF.setMBeanServer(mbsf);
575.229 - chain = c + chain;
575.230 - break;
575.231 - }
575.232 - }
575.233 - }
575.234 - expectChain(cs, chain, end);
575.235 - }
575.236 - }
575.237 -
575.238 - /*
575.239 - * Check that the forwarder chain has the expected contents. The forwarders
575.240 - * are encoded as a string. For example, "12U34" means that the system
575.241 - * chain contains forwarders[1] followed by forwarders[2], and the user
575.242 - * chain contains forwarders[3] followed by forwarders[4]. Since the
575.243 - * user chain is attached to the end of the system chain, another way to
575.244 - * look at this is that the U marks the transition from one to the other.
575.245 - *
575.246 - * After traversing the chains, we should be pointing at "end".
575.247 - */
575.248 - private static void expectChain(
575.249 - JMXConnectorServer cs, String chain, MBeanServer end) {
575.250 - System.out.println("...expected chain: " + chain);
575.251 - MBeanServer curr = cs.getSystemMBeanServerForwarder().getMBeanServer();
575.252 - int i = 0;
575.253 - while (i < chain.length()) {
575.254 - char c = chain.charAt(i);
575.255 - if (c == 'U') {
575.256 - if (cs.getMBeanServer() != curr) {
575.257 - fail("User chain should have started here: " + curr);
575.258 - return;
575.259 - }
575.260 - } else {
575.261 - int fwdi = c - '0';
575.262 - MBeanServerForwarder forwarder = forwarders[fwdi];
575.263 - if (curr != forwarder) {
575.264 - fail("Expected forwarder " + c + " here: " + curr);
575.265 - return;
575.266 - }
575.267 - curr = ((MBeanServerForwarder) curr).getMBeanServer();
575.268 - }
575.269 - i++;
575.270 - }
575.271 - if (curr != end) {
575.272 - fail("End of chain is " + curr + ", should be " + end);
575.273 - return;
575.274 - }
575.275 - System.out.println("...OK");
575.276 - }
575.277 -
575.278 - private static void fail(String msg) {
575.279 - System.out.println("FAILED: " + msg);
575.280 - failure = msg;
575.281 - }
575.282 -}
576.1 --- a/test/javax/management/remote/mandatory/connectorServer/StandardForwardersTest.java Mon Nov 23 10:04:47 2009 +0000
576.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
576.3 @@ -1,193 +0,0 @@
576.4 -/*
576.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
576.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
576.7 - *
576.8 - * This code is free software; you can redistribute it and/or modify it
576.9 - * under the terms of the GNU General Public License version 2 only, as
576.10 - * published by the Free Software Foundation.
576.11 - *
576.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
576.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
576.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
576.15 - * version 2 for more details (a copy is included in the LICENSE file that
576.16 - * accompanied this code).
576.17 - *
576.18 - * You should have received a copy of the GNU General Public License version
576.19 - * 2 along with this work; if not, write to the Free Software Foundation,
576.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
576.21 - *
576.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
576.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
576.24 - * have any questions.
576.25 - */
576.26 -
576.27 -import java.lang.management.ManagementFactory;
576.28 -import java.util.ArrayList;
576.29 -import java.util.HashMap;
576.30 -import java.util.List;
576.31 -import java.util.Map;
576.32 -import javax.management.ClientContext;
576.33 -import javax.management.MBeanServer;
576.34 -import javax.management.event.EventClientDelegate;
576.35 -import javax.management.remote.JMXConnectorServer;
576.36 -
576.37 -/*
576.38 - * @test
576.39 - * @bug 6663757
576.40 - * @summary Tests standard MBeanServerForwarders introduced by connector server
576.41 - * options.
576.42 - * @author Eamonn McManus
576.43 - */
576.44 -import javax.management.remote.JMXConnectorServerFactory;
576.45 -import javax.management.remote.JMXServiceURL;
576.46 -import javax.management.remote.MBeanServerForwarder;
576.47 -
576.48 -public class StandardForwardersTest {
576.49 - private static String failure;
576.50 -
576.51 - private static class Forwarder {
576.52 - private final String attribute;
576.53 - private final boolean defaultEnabled;
576.54 - private final Class<?> expectedClass;
576.55 -
576.56 - public Forwarder(String attribute, boolean defaultEnabled,
576.57 - Class<?> expectedClass) {
576.58 - this.attribute = attribute;
576.59 - this.defaultEnabled = defaultEnabled;
576.60 - this.expectedClass = expectedClass;
576.61 - }
576.62 - }
576.63 -
576.64 - private static enum Status {DISABLED, ENABLED, DEFAULT}
576.65 -
576.66 - public static void main(String[] args) throws Exception {
576.67 - MBeanServer mbs = ManagementFactory.getPlatformMBeanServer();
576.68 -
576.69 - MBeanServerForwarder ctxFwd = ClientContext.newContextForwarder(mbs, null);
576.70 - Forwarder ctx = new Forwarder(
576.71 - JMXConnectorServer.CONTEXT_FORWARDER, true, ctxFwd.getClass());
576.72 -
576.73 - MBeanServerForwarder locFwd =
576.74 - ClientContext.newLocalizeMBeanInfoForwarder(mbs);
576.75 - Forwarder loc = new Forwarder(
576.76 - JMXConnectorServer.LOCALIZE_MBEAN_INFO_FORWARDER, false,
576.77 - locFwd.getClass());
576.78 -
576.79 - MBeanServerForwarder ecdFwd =
576.80 - EventClientDelegate.newForwarder(mbs, null);
576.81 - Forwarder ecd = new Forwarder(
576.82 - JMXConnectorServer.EVENT_CLIENT_DELEGATE_FORWARDER, true,
576.83 - ecdFwd.getClass());
576.84 -
576.85 - Forwarder[] forwarders = {ctx, loc, ecd};
576.86 -
576.87 - // Now go through every combination of forwarders. Each forwarder
576.88 - // may be explicitly enabled, explicitly disabled, or left to its
576.89 - // default value.
576.90 - int nStatus = Status.values().length;
576.91 - int limit = (int) Math.pow(nStatus, forwarders.length);
576.92 - for (int i = 0; i < limit; i++) {
576.93 - Status[] status = new Status[forwarders.length];
576.94 - int ii = i;
576.95 - for (int j = 0; j < status.length; j++) {
576.96 - status[j] = Status.values()[ii % nStatus];
576.97 - ii /= nStatus;
576.98 - }
576.99 - Map<String, String> env = new HashMap<String, String>();
576.100 - String test = "";
576.101 - for (int j = 0; j < status.length; j++) {
576.102 - if (!test.equals(""))
576.103 - test += "; ";
576.104 - test += forwarders[j].attribute;
576.105 - switch (status[j]) {
576.106 - case DISABLED:
576.107 - test += "=false";
576.108 - env.put(forwarders[j].attribute, "false");
576.109 - break;
576.110 - case ENABLED:
576.111 - test += "=true";
576.112 - env.put(forwarders[j].attribute, "true");
576.113 - break;
576.114 - case DEFAULT:
576.115 - test += "=default(" + forwarders[j].defaultEnabled + ")";
576.116 - break;
576.117 - }
576.118 - }
576.119 - boolean consistent = isConsistent(env);
576.120 - test += "; (" + (consistent ? "" : "in") + "consistent)";
576.121 - System.out.println(test);
576.122 - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///");
576.123 - try {
576.124 - JMXConnectorServer cs =
576.125 - JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
576.126 - if (!consistent) {
576.127 - fail("Inconsistent attributes should have been rejected " +
576.128 - "but were not");
576.129 - }
576.130 - checkForwarders(cs, forwarders, status);
576.131 - } catch (IllegalArgumentException e) {
576.132 - if (consistent) {
576.133 - fail("Consistent attributes provoked IllegalArgumentException");
576.134 - e.printStackTrace(System.out);
576.135 - }
576.136 - }
576.137 - }
576.138 -
576.139 - if (failure == null)
576.140 - System.out.println("TEST PASSED");
576.141 - else
576.142 - throw new Exception(failure);
576.143 - }
576.144 -
576.145 - // Check that the classes of the forwarders in the system chain correspond
576.146 - // to what we expect given the options we have passed. This check is a bit
576.147 - // superficial in the sense that a forwarder might be for example a
576.148 - // SingleMBeanForwarderHandler but that doesn't prove that it is the
576.149 - // right Single MBean. Nevertheless the test should expose any severe
576.150 - // wrongness.
576.151 - //
576.152 - // The check here makes some assumptions that could become untrue in the
576.153 - // future. First, it assumes that the forwarders that are added have
576.154 - // exactly the classes that are in the Forwarder[] array. So for example
576.155 - // the forwarder for CONTEXT_FORWARDER must be of the same class as an
576.156 - // explicit call to ClientContext.newContextForwarder. The spec doesn't
576.157 - // require that - it only requires that the forwarder have the same
576.158 - // behaviour. The second assumption is that the connector server doesn't
576.159 - // add any forwarders of its own into the system chain, and again the spec
576.160 - // doesn't disallow that.
576.161 - private static void checkForwarders(
576.162 - JMXConnectorServer cs, Forwarder[] forwarders, Status[] status) {
576.163 - List<Class<?>> expectedClasses = new ArrayList<Class<?>>();
576.164 - for (int i = 0; i < forwarders.length; i++) {
576.165 - if (status[i] == Status.ENABLED ||
576.166 - (status[i] == Status.DEFAULT && forwarders[i].defaultEnabled))
576.167 - expectedClasses.add(forwarders[i].expectedClass);
576.168 - }
576.169 - MBeanServer stop = cs.getMBeanServer();
576.170 - List<Class<?>> foundClasses = new ArrayList<Class<?>>();
576.171 - for (MBeanServer mbs = cs.getSystemMBeanServerForwarder().getMBeanServer();
576.172 - mbs != stop;
576.173 - mbs = ((MBeanServerForwarder) mbs).getMBeanServer()) {
576.174 - foundClasses.add(mbs.getClass());
576.175 - }
576.176 - if (!expectedClasses.equals(foundClasses)) {
576.177 - fail("Incorrect forwarder chain: expected " + expectedClasses +
576.178 - "; found " + foundClasses);
576.179 - }
576.180 - }
576.181 -
576.182 - // env is consistent if either (a) localizer is not enabled or (b)
576.183 - // localizer is enabled and context is enabled.
576.184 - private static boolean isConsistent(Map<String, String> env) {
576.185 - String ctxS = env.get(JMXConnectorServer.CONTEXT_FORWARDER);
576.186 - boolean ctx = (ctxS == null) ? true : Boolean.parseBoolean(ctxS);
576.187 - String locS = env.get(JMXConnectorServer.LOCALIZE_MBEAN_INFO_FORWARDER);
576.188 - boolean loc = (locS == null) ? false : Boolean.parseBoolean(locS);
576.189 - return !loc || ctx;
576.190 - }
576.191 -
576.192 - private static void fail(String why) {
576.193 - System.out.println("FAILED: " + why);
576.194 - failure = why;
576.195 - }
576.196 -}
577.1 --- a/test/javax/management/remote/mandatory/loading/MissingClassTest.java Mon Nov 23 10:04:47 2009 +0000
577.2 +++ b/test/javax/management/remote/mandatory/loading/MissingClassTest.java Wed Nov 25 11:08:25 2009 -0800
577.3 @@ -124,16 +124,7 @@
577.4 }
577.5
577.6 private static boolean test(String proto) throws Exception {
577.7 - boolean ok = true;
577.8 - for (boolean eventService : new boolean[] {false, true})
577.9 - ok &= test(proto, eventService);
577.10 - return ok;
577.11 - }
577.12 -
577.13 - private static boolean test(String proto, boolean eventService)
577.14 - throws Exception {
577.15 - System.out.println("Testing for proto " + proto + " with" +
577.16 - (eventService ? "" : "out") + " Event Service");
577.17 + System.out.println("Testing for proto " + proto);
577.18
577.19 boolean ok = true;
577.20
577.21 @@ -145,8 +136,6 @@
577.22 Map serverMap = new HashMap();
577.23 serverMap.put(JMXConnectorServerFactory.DEFAULT_CLASS_LOADER,
577.24 serverLoader);
577.25 - serverMap.put(RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE,
577.26 - Boolean.toString(eventService));
577.27
577.28 // make sure no auto-close at server side
577.29 serverMap.put("jmx.remote.x.server.connection.timeout", "888888888");
578.1 --- a/test/javax/management/remote/mandatory/notif/AddRemoveTest.java Mon Nov 23 10:04:47 2009 +0000
578.2 +++ b/test/javax/management/remote/mandatory/notif/AddRemoveTest.java Wed Nov 25 11:08:25 2009 -0800
578.3 @@ -1,5 +1,5 @@
578.4 /*
578.5 - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
578.6 + * Copyright 2003 Sun Microsystems, Inc. All Rights Reserved.
578.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
578.8 *
578.9 * This code is free software; you can redistribute it and/or modify it
578.10 @@ -33,12 +33,10 @@
578.11 */
578.12
578.13 import java.net.MalformedURLException;
578.14 +import java.io.IOException;
578.15
578.16 -import java.util.Collections;
578.17 -import java.util.Map;
578.18 import javax.management.*;
578.19 import javax.management.remote.*;
578.20 -import javax.management.remote.rmi.RMIConnectorServer;
578.21
578.22 public class AddRemoveTest {
578.23 private static final String[] protocols = {"rmi", "iiop", "jmxmp"};
578.24 @@ -71,16 +69,9 @@
578.25 }
578.26 }
578.27
578.28 - private static boolean test(String proto) throws Exception {
578.29 - boolean ok = test(proto, false);
578.30 - ok &= test(proto, true);
578.31 - return ok;
578.32 - }
578.33 -
578.34 - private static boolean test(String proto, boolean eventService)
578.35 + private static boolean test(String proto)
578.36 throws Exception {
578.37 - System.out.println(">>> Test for protocol " + proto + " with" +
578.38 - (eventService ? "" : "out") + " event service");
578.39 + System.out.println(">>> Test for protocol " + proto);
578.40 JMXServiceURL u = new JMXServiceURL(proto, null, 0);
578.41 JMXConnectorServer server;
578.42 JMXServiceURL addr;
578.43 @@ -98,10 +89,7 @@
578.44
578.45 try {
578.46 // with a client listener, but close the server first
578.47 - Map<String, String> env = Collections.singletonMap(
578.48 - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE,
578.49 - Boolean.toString(eventService));
578.50 - server = JMXConnectorServerFactory.newJMXConnectorServer(u, env, mbs);
578.51 + server = JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs);
578.52 server.start();
578.53
578.54 addr = server.getAddress();
579.1 --- a/test/javax/management/remote/mandatory/notif/DiffHBTest.java Mon Nov 23 10:04:47 2009 +0000
579.2 +++ b/test/javax/management/remote/mandatory/notif/DiffHBTest.java Wed Nov 25 11:08:25 2009 -0800
579.3 @@ -32,11 +32,8 @@
579.4 */
579.5
579.6
579.7 -import java.util.Collections;
579.8 -import java.util.Map;
579.9 import javax.management.*;
579.10 import javax.management.remote.*;
579.11 -import javax.management.remote.rmi.RMIConnectorServer;
579.12
579.13 /**
579.14 * This test registeres an unique listener with two different handbacks,
579.15 @@ -80,33 +77,14 @@
579.16 }
579.17
579.18 private static String test(String proto) throws Exception {
579.19 - String ret = null;
579.20 - for (boolean eventService : new boolean[] {false, true}) {
579.21 - String s = test(proto, eventService);
579.22 - if (s != null) {
579.23 - if (ret == null)
579.24 - ret = s;
579.25 - else
579.26 - ret = ret + "; " + s;
579.27 - }
579.28 - }
579.29 - return ret;
579.30 - }
579.31 -
579.32 - private static String test(String proto, boolean eventService)
579.33 - throws Exception {
579.34 - System.out.println(">>> Test for protocol " + proto + " with" +
579.35 - (eventService ? "" : "out") + " event service");
579.36 + System.out.println(">>> Test for protocol " + proto);
579.37 JMXServiceURL u = new JMXServiceURL(proto, null, 0);
579.38 JMXConnectorServer server;
579.39 JMXConnector client;
579.40
579.41 try {
579.42 - Map<String, String> env = Collections.singletonMap(
579.43 - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE,
579.44 - Boolean.toString(eventService));
579.45 server =
579.46 - JMXConnectorServerFactory.newJMXConnectorServer(u, env, mbs);
579.47 + JMXConnectorServerFactory.newJMXConnectorServer(u, null, mbs);
579.48 server.start();
579.49 JMXServiceURL addr = server.getAddress();
579.50 client = JMXConnectorFactory.connect(addr, null);
580.1 --- a/test/javax/management/remote/mandatory/notif/EmptyDomainNotificationTest.java Mon Nov 23 10:04:47 2009 +0000
580.2 +++ b/test/javax/management/remote/mandatory/notif/EmptyDomainNotificationTest.java Wed Nov 25 11:08:25 2009 -0800
580.3 @@ -1,5 +1,5 @@
580.4 /*
580.5 - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
580.6 + * Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
580.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
580.8 *
580.9 * This code is free software; you can redistribute it and/or modify it
580.10 @@ -29,12 +29,11 @@
580.11 * @author Shanliang JIANG
580.12 * @run clean EmptyDomainNotificationTest
580.13 * @run build EmptyDomainNotificationTest
580.14 - * @run main EmptyDomainNotificationTest classic
580.15 - * @run main EmptyDomainNotificationTest event
580.16 + * @run main EmptyDomainNotificationTest
580.17 */
580.18
580.19 -import java.util.Collections;
580.20 -import java.util.Map;
580.21 +import java.util.ArrayList;
580.22 +import java.util.List;
580.23 import javax.management.MBeanServer;
580.24 import javax.management.MBeanServerConnection;
580.25 import javax.management.MBeanServerFactory;
580.26 @@ -47,7 +46,6 @@
580.27 import javax.management.remote.JMXConnectorServer;
580.28 import javax.management.remote.JMXConnectorServerFactory;
580.29 import javax.management.remote.JMXServiceURL;
580.30 -import javax.management.remote.rmi.RMIConnectorServer;
580.31
580.32 public class EmptyDomainNotificationTest {
580.33
580.34 @@ -82,25 +80,11 @@
580.35
580.36 public static void main(String[] args) throws Exception {
580.37
580.38 - String type = args[0];
580.39 - boolean eventService;
580.40 - if (type.equals("classic"))
580.41 - eventService = false;
580.42 - else if (type.equals("event"))
580.43 - eventService = true;
580.44 - else
580.45 - throw new IllegalArgumentException(type);
580.46 -
580.47 final MBeanServer mbs = MBeanServerFactory.createMBeanServer();
580.48
580.49 final JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
580.50
580.51 - Map<String, String> env = Collections.singletonMap(
580.52 - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE,
580.53 - Boolean.toString(eventService));
580.54 -
580.55 - JMXConnectorServer server =
580.56 - JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
580.57 + JMXConnectorServer server = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
580.58 server.start();
580.59
580.60 JMXConnector client = JMXConnectorFactory.connect(server.getAddress(), null);
581.1 --- a/test/javax/management/remote/mandatory/notif/ListenerScaleTest.java Mon Nov 23 10:04:47 2009 +0000
581.2 +++ b/test/javax/management/remote/mandatory/notif/ListenerScaleTest.java Wed Nov 25 11:08:25 2009 -0800
581.3 @@ -51,8 +51,6 @@
581.4 * been compiled by the second.
581.5 */
581.6
581.7 -import java.util.Collections;
581.8 -import java.util.Map;
581.9 import java.util.concurrent.Semaphore;
581.10 import javax.management.MBeanServer;
581.11 import javax.management.MBeanServerConnection;
581.12 @@ -67,7 +65,6 @@
581.13 import javax.management.remote.JMXConnectorServer;
581.14 import javax.management.remote.JMXConnectorServerFactory;
581.15 import javax.management.remote.JMXServiceURL;
581.16 -import javax.management.remote.rmi.RMIConnectorServer;
581.17
581.18 public class ListenerScaleTest {
581.19 private static final int WARMUP_WITH_ONE_MBEAN = 1000;
581.20 @@ -128,20 +125,12 @@
581.21 };
581.22
581.23 public static void main(String[] args) throws Exception {
581.24 - test(false);
581.25 - test(true);
581.26 - }
581.27 -
581.28 - private static void test(boolean eventService) throws Exception {
581.29 MBeanServer mbs = MBeanServerFactory.newMBeanServer();
581.30 Sender sender = new Sender();
581.31 mbs.registerMBean(sender, testObjectName);
581.32 JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://");
581.33 - Map<String, String> env = Collections.singletonMap(
581.34 - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE,
581.35 - Boolean.toString(eventService));
581.36 JMXConnectorServer cs =
581.37 - JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
581.38 + JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
581.39 cs.start();
581.40 JMXServiceURL addr = cs.getAddress();
581.41 JMXConnector cc = JMXConnectorFactory.connect(addr);
582.1 --- a/test/javax/management/remote/mandatory/notif/NotifBufferSizePropertyNameTest.java Mon Nov 23 10:04:47 2009 +0000
582.2 +++ b/test/javax/management/remote/mandatory/notif/NotifBufferSizePropertyNameTest.java Wed Nov 25 11:08:25 2009 -0800
582.3 @@ -1,5 +1,5 @@
582.4 /*
582.5 - * Copyright 2004-2008 Sun Microsystems, Inc. All Rights Reserved.
582.6 + * Copyright 2004-2005 Sun Microsystems, Inc. All Rights Reserved.
582.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
582.8 *
582.9 * This code is free software; you can redistribute it and/or modify it
582.10 @@ -31,11 +31,11 @@
582.11 * @run main NotifBufferSizePropertyNameTest
582.12 */
582.13
582.14 +import java.io.IOException;
582.15 import java.util.*;
582.16
582.17 import javax.management.*;
582.18 import javax.management.remote.*;
582.19 -import javax.management.remote.rmi.RMIConnectorServer;
582.20
582.21 /**
582.22 * This class tests also the size of a server notification buffer.
582.23 @@ -88,9 +88,6 @@
582.24 private static void test(Map env) throws Exception {
582.25 final MBeanServer mbs = MBeanServerFactory.newMBeanServer();
582.26
582.27 - env = new HashMap((env == null) ? Collections.emptyMap() : env);
582.28 - env.put(RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, "false");
582.29 -
582.30 mbs.registerMBean(new NotificationEmitter(), oname);
582.31 JMXConnectorServer server = JMXConnectorServerFactory.newJMXConnectorServer(
582.32 url,
583.1 --- a/test/javax/management/remote/mandatory/notif/NotifReconnectDeadlockTest.java Mon Nov 23 10:04:47 2009 +0000
583.2 +++ b/test/javax/management/remote/mandatory/notif/NotifReconnectDeadlockTest.java Wed Nov 25 11:08:25 2009 -0800
583.3 @@ -45,7 +45,6 @@
583.4 import javax.management.remote.JMXConnectorServer;
583.5 import javax.management.remote.JMXConnectorServerFactory;
583.6 import javax.management.remote.JMXServiceURL;
583.7 -import javax.management.remote.rmi.RMIConnectorServer;
583.8
583.9 /**
583.10 * "This test checks for a bug whereby reconnection did not work if (a) it was
583.11 @@ -74,7 +73,6 @@
583.12 Map env = new HashMap(2);
583.13 env.put("jmx.remote.x.server.connection.timeout", new Long(serverTimeout));
583.14 env.put("jmx.remote.x.client.connection.check.period", new Long(Long.MAX_VALUE));
583.15 - env.put(RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, "false");
583.16
583.17 final MBeanServer mbs = MBeanServerFactory.newMBeanServer();
583.18
584.1 --- a/test/javax/management/remote/mandatory/notif/NotificationBufferCreationTest.java Mon Nov 23 10:04:47 2009 +0000
584.2 +++ b/test/javax/management/remote/mandatory/notif/NotificationBufferCreationTest.java Wed Nov 25 11:08:25 2009 -0800
584.3 @@ -1,5 +1,5 @@
584.4 /*
584.5 - * Copyright 2003-2008 Sun Microsystems, Inc. All Rights Reserved.
584.6 + * Copyright 2003-2007 Sun Microsystems, Inc. All Rights Reserved.
584.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
584.8 *
584.9 * This code is free software; you can redistribute it and/or modify it
584.10 @@ -32,8 +32,6 @@
584.11 */
584.12 import java.net.MalformedURLException;
584.13
584.14 -import java.util.Collections;
584.15 -import java.util.Map;
584.16 import javax.management.MBeanServerFactory;
584.17 import javax.management.MBeanServer;
584.18 import javax.management.MBeanServerConnection;
584.19 @@ -46,7 +44,6 @@
584.20 import javax.management.remote.JMXConnectorServer;
584.21 import javax.management.remote.JMXConnectorServerFactory;
584.22 import javax.management.remote.JMXServiceURL;
584.23 -import javax.management.remote.rmi.RMIConnectorServer;
584.24
584.25 public class NotificationBufferCreationTest {
584.26 private static final MBeanServer mbs =
584.27 @@ -89,8 +86,6 @@
584.28 JMXServiceURL u = null;
584.29 try {
584.30 u = new JMXServiceURL(protocol, null, 0);
584.31 - Map<String, String> env = Collections.singletonMap(
584.32 - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, "false");
584.33 server =
584.34 JMXConnectorServerFactory.newJMXConnectorServer(u,
584.35 null,
585.1 --- a/test/javax/management/remote/mandatory/notif/NotificationBufferDeadlockTest.java Mon Nov 23 10:04:47 2009 +0000
585.2 +++ b/test/javax/management/remote/mandatory/notif/NotificationBufferDeadlockTest.java Wed Nov 25 11:08:25 2009 -0800
585.3 @@ -1,5 +1,5 @@
585.4 /*
585.5 - * Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
585.6 + * Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
585.7 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
585.8 *
585.9 * This code is free software; you can redistribute it and/or modify it
585.10 @@ -35,9 +35,7 @@
585.11 import java.lang.reflect.Method;
585.12 import java.lang.reflect.Proxy;
585.13 import java.net.MalformedURLException;
585.14 -import java.util.Collections;
585.15 import java.util.List;
585.16 -import java.util.Map;
585.17 import java.util.Set;
585.18 import java.util.Vector;
585.19 import javax.management.*;
585.20 @@ -90,7 +88,6 @@
585.21 * If the logic for adding the notification buffer's listener is incorrect
585.22 * we could remove zero or two notifications from an MBean.
585.23 */
585.24 -import javax.management.remote.rmi.RMIConnectorServer;
585.25 public class NotificationBufferDeadlockTest {
585.26 public static void main(String[] args) throws Exception {
585.27 System.out.println("Check no deadlock if notif sent while initial " +
585.28 @@ -112,13 +109,7 @@
585.29 }
585.30
585.31 private static void test(String proto) throws Exception {
585.32 - test(proto, false);
585.33 - test(proto, true);
585.34 - }
585.35 -
585.36 - private static void test(String proto, boolean eventService) throws Exception {
585.37 - System.out.println("Testing protocol " + proto + " with" +
585.38 - (eventService ? "" : "out") + " event service");
585.39 + System.out.println("Testing protocol " + proto);
585.40 MBeanServer mbs = MBeanServerFactory.newMBeanServer();
585.41 ObjectName testName = newName();
585.42 DeadlockTest test = new DeadlockTest();
585.43 @@ -126,11 +117,8 @@
585.44 JMXServiceURL url = new JMXServiceURL("service:jmx:" + proto + ":///");
585.45 JMXConnectorServer cs;
585.46 try {
585.47 - Map<String, String> env = Collections.singletonMap(
585.48 - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE,
585.49 - Boolean.toString(eventService));
585.50 cs =
585.51 - JMXConnectorServerFactory.newJMXConnectorServer(url, env, mbs);
585.52 + JMXConnectorServerFactory.newJMXConnectorServer(url, null, mbs);
585.53 } catch (MalformedURLException e) {
585.54 System.out.println("...protocol not supported, ignoring");
585.55 return;
586.1 --- a/test/javax/management/remote/mandatory/notif/NotificationEmissionTest.java Mon Nov 23 10:04:47 2009 +0000
586.2 +++ b/test/javax/management/remote/mandatory/notif/NotificationEmissionTest.java Wed Nov 25 11:08:25 2009 -0800
586.3 @@ -29,16 +29,11 @@
586.4 * @author Luis-Miguel Alventosa
586.5 * @run clean NotificationEmissionTest
586.6 * @run build NotificationEmissionTest
586.7 - * @run main NotificationEmissionTest 1 Classic
586.8 - * @run main NotificationEmissionTest 2 Classic
586.9 - * @run main NotificationEmissionTest 3 Classic
586.10 - * @run main NotificationEmissionTest 4 Classic
586.11 - * @run main NotificationEmissionTest 5 Classic
586.12 - * @run main NotificationEmissionTest 1 EventService
586.13 - * @run main NotificationEmissionTest 2 EventService
586.14 - * @run main NotificationEmissionTest 3 EventService
586.15 - * @run main NotificationEmissionTest 4 EventService
586.16 - * @run main NotificationEmissionTest 5 EventService
586.17 + * @run main NotificationEmissionTest 1
586.18 + * @run main NotificationEmissionTest 2
586.19 + * @run main NotificationEmissionTest 3
586.20 + * @run main NotificationEmissionTest 4
586.21 + * @run main NotificationEmissionTest 5
586.22 */
586.23
586.24 import java.io.File;
586.25 @@ -61,15 +56,9 @@
586.26 import javax.management.remote.JMXConnectorServerFactory;
586.27 import javax.management.remote.JMXPrincipal;
586.28 import javax.management.remote.JMXServiceURL;
586.29 -import javax.management.remote.rmi.RMIConnectorServer;
586.30 import javax.security.auth.Subject;
586.31
586.32 public class NotificationEmissionTest {
586.33 - private final boolean eventService;
586.34 -
586.35 - public NotificationEmissionTest(boolean eventService) {
586.36 - this.eventService = eventService;
586.37 - }
586.38
586.39 public class CustomJMXAuthenticator implements JMXAuthenticator {
586.40 public Subject authenticate(Object credentials) {
586.41 @@ -228,13 +217,8 @@
586.42 //
586.43 final Map<String,Object> env = new HashMap<String,Object>();
586.44 env.put("jmx.remote.authenticator", new CustomJMXAuthenticator());
586.45 - env.put(RMIConnectorServer.EVENT_CLIENT_DELEGATE_FORWARDER,
586.46 - Boolean.toString(eventService));
586.47 - if (prop) {
586.48 - echo("Setting jmx.remote.x.check.notification.emission to " +
586.49 - propValue);
586.50 + if (prop)
586.51 env.put("jmx.remote.x.check.notification.emission", propValue);
586.52 - }
586.53
586.54 // Create the JMXServiceURL
586.55 //
586.56 @@ -302,14 +286,11 @@
586.57 // If the check is effective and we're using policy.negative,
586.58 // then we should see the two notifs sent by nb2 (of which one
586.59 // has a getSource() that is nb3), but not the notif sent by nb1.
586.60 - // Otherwise we should see all three notifs. If we're using the
586.61 - // Event Service with a Security Manager then the logic to
586.62 - // reapply the addNL permission test for every notification is
586.63 - // always enabled, regardless of the value of
586.64 - // jmx.remote.x.check.notification.emission. Otherwise, the
586.65 - // test is only applied if that property is explicitly true.
586.66 + // Otherwise we should see all three notifs. The check is only
586.67 + // effective if the property jmx.remote.x.check.notification.emission
586.68 + // is explicitly true and there is a security manager.
586.69 int expectedNotifs =
586.70 - ((prop || eventService) && sm && !policyPositive) ? 2 : 3;
586.71 + (prop && sm && !policyPositive) ? 2 : 3;
586.72
586.73 // Wait for notifications to be emitted
586.74 //
586.75 @@ -324,15 +305,14 @@
586.76 mbsc.removeNotificationListener(nb2, li);
586.77
586.78 int result = 0;
586.79 - List<ObjectName> sources = new ArrayList();
586.80 + List<ObjectName> sources = new ArrayList<ObjectName>();
586.81 sources.add(nb1);
586.82 sources.add(nb2);
586.83 sources.add(nb3);
586.84
586.85 result = checkNotifs(expectedNotifs, li.notifs, sources);
586.86 if (result > 0) {
586.87 - echo("...SecurityManager=" + sm + "; policy=" + policyPositive +
586.88 - "; eventService=" + eventService);
586.89 + echo("...SecurityManager=" + sm + "; policy=" + policyPositive);
586.90 return result;
586.91 }
586.92 } finally {
586.93 @@ -362,18 +342,9 @@
586.94 public static void main(String[] args) throws Exception {
586.95
586.96 echo("\n--- Check the emission of notifications " +
586.97 - "when a Security Manager is installed [" +
586.98 - args[1] + "] ---");
586.99 + "when a Security Manager is installed");
586.100
586.101 - boolean eventService;
586.102 - if (args[1].equals("Classic"))
586.103 - eventService = false;
586.104 - else if (args[1].equals("EventService"))
586.105 - eventService = true;
586.106 - else
586.107 - throw new IllegalArgumentException(args[1]);
586.108 -
586.109 - NotificationEmissionTest net = new NotificationEmissionTest(eventService);
586.110 + NotificationEmissionTest net = new NotificationEmissionTest();
586.111
586.112 int error = 0;
586.113
587.1 --- a/test/javax/management/remote/mandatory/notif/RMINotifTest.java Mon Nov 23 10:04:47 2009 +0000
587.2 +++ b/test/javax/management/remote/mandatory/notif/RMINotifTest.java Wed Nov 25 11:08:25 2009 -0800
587.3 @@ -25,10 +25,11 @@
587.4 * @test
587.5 * @bug 7654321
587.6 * @summary Tests to receive notifications for opened and closed connections
587.7 +ions
587.8 * @author sjiang
587.9 * @run clean RMINotifTest
587.10 * @run build RMINotifTest
587.11 - * @run main RMINotifTest classic
587.12 + * @run main RMINotifTest
587.13 * @run main RMINotifTest event
587.14 */
587.15
587.16 @@ -38,8 +39,6 @@
587.17 import java.rmi.RemoteException;
587.18 import java.rmi.registry.LocateRegistry;
587.19 import java.rmi.registry.Registry;
587.20 -import java.util.Collections;
587.21 -import java.util.Map;
587.22 import java.util.Random;
587.23 import javax.management.MBeanNotificationInfo;
587.24 import javax.management.MBeanServer;
587.25 @@ -56,19 +55,10 @@
587.26 import javax.management.remote.JMXConnectorServer;
587.27 import javax.management.remote.JMXConnectorServerFactory;
587.28 import javax.management.remote.JMXServiceURL;
587.29 -import javax.management.remote.rmi.RMIConnectorServer;
587.30
587.31 public class RMINotifTest {
587.32
587.33 public static void main(String[] args) {
587.34 - String eventService;
587.35 - if (args[0].equals("classic"))
587.36 - eventService = "false";
587.37 - else if (args[0].equals("event"))
587.38 - eventService = "true";
587.39 - else
587.40 - throw new IllegalArgumentException(args[0]);
587.41 -
587.42 try {
587.43 // create a rmi registry
587.44 Registry reg = null;
587.45 @@ -105,10 +95,9 @@
587.46 "/jndi/rmi://:" + port + "/server" + port);
587.47 System.out.println("RMIConnectorServer address " + url);
587.48
587.49 - Map<String, String> env = Collections.singletonMap(
587.50 - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE, eventService);
587.51 JMXConnectorServer sServer =
587.52 - JMXConnectorServerFactory.newJMXConnectorServer(url, env, null);
587.53 + JMXConnectorServerFactory.newJMXConnectorServer(url, null,
587.54 + null);
587.55
587.56 ObjectInstance ss = server.registerMBean(sServer, new ObjectName("Default:name=RmiConnectorServer"));
587.57
588.1 --- a/test/javax/management/remote/mandatory/notif/UnexpectedNotifTest.java Mon Nov 23 10:04:47 2009 +0000
588.2 +++ b/test/javax/management/remote/mandatory/notif/UnexpectedNotifTest.java Wed Nov 25 11:08:25 2009 -0800
588.3 @@ -63,17 +63,13 @@
588.4 } catch (ClassNotFoundException e) {
588.5 // OK: JMXMP not present so don't test it.
588.6 }
588.7 - for (String proto : protos) {
588.8 - test(proto, false);
588.9 - test(proto, true);
588.10 - }
588.11 + for (String proto : protos)
588.12 + test(proto);
588.13 }
588.14
588.15 - private static void test(String proto, boolean eventService)
588.16 - throws Exception {
588.17 + private static void test(String proto) throws Exception {
588.18 System.out.println("Unexpected notifications test for protocol " +
588.19 - proto + " with" +
588.20 - (eventService ? "" : "out") + " event service");
588.21 + proto);
588.22 MBeanServer mbs = null;
588.23 try {
588.24 // Create a MBeanServer
588.25 @@ -88,12 +84,9 @@
588.26 // Create a connector server
588.27 //
588.28 url = new JMXServiceURL("service:jmx:" + proto + "://");
588.29 - Map<String, String> env = Collections.singletonMap(
588.30 - RMIConnectorServer.DELEGATE_TO_EVENT_SERVICE,
588.31 - Boolean.toString(eventService));
588.32
588.33 server = JMXConnectorServerFactory.newJMXConnectorServer(url,
588.34 - env,
588.35 + null,
588.36 mbs);
588.37
588.38 mbs.registerMBean(
589.1 --- a/test/javax/management/remote/mandatory/version/JMXSpecVersionTest.java Mon Nov 23 10:04:47 2009 +0000
589.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
589.3 @@ -1,308 +0,0 @@
589.4 -/*
589.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
589.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
589.7 - *
589.8 - * This code is free software; you can redistribute it and/or modify it
589.9 - * under the terms of the GNU General Public License version 2 only, as
589.10 - * published by the Free Software Foundation.
589.11 - *
589.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
589.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
589.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
589.15 - * version 2 for more details (a copy is included in the LICENSE file that
589.16 - * accompanied this code).
589.17 - *
589.18 - * You should have received a copy of the GNU General Public License version
589.19 - * 2 along with this work; if not, write to the Free Software Foundation,
589.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
589.21 - *
589.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
589.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
589.24 - * have any questions.
589.25 - */
589.26 -
589.27 -/*
589.28 - * @test
589.29 - * @bug 6750008
589.30 - * @summary Test JMX.getSpecificationVersion
589.31 - * @author Eamonn McManus
589.32 - */
589.33 -
589.34 -import java.io.IOException;
589.35 -import java.util.Collections;
589.36 -import java.util.ListIterator;
589.37 -import java.util.Set;
589.38 -import javax.management.Attribute;
589.39 -import javax.management.AttributeList;
589.40 -import javax.management.AttributeNotFoundException;
589.41 -import javax.management.DynamicMBean;
589.42 -import javax.management.InstanceNotFoundException;
589.43 -import javax.management.InvalidAttributeValueException;
589.44 -import javax.management.JMX;
589.45 -import javax.management.MBeanException;
589.46 -import javax.management.MBeanInfo;
589.47 -import javax.management.MBeanServer;
589.48 -import javax.management.MBeanServerConnection;
589.49 -import javax.management.MBeanServerDelegate;
589.50 -import javax.management.MBeanServerDelegateMBean;
589.51 -import javax.management.MBeanServerFactory;
589.52 -import javax.management.ObjectName;
589.53 -import javax.management.ReflectionException;
589.54 -import javax.management.StandardMBean;
589.55 -import javax.management.namespace.JMXNamespace;
589.56 -import javax.management.namespace.JMXNamespaces;
589.57 -import javax.management.namespace.MBeanServerSupport;
589.58 -import javax.management.remote.JMXConnector;
589.59 -import javax.management.remote.JMXConnectorFactory;
589.60 -import javax.management.remote.JMXConnectorServer;
589.61 -import javax.management.remote.JMXConnectorServerFactory;
589.62 -import javax.management.remote.JMXServiceURL;
589.63 -
589.64 -public class JMXSpecVersionTest {
589.65 - private static String failure;
589.66 - private static final Object POISON_PILL = new Object();
589.67 -
589.68 - private static class FakeDelegate implements DynamicMBean {
589.69 - private final Object specVersion;
589.70 - private final DynamicMBean delegate = new StandardMBean(
589.71 - new MBeanServerDelegate(), MBeanServerDelegateMBean.class, false);
589.72 -
589.73 - FakeDelegate(Object specVersion) {
589.74 - this.specVersion = specVersion;
589.75 - }
589.76 -
589.77 - public Object getAttribute(String attribute)
589.78 - throws AttributeNotFoundException, MBeanException,
589.79 - ReflectionException {
589.80 - if ("SpecificationVersion".equals(attribute)) {
589.81 - if (specVersion == POISON_PILL)
589.82 - throw new AttributeNotFoundException(attribute);
589.83 - else
589.84 - return specVersion;
589.85 - } else
589.86 - return delegate.getAttribute(attribute);
589.87 - }
589.88 -
589.89 - public void setAttribute(Attribute attribute)
589.90 - throws AttributeNotFoundException, InvalidAttributeValueException,
589.91 - MBeanException, ReflectionException {
589.92 - delegate.setAttribute(attribute);
589.93 - }
589.94 -
589.95 - public AttributeList getAttributes(String[] attributes) {
589.96 - AttributeList list = delegate.getAttributes(attributes);
589.97 - for (ListIterator<Attribute> it = list.asList().listIterator();
589.98 - it.hasNext(); ) {
589.99 - Attribute attr = it.next();
589.100 - if (attr.getName().equals("SpecificationVersion")) {
589.101 - it.remove();
589.102 - if (specVersion != POISON_PILL) {
589.103 - attr = new Attribute(attr.getName(), specVersion);
589.104 - it.add(attr);
589.105 - }
589.106 - }
589.107 - }
589.108 - return list;
589.109 - }
589.110 -
589.111 - public AttributeList setAttributes(AttributeList attributes) {
589.112 - return delegate.setAttributes(attributes);
589.113 - }
589.114 -
589.115 - public Object invoke(String actionName, Object[] params,
589.116 - String[] signature) throws MBeanException,
589.117 - ReflectionException {
589.118 - return delegate.invoke(actionName, params, signature);
589.119 - }
589.120 -
589.121 - public MBeanInfo getMBeanInfo() {
589.122 - throw new UnsupportedOperationException("Not supported yet.");
589.123 - }
589.124 - }
589.125 -
589.126 - private static class MBeanServerWithVersion extends MBeanServerSupport {
589.127 - private final DynamicMBean delegate;
589.128 -
589.129 - public MBeanServerWithVersion(Object specVersion) {
589.130 - this.delegate = new FakeDelegate(specVersion);
589.131 - }
589.132 -
589.133 - @Override
589.134 - public DynamicMBean getDynamicMBeanFor(ObjectName name)
589.135 - throws InstanceNotFoundException {
589.136 - if (MBeanServerDelegate.DELEGATE_NAME.equals(name))
589.137 - return delegate;
589.138 - else
589.139 - throw new InstanceNotFoundException(name);
589.140 - }
589.141 -
589.142 - @Override
589.143 - protected Set<ObjectName> getNames() {
589.144 - return Collections.singleton(MBeanServerDelegate.DELEGATE_NAME);
589.145 - }
589.146 - }
589.147 -
589.148 - private static class EmptyMBeanServer extends MBeanServerSupport {
589.149 - @Override
589.150 - public DynamicMBean getDynamicMBeanFor(ObjectName name) throws InstanceNotFoundException {
589.151 - throw new InstanceNotFoundException(name);
589.152 - }
589.153 -
589.154 - @Override
589.155 - protected Set<ObjectName> getNames() {
589.156 - return Collections.emptySet();
589.157 - }
589.158 - }
589.159 -
589.160 - public static void main(String[] args) throws Exception {
589.161 - MBeanServer mbs = MBeanServerFactory.newMBeanServer();
589.162 - JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///");
589.163 - JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(
589.164 - url, null, mbs);
589.165 - cs.start();
589.166 -
589.167 - String realVersion = (String) mbs.getAttribute(
589.168 - MBeanServerDelegate.DELEGATE_NAME, "SpecificationVersion");
589.169 - assertEquals("Reported local version",
589.170 - realVersion, JMX.getSpecificationVersion(mbs, null));
589.171 - assertEquals("Reported local version >= \"2.0\"",
589.172 - true, (realVersion.compareTo("2.0") >= 0));
589.173 -
589.174 - JMXConnector cc = JMXConnectorFactory.connect(cs.getAddress());
589.175 - MBeanServerConnection mbsc = cc.getMBeanServerConnection();
589.176 - assertEquals("Reported remote version",
589.177 - realVersion, JMX.getSpecificationVersion(mbsc, null));
589.178 -
589.179 - cc.close();
589.180 - try {
589.181 - String brokenVersion = JMX.getSpecificationVersion(mbsc, null);
589.182 - fail("JMX.getSpecificationVersion succeded over closed connection" +
589.183 - " (returned " + brokenVersion + ")");
589.184 - } catch (Exception e) {
589.185 - assertEquals("Exception for closed connection",
589.186 - IOException.class, e.getClass());
589.187 - }
589.188 -
589.189 - try {
589.190 - String brokenVersion = JMX.getSpecificationVersion(
589.191 - new EmptyMBeanServer(), null);
589.192 - fail("JMX.getSpecificationVersion succeded with empty MBean Server" +
589.193 - " (returned " + brokenVersion + ")");
589.194 - } catch (Exception e) {
589.195 - assertEquals("Exception for empty MBean Server",
589.196 - IOException.class, e.getClass());
589.197 - }
589.198 -
589.199 - try {
589.200 - String brokenVersion = JMX.getSpecificationVersion(null, null);
589.201 - fail("JMX.getSpecificationVersion succeded with null MBean Server" +
589.202 - " (returned " + brokenVersion + ")");
589.203 - } catch (Exception e) {
589.204 - assertEquals("Exception for null MBean Server",
589.205 - IllegalArgumentException.class, e.getClass());
589.206 - }
589.207 -
589.208 - MBeanServer mbs1_2 = new MBeanServerWithVersion("1.2");
589.209 - String version1_2 = JMX.getSpecificationVersion(mbs1_2, null);
589.210 - assertEquals("Version for 1.2 MBean Server", "1.2", version1_2);
589.211 -
589.212 - // It's completely nutty for an MBean Server to return null as the
589.213 - // value of its spec version, and we don't actually say what happens
589.214 - // in that case, but in fact we return the null to the caller.
589.215 - MBeanServer mbs_null = new MBeanServerWithVersion(null);
589.216 - String version_null = JMX.getSpecificationVersion(mbs_null, null);
589.217 - assertEquals("Version for MBean Server that declares null spec version",
589.218 - null, version_null);
589.219 -
589.220 - try {
589.221 - MBeanServer mbs1_2_float = new MBeanServerWithVersion(1.2f);
589.222 - String version1_2_float =
589.223 - JMX.getSpecificationVersion(mbs1_2_float, null);
589.224 - fail("JMX.getSpecificationVersion succeeded with version 1.2f" +
589.225 - " (returned " + version1_2_float + ")");
589.226 - } catch (Exception e) {
589.227 - assertEquals("Exception for non-string version (1.2f)",
589.228 - IOException.class, e.getClass());
589.229 - }
589.230 -
589.231 - try {
589.232 - MBeanServer mbs_missing = new MBeanServerWithVersion(POISON_PILL);
589.233 - String version_missing =
589.234 - JMX.getSpecificationVersion(mbs_missing, null);
589.235 - fail("JMX.getSpecificationVersion succeeded with null version" +
589.236 - " (returned " + version_missing + ")");
589.237 - } catch (Exception e) {
589.238 - assertEquals("Exception for missing version",
589.239 - IOException.class, e.getClass());
589.240 - }
589.241 -
589.242 - ObjectName wildcardNamespaceName = new ObjectName("foo//*//bar//baz:k=v");
589.243 - try {
589.244 - String brokenVersion =
589.245 - JMX.getSpecificationVersion(mbsc, wildcardNamespaceName);
589.246 - fail("JMX.getSpecificationVersion succeeded with wildcard namespace" +
589.247 - " (returned " + brokenVersion + ")");
589.248 - } catch (Exception e) {
589.249 - assertEquals("Exception for wildcard namespace",
589.250 - IllegalArgumentException.class, e.getClass());
589.251 - }
589.252 -
589.253 - String sub1_2namespace = "blibby";
589.254 - JMXNamespace sub1_2 = new JMXNamespace(mbs1_2);
589.255 - ObjectName sub1_2name =
589.256 - JMXNamespaces.getNamespaceObjectName(sub1_2namespace);
589.257 - mbs.registerMBean(sub1_2, sub1_2name);
589.258 - String sub1_2namespaceHandlerVersion =
589.259 - JMX.getSpecificationVersion(mbs, sub1_2name);
589.260 - assertEquals("Spec version of namespace handler",
589.261 - realVersion, sub1_2namespaceHandlerVersion);
589.262 - // The namespace handler is in the top-level namespace so its
589.263 - // version should not be 1.2.
589.264 -
589.265 - for (String nameInSub : new String[] {"*:*", "d:k=v"}) {
589.266 - ObjectName subName = new ObjectName(sub1_2namespace + "//" + nameInSub);
589.267 - String subVersion = JMX.getSpecificationVersion(mbs, subName);
589.268 - assertEquals("Spec version in 1.2 namespace (" + nameInSub + ")",
589.269 - "1.2", subVersion);
589.270 - }
589.271 -
589.272 - mbs.unregisterMBean(sub1_2name);
589.273 - for (String noSuchNamespace : new String[] {
589.274 - sub1_2namespace + "//*:*", sub1_2namespace + "//d:k=v",
589.275 - }) {
589.276 - try {
589.277 - String brokenVersion = JMX.getSpecificationVersion(
589.278 - mbs, new ObjectName(noSuchNamespace));
589.279 - fail("JMX.getSpecificationVersion succeeded with missing " +
589.280 - "namespace (" + noSuchNamespace + " -> " +
589.281 - brokenVersion);
589.282 - } catch (Exception e) {
589.283 - assertEquals("Exception for missing namespace",
589.284 - IOException.class, e.getClass());
589.285 - }
589.286 - }
589.287 -
589.288 - if (failure != null)
589.289 - throw new Exception("TEST FAILED: " + failure);
589.290 - System.out.println("TEST PASSED");
589.291 - }
589.292 -
589.293 - private static void assertEquals(String what, Object expect, Object actual) {
589.294 - if (equal(expect, actual))
589.295 - System.out.println("OK: " + what + ": " + expect);
589.296 - else
589.297 - fail(what + ": expected " + expect + ", got " + actual);
589.298 - }
589.299 -
589.300 - private static boolean equal(Object x, Object y) {
589.301 - if (x == null)
589.302 - return (y == null);
589.303 - else
589.304 - return x.equals(y);
589.305 - }
589.306 -
589.307 - private static void fail(String why) {
589.308 - System.out.println("FAILED: " + why);
589.309 - failure = why;
589.310 - }
589.311 -}
590.1 --- a/test/javax/management/standardmbean/FindMethodTest.java Mon Nov 23 10:04:47 2009 +0000
590.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
590.3 @@ -1,384 +0,0 @@
590.4 -/*
590.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
590.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
590.7 - *
590.8 - * This code is free software; you can redistribute it and/or modify it
590.9 - * under the terms of the GNU General Public License version 2 only, as
590.10 - * published by the Free Software Foundation.
590.11 - *
590.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
590.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
590.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
590.15 - * version 2 for more details (a copy is included in the LICENSE file that
590.16 - * accompanied this code).
590.17 - *
590.18 - * You should have received a copy of the GNU General Public License version
590.19 - * 2 along with this work; if not, write to the Free Software Foundation,
590.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
590.21 - *
590.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
590.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
590.24 - * have any questions.
590.25 - */
590.26 -
590.27 -/*
590.28 - * @test
590.29 - * @bug 6287328
590.30 - * @summary Add methods to StandardMBean to retrieve a method based on
590.31 - * MBean{Attribute|Operation}Info
590.32 - * @author Jean-Francois Denise
590.33 - * @run main FindMethodTest
590.34 - */
590.35 -
590.36 -import java.lang.management.ManagementFactory;
590.37 -import java.lang.management.MemoryMXBean;
590.38 -import java.lang.management.ThreadMXBean;
590.39 -import java.lang.reflect.Method;
590.40 -import java.util.HashMap;
590.41 -import java.util.HashSet;
590.42 -import java.util.Map;
590.43 -import java.util.Set;
590.44 -import javax.management.MBean;
590.45 -import javax.management.MBeanAttributeInfo;
590.46 -import javax.management.MBeanInfo;
590.47 -import javax.management.MBeanOperationInfo;
590.48 -import javax.management.MBeanParameterInfo;
590.49 -import javax.management.MBeanServer;
590.50 -import javax.management.ManagedAttribute;
590.51 -import javax.management.ManagedOperation;
590.52 -import javax.management.ObjectName;
590.53 -import javax.management.StandardMBean;
590.54 -
590.55 -public class FindMethodTest {
590.56 -
590.57 - private static MBeanServer server =
590.58 - ManagementFactory.getPlatformMBeanServer();
590.59 -
590.60 - private static Map<String, Set<Method>> expectedMapping =
590.61 - new HashMap<String, Set<Method>>();
590.62 - private static Set<Method> STATE_SET = new HashSet<Method>();
590.63 - private static Set<Method> ENABLED_SET = new HashSet<Method>();
590.64 - private static Set<Method> DOIT_SET = new HashSet<Method>();
590.65 - private static Set<Method> STATUS_SET = new HashSet<Method>();
590.66 - private static Set<Method> HEAPMEMORYUSAGE_SET = new HashSet<Method>();
590.67 - private static Set<Method> THREADINFO_SET = new HashSet<Method>();
590.68 - private static Set<Method> DOIT_ANNOTATED_SET = new HashSet<Method>();
590.69 - private static Set<Method> IT_ANNOTATED_SET = new HashSet<Method>();
590.70 - private static HashSet<Set<Method>> TEST_MBEAN_SET =
590.71 - new HashSet<Set<Method>>();
590.72 - private static HashSet<Set<Method>> ANNOTATED_MBEAN_SET =
590.73 - new HashSet<Set<Method>>();
590.74 - private static HashSet<Set<Method>> MEMORY_MBEAN_SET =
590.75 - new HashSet<Set<Method>>();
590.76 - private static HashSet<Set<Method>> THREAD_MBEAN_SET =
590.77 - new HashSet<Set<Method>>();
590.78 -
590.79 - public interface TestMBean {
590.80 -
590.81 - public void doIt();
590.82 -
590.83 - public void setState(String str);
590.84 -
590.85 - public String getState();
590.86 -
590.87 - public boolean isEnabled();
590.88 -
590.89 - public void setStatus(int i);
590.90 - }
590.91 -
590.92 - public interface FaultyTestMBean {
590.93 -
590.94 - public void doIt(String doIt);
590.95 -
590.96 - public long getState();
590.97 -
590.98 - public void setEnabled(boolean b);
590.99 -
590.100 - public int getStatus();
590.101 -
590.102 - public String setWrong(int i);
590.103 - }
590.104 -
590.105 - @MBean
590.106 - public static class AnnotatedTest {
590.107 - @ManagedOperation
590.108 - public void doItAnnotated() {
590.109 -
590.110 - }
590.111 -
590.112 - public void dontDoIt() {
590.113 -
590.114 - }
590.115 -
590.116 - @ManagedAttribute
590.117 - public String getItAnnotated() {
590.118 - return null;
590.119 - }
590.120 - @ManagedAttribute
590.121 - public void setItAnnotated(String str) {
590.122 -
590.123 - }
590.124 -
590.125 - public String getItNot() {
590.126 - return null;
590.127 - }
590.128 -
590.129 - }
590.130 -
590.131 - static class Test implements TestMBean {
590.132 -
590.133 - public void doIt() {
590.134 - throw new UnsupportedOperationException("Not supported yet.");
590.135 - }
590.136 -
590.137 - public void setState(String str) {
590.138 - throw new UnsupportedOperationException("Not supported yet.");
590.139 - }
590.140 -
590.141 - public String getState() {
590.142 - throw new UnsupportedOperationException("Not supported yet.");
590.143 - }
590.144 -
590.145 - public boolean isEnabled() {
590.146 - throw new UnsupportedOperationException("Not supported yet.");
590.147 - }
590.148 -
590.149 - public void setStatus(int i) {
590.150 - throw new UnsupportedOperationException("Not supported yet.");
590.151 - }
590.152 - }
590.153 -
590.154 -
590.155 - static {
590.156 - try {
590.157 - ENABLED_SET.add(TestMBean.class.getDeclaredMethod("isEnabled"));
590.158 -
590.159 - STATE_SET.add(TestMBean.class.getDeclaredMethod("getState"));
590.160 - STATE_SET.add(TestMBean.class.getDeclaredMethod("setState",
590.161 - String.class));
590.162 - STATUS_SET.add(TestMBean.class.getDeclaredMethod("setStatus",
590.163 - int.class));
590.164 -
590.165 - DOIT_SET.add(TestMBean.class.getDeclaredMethod("doIt"));
590.166 -
590.167 - DOIT_ANNOTATED_SET.add(AnnotatedTest.class.getDeclaredMethod("doItAnnotated"));
590.168 -
590.169 - IT_ANNOTATED_SET.add(AnnotatedTest.class.getDeclaredMethod("getItAnnotated"));
590.170 - IT_ANNOTATED_SET.add(AnnotatedTest.class.getDeclaredMethod("setItAnnotated", String.class));
590.171 -
590.172 - THREADINFO_SET.add(ThreadMXBean.class.getDeclaredMethod("dumpAllThreads", boolean.class,
590.173 - boolean.class));
590.174 -
590.175 - HEAPMEMORYUSAGE_SET.add(MemoryMXBean.class.getDeclaredMethod("getHeapMemoryUsage"));
590.176 -
590.177 - TEST_MBEAN_SET.add(ENABLED_SET);
590.178 - TEST_MBEAN_SET.add(STATE_SET);
590.179 - TEST_MBEAN_SET.add(STATUS_SET);
590.180 - TEST_MBEAN_SET.add(DOIT_SET);
590.181 -
590.182 - ANNOTATED_MBEAN_SET.add(DOIT_ANNOTATED_SET);
590.183 - ANNOTATED_MBEAN_SET.add(IT_ANNOTATED_SET);
590.184 -
590.185 - MEMORY_MBEAN_SET.add(HEAPMEMORYUSAGE_SET);
590.186 -
590.187 - THREAD_MBEAN_SET.add(THREADINFO_SET);
590.188 -
590.189 - expectedMapping.put("State", STATE_SET);
590.190 - expectedMapping.put("Enabled", ENABLED_SET);
590.191 - expectedMapping.put("Status", STATUS_SET);
590.192 - expectedMapping.put("doIt", DOIT_SET);
590.193 - expectedMapping.put("HeapMemoryUsage", HEAPMEMORYUSAGE_SET);
590.194 - expectedMapping.put("dumpAllThreads", THREADINFO_SET);
590.195 - expectedMapping.put("doItAnnotated", DOIT_ANNOTATED_SET);
590.196 - expectedMapping.put("ItAnnotated", IT_ANNOTATED_SET);
590.197 -
590.198 - } catch (Exception ex) {
590.199 - ex.printStackTrace();
590.200 - throw new RuntimeException("Initialization failed");
590.201 - }
590.202 - }
590.203 -
590.204 - private static void testMBean(ObjectName name, Class<?> itf,
590.205 - HashSet<Set<Method>> expectMappings)
590.206 - throws Exception {
590.207 -
590.208 - Set<Set<Method>> expectedMappings =
590.209 - (Set<Set<Method>>) expectMappings.clone();
590.210 -
590.211 - MBeanInfo info = server.getMBeanInfo(name);
590.212 - for (MBeanAttributeInfo attr : info.getAttributes()) {
590.213 - Set<Method> expected = expectedMapping.get(attr.getName());
590.214 - if (expected == null) {
590.215 - continue;
590.216 - }
590.217 - if (!expectedMappings.remove(expected)) {
590.218 - throw new Exception("The mapping to use is not the expected " +
590.219 - "one for " + attr);
590.220 - }
590.221 - System.out.println("Expected : " + expected);
590.222 - Set<Method> found =
590.223 - StandardMBean.findAttributeAccessors(itf, attr);
590.224 - System.out.println("Found : " + found);
590.225 - if (!found.equals(expected)) {
590.226 - throw new Exception("Mapping error.");
590.227 - }
590.228 - }
590.229 - for (MBeanOperationInfo op : info.getOperations()) {
590.230 - Set<Method> expected = expectedMapping.get(op.getName());
590.231 - if (expected == null) {
590.232 - continue;
590.233 - }
590.234 - if (!expectedMappings.remove(expected)) {
590.235 - throw new Exception("The mapping to use is not the expected " +
590.236 - "one for " + op);
590.237 - }
590.238 - System.out.println("Expected : " + expected);
590.239 - Method method =
590.240 - StandardMBean.findOperationMethod(itf, op);
590.241 - Set<Method> found = new HashSet<Method>();
590.242 - found.add(method);
590.243 - System.out.println("Found : " + found);
590.244 - if (!found.equals(expected)) {
590.245 - throw new Exception("Mapping error.");
590.246 - }
590.247 - }
590.248 -
590.249 - if (expectedMappings.size() != 0) {
590.250 - throw new Exception("Some mapping have not been found " +
590.251 - expectedMappings);
590.252 - } else {
590.253 - System.out.println("All mappings have been found");
590.254 - }
590.255 - }
590.256 -
590.257 - public static void main(String[] args) throws Exception {
590.258 - // Positive tests
590.259 - Test t = new Test();
590.260 - ObjectName name = ObjectName.valueOf(":type=Test");
590.261 - server.registerMBean(t, name);
590.262 - AnnotatedTest at = new AnnotatedTest();
590.263 - ObjectName annotatedName = ObjectName.valueOf(":type=AnnotatedTest");
590.264 - server.registerMBean(at, annotatedName);
590.265 -
590.266 - testMBean(name, TestMBean.class, TEST_MBEAN_SET);
590.267 -
590.268 - testMBean(annotatedName, AnnotatedTest.class, ANNOTATED_MBEAN_SET);
590.269 -
590.270 - ObjectName memoryName =
590.271 - ObjectName.valueOf(ManagementFactory.MEMORY_MXBEAN_NAME);
590.272 - testMBean(memoryName, MemoryMXBean.class, MEMORY_MBEAN_SET);
590.273 -
590.274 - ObjectName threadName =
590.275 - ObjectName.valueOf(ManagementFactory.THREAD_MXBEAN_NAME);
590.276 - testMBean(threadName, ThreadMXBean.class, THREAD_MBEAN_SET);
590.277 -
590.278 - // Negative tests
590.279 - try {
590.280 - StandardMBean.findOperationMethod(null,
590.281 - new MBeanOperationInfo("Test",
590.282 - TestMBean.class.getDeclaredMethod("doIt")));
590.283 - throw new Exception("Expected exception not found");
590.284 - } catch (IllegalArgumentException ex) {
590.285 - System.out.println("OK received expected exception " + ex);
590.286 - }
590.287 - try {
590.288 - StandardMBean.findOperationMethod(TestMBean.class, null);
590.289 - throw new Exception("Expected exception not found");
590.290 - } catch (IllegalArgumentException ex) {
590.291 - System.out.println("OK received expected exception " + ex);
590.292 - }
590.293 - try {
590.294 - StandardMBean.findAttributeAccessors(null,
590.295 - new MBeanAttributeInfo("Test", "Test",
590.296 - TestMBean.class.getDeclaredMethod("getState"),
590.297 - TestMBean.class.getDeclaredMethod("setState",
590.298 - String.class)));
590.299 - throw new Exception("Expected exception not found");
590.300 - } catch (IllegalArgumentException ex) {
590.301 - System.out.println("OK received expected exception " + ex);
590.302 - }
590.303 - try {
590.304 - StandardMBean.findAttributeAccessors(TestMBean.class, null);
590.305 - throw new Exception("Expected exception not found");
590.306 - } catch (IllegalArgumentException ex) {
590.307 - System.out.println("OK received expected exception " + ex);
590.308 - }
590.309 - //Wrong operation signature
590.310 - try {
590.311 - StandardMBean.findOperationMethod(TestMBean.class,
590.312 - new MBeanOperationInfo("FaultyTest",
590.313 - FaultyTestMBean.class.getDeclaredMethod("doIt",
590.314 - String.class)));
590.315 - throw new Exception("Expected exception not found");
590.316 - } catch (NoSuchMethodException ex) {
590.317 - System.out.println("OK received expected exception " + ex);
590.318 - }
590.319 - //Wrong attribute accessor
590.320 - try {
590.321 - StandardMBean.findAttributeAccessors(TestMBean.class,
590.322 - new MBeanAttributeInfo("FaultyTest", "FaultyTest", null,
590.323 - FaultyTestMBean.class.getDeclaredMethod("setEnabled",
590.324 - String.class)));
590.325 - throw new Exception("Expected exception not found");
590.326 - } catch (NoSuchMethodException ex) {
590.327 - System.out.println("OK received expected exception " + ex);
590.328 - }
590.329 - //Wrong attribute type
590.330 - try {
590.331 - StandardMBean.findAttributeAccessors(TestMBean.class,
590.332 - new MBeanAttributeInfo("State", "toto.FaultType",
590.333 - "FaultyTest", true, true, false));
590.334 - throw new Exception("Expected exception not found");
590.335 - } catch (ClassNotFoundException ex) {
590.336 - System.out.println("OK received expected exception " + ex);
590.337 - }
590.338 - //Wrong operation parameter type
590.339 - try {
590.340 - MBeanParameterInfo[] p = {new MBeanParameterInfo("p1",
590.341 - "toto.FaultType2", "FaultyParameter")
590.342 - };
590.343 - StandardMBean.findOperationMethod(TestMBean.class,
590.344 - new MBeanOperationInfo("doIt", "FaultyMethod", p, "void",
590.345 - 0));
590.346 - throw new Exception("Expected exception not found");
590.347 - } catch (ClassNotFoundException ex) {
590.348 - System.out.println("OK received expected exception " + ex);
590.349 - }
590.350 - // Check that not annotated attributes are not found
590.351 - try {
590.352 - StandardMBean.findAttributeAccessors(AnnotatedTest.class,
590.353 - new MBeanAttributeInfo("ItNot", String.class.getName(),
590.354 - "FaultyTest", true, false, false));
590.355 - throw new Exception("Expected exception not found");
590.356 - } catch (NoSuchMethodException ex) {
590.357 - System.out.println("OK received expected exception " + ex);
590.358 - }
590.359 - // Check that not annotated operations are not found
590.360 - try {
590.361 - StandardMBean.findOperationMethod(AnnotatedTest.class,
590.362 - new MBeanOperationInfo("dontDoIt","dontDoIt",null,
590.363 - Void.TYPE.getName(),0));
590.364 - throw new Exception("Expected exception not found");
590.365 - } catch (NoSuchMethodException ex) {
590.366 - System.out.println("OK received expected exception " + ex);
590.367 - }
590.368 - // Check that wrong getter return type throws Exception
590.369 - try {
590.370 - StandardMBean.findAttributeAccessors(AnnotatedTest.class,
590.371 - new MBeanAttributeInfo("ItAnnotated", Long.class.getName(),
590.372 - "FaultyTest", true, false, false));
590.373 - throw new Exception("Expected exception not found");
590.374 - } catch (NoSuchMethodException ex) {
590.375 - System.out.println("OK received expected exception " + ex);
590.376 - }
590.377 - // Check that wrong setter return type throws Exception
590.378 - try {
590.379 - StandardMBean.findAttributeAccessors(FaultyTestMBean.class,
590.380 - new MBeanAttributeInfo("Wrong", String.class.getName(),
590.381 - "FaultyTest", true, true, false));
590.382 - throw new Exception("Expected exception not found");
590.383 - } catch (NoSuchMethodException ex) {
590.384 - System.out.println("OK received expected exception " + ex);
590.385 - }
590.386 - }
590.387 -}
591.1 --- a/test/javax/management/standardmbean/RegistrationTest.java Mon Nov 23 10:04:47 2009 +0000
591.2 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000
591.3 @@ -1,91 +0,0 @@
591.4 -/*
591.5 - * Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
591.6 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
591.7 - *
591.8 - * This code is free software; you can redistribute it and/or modify it
591.9 - * under the terms of the GNU General Public License version 2 only, as
591.10 - * published by the Free Software Foundation.
591.11 - *
591.12 - * This code is distributed in the hope that it will be useful, but WITHOUT
591.13 - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
591.14 - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
591.15 - * version 2 for more details (a copy is included in the LICENSE file that
591.16 - * accompanied this code).
591.17 - *
591.18 - * You should have received a copy of the GNU General Public License version
591.19 - * 2 along with this work; if not, write to the Free Software Foundation,
591.20 - * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
591.21 - *
591.22 - * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
591.23 - * CA 95054 USA or visit www.sun.com if you need additional information or
591.24 - * have any questions.
591.25 - */
591.26 -
591.27 -/*
591.28 - * @test
591.29 - * @bug 6450834
591.30 - * @summary Forward MBeanRegistration calls
591.31 - * @author JF Denise
591.32 - * @run main RegistrationTest
591.33 - */
591.34 -
591.35 -import java.io.Serializable;
591.36 -import java.lang.management.ManagementFactory;
591.37 -import javax.management.*;
591.38 -
591.39 -public class RegistrationTest {
591.40 - static boolean preRegisterCalled;
591.41 - static boolean postRegisterCalled;
591.42 - static boolean preDeregisterCalled;
591.43 - static boolean postDeregisterCalled;
591.44 -
591.45 - static void checkResult(boolean expected) throws Exception {
591.46 - if((preRegisterCalled != expected ||
591.47 - postRegisterCalled != expected ||
591.48 - preDeregisterCalled != expected ||
591.49 - postDeregisterCalled != expected))
591.50 - throw new Exception("Mismatch preRegisterCalled = "
591.51 - + preRegisterCalled + ", postRegisterCalled = "
591.52 - + postRegisterCalled + ", preDeregisterCalled = "
591.53 - + preDeregisterCalled + ", postDeregisterCalled = "
591.54 - + postDeregisterCalled);
591.55 - }
591.56 - static class Wrapped implements MBeanRegistration,Serializable {
591.57 -
591.58 - public ObjectName preRegister(MBeanServer server, ObjectName name)
591.59 - throws Exception {
591.60 - preRegisterCalled = true;
591.61 - return name;
591.62 - }
591.63 -
591.64 - public void postRegister(Boolean registrationDone) {
591.65 - postRegisterCalled = true;
591.66 - }
591.67 -
591.68 - public void preDeregister() throws Exception {
591.69 - preDeregisterCalled = true;
591.70 - }
591.71 -
591.72 - public void postDeregister() {
591.73 - postDeregisterCalled = true;
591.74 - }
591.75 -
591.76 - }
591.77 -
591.78 - public static void main(String[] args) throws Exception {
591.79 - StandardMBean std = new StandardMBean(new Wrapped(),
591.80 - Serializable.class);
591.81 - ObjectName name = ObjectName.valueOf(":type=Test");
591.82 - ManagementFactory.getPlatformMBeanServer().registerMBean(std,name);
591.83 - ManagementFactory.getPlatformMBeanServer().unregisterMBean(name);
591.84 - checkResult(false);
591.85 - StandardMBean.Options opt = new StandardMBean.Options();
591.86 - opt.setMBeanRegistrationForwarded(true);
591.87 - std = new StandardMBean(new Wrapped(),
591.88 - Serializable.class, opt );
591.89 - ManagementFactory.getPlatformMBeanServer().registerMBean(std,name);
591.90 - ManagementFactory.getPlatformMBeanServer().unregisterMBean(name);
591.91 - checkResult(true);
591.92 - System.out.println("Test OK");
591.93 - }
591.94 -}
592.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
592.2 +++ b/test/javax/swing/JFileChooser/6550546/bug6550546.java Wed Nov 25 11:08:25 2009 -0800
592.3 @@ -0,0 +1,57 @@
592.4 +/*
592.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
592.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
592.7 + *
592.8 + * This code is free software; you can redistribute it and/or modify it
592.9 + * under the terms of the GNU General Public License version 2 only, as
592.10 + * published by the Free Software Foundation.
592.11 + *
592.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
592.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
592.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
592.15 + * version 2 for more details (a copy is included in the LICENSE file that
592.16 + * accompanied this code).
592.17 + *
592.18 + * You should have received a copy of the GNU General Public License version
592.19 + * 2 along with this work; if not, write to the Free Software Foundation,
592.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
592.21 + *
592.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
592.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
592.24 + * have any questions.
592.25 + */
592.26 +
592.27 +/* @test
592.28 + @bug 6550546
592.29 + @summary Win LAF: JFileChooser -> Look in Drop down should not display any shortcuts created on desktop
592.30 + @author Pavel Porvatov
592.31 + @run main bug6550546
592.32 +*/
592.33 +
592.34 +import sun.awt.OSInfo;
592.35 +import sun.awt.shell.ShellFolder;
592.36 +
592.37 +import javax.swing.*;
592.38 +import java.io.File;
592.39 +
592.40 +public class bug6550546 {
592.41 + public static void main(String[] args) throws Exception {
592.42 + if (OSInfo.getOSType() != OSInfo.OSType.WINDOWS) {
592.43 + System.out.println("The test is suitable only for Windows, skipped.");
592.44 +
592.45 + return;
592.46 + }
592.47 +
592.48 + SwingUtilities.invokeAndWait(new Runnable() {
592.49 + public void run() {
592.50 + File[] files = (File[]) ShellFolder.get("fileChooserComboBoxFolders");
592.51 +
592.52 + for (File file : files) {
592.53 + if (file instanceof ShellFolder && ((ShellFolder) file).isLink()) {
592.54 + throw new RuntimeException("Link shouldn't be in FileChooser combobox, " + file.getPath());
592.55 + }
592.56 + }
592.57 + }
592.58 + });
592.59 + }
592.60 +}
593.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
593.2 +++ b/test/javax/swing/JFileChooser/6741890/bug6741890.java Wed Nov 25 11:08:25 2009 -0800
593.3 @@ -0,0 +1,107 @@
593.4 +/*
593.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
593.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
593.7 + *
593.8 + * This code is free software; you can redistribute it and/or modify it
593.9 + * under the terms of the GNU General Public License version 2 only, as
593.10 + * published by the Free Software Foundation.
593.11 + *
593.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
593.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
593.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
593.15 + * version 2 for more details (a copy is included in the LICENSE file that
593.16 + * accompanied this code).
593.17 + *
593.18 + * You should have received a copy of the GNU General Public License version
593.19 + * 2 along with this work; if not, write to the Free Software Foundation,
593.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
593.21 + *
593.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
593.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
593.24 + * have any questions.
593.25 + */
593.26 +
593.27 +/* @test
593.28 + @bug 6741890
593.29 + @summary Deadlock in Win32ShellFolderManager2
593.30 + @author Pavel Porvatov
593.31 + @run main bug6741890
593.32 +*/
593.33 +
593.34 +import sun.awt.shell.ShellFolder;
593.35 +import sun.awt.OSInfo;
593.36 +
593.37 +import java.io.File;
593.38 +import java.lang.reflect.Field;
593.39 +import java.util.concurrent.Callable;
593.40 +
593.41 +public class bug6741890 {
593.42 + /**
593.43 + * This mux is used to prevent NPE in the isLink and isFileSystem methods
593.44 + */
593.45 + private static final Object mux = new Object();
593.46 +
593.47 + private static final int COUNT = 100000;
593.48 +
593.49 + public static void main(String[] args) throws Exception {
593.50 + if (OSInfo.getOSType() != OSInfo.OSType.WINDOWS) {
593.51 + System.out.println("The test is applicable only for Windows. Skipped.");
593.52 +
593.53 + return;
593.54 + }
593.55 +
593.56 + String tmpDir = System.getProperty("java.io.tmpdir");
593.57 +
593.58 + if (tmpDir.length() == 0) { //'java.io.tmpdir' isn't guaranteed to be defined
593.59 + tmpDir = System.getProperty("user.home");
593.60 + }
593.61 +
593.62 + final ShellFolder tmpFile = ShellFolder.getShellFolder(new File(tmpDir));
593.63 +
593.64 + System.out.println("Temp directory: " + tmpDir);
593.65 +
593.66 + System.out.println("Stress test was run");
593.67 +
593.68 + Thread thread = new Thread() {
593.69 + public void run() {
593.70 + while (!isInterrupted()) {
593.71 + ShellFolder.invoke(new Callable<Void>() {
593.72 + public Void call() throws Exception {
593.73 + synchronized (mux) {
593.74 + tmpFile.isFileSystem();
593.75 + tmpFile.isLink();
593.76 + }
593.77 +
593.78 + return null;
593.79 + }
593.80 + });
593.81 + }
593.82 + }
593.83 + };
593.84 +
593.85 + thread.start();
593.86 +
593.87 + for (int i = 0; i < COUNT; i++) {
593.88 + synchronized (mux) {
593.89 + clearField(tmpFile, "cachedIsLink");
593.90 + clearField(tmpFile, "cachedIsFileSystem");
593.91 + }
593.92 +
593.93 + tmpFile.isFileSystem();
593.94 + tmpFile.isLink();
593.95 + }
593.96 +
593.97 + thread.interrupt();
593.98 + thread.join();
593.99 +
593.100 + System.out.println("Test passed successfully");
593.101 + }
593.102 +
593.103 + private static void clearField(Object o, String fieldName) throws Exception {
593.104 + Field field = o.getClass().getDeclaredField(fieldName);
593.105 +
593.106 + field.setAccessible(true);
593.107 +
593.108 + field.set(o, null);
593.109 + }
593.110 +}
594.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
594.2 +++ b/test/javax/swing/JFileChooser/6868611/bug6868611.java Wed Nov 25 11:08:25 2009 -0800
594.3 @@ -0,0 +1,93 @@
594.4 +/*
594.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
594.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
594.7 + *
594.8 + * This code is free software; you can redistribute it and/or modify it
594.9 + * under the terms of the GNU General Public License version 2 only, as
594.10 + * published by the Free Software Foundation.
594.11 + *
594.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
594.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
594.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
594.15 + * version 2 for more details (a copy is included in the LICENSE file that
594.16 + * accompanied this code).
594.17 + *
594.18 + * You should have received a copy of the GNU General Public License version
594.19 + * 2 along with this work; if not, write to the Free Software Foundation,
594.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
594.21 + *
594.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
594.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
594.24 + * have any questions.
594.25 + */
594.26 +
594.27 +/* @test
594.28 + @bug 6868611
594.29 + @summary FileSystemView throws NullPointerException
594.30 + @author Pavel Porvatov
594.31 + @run main bug6868611
594.32 +*/
594.33 +
594.34 +import javax.swing.*;
594.35 +import javax.swing.filechooser.FileSystemView;
594.36 +import java.io.File;
594.37 +
594.38 +public class bug6868611 {
594.39 + private static final int COUNT = 1000;
594.40 +
594.41 + public static void main(String[] args) throws Exception {
594.42 + String tempDirProp = System.getProperty("java.io.tmpdir");
594.43 +
594.44 + final String tempDir = tempDirProp == null || !new File(tempDirProp).isDirectory() ?
594.45 + System.getProperty("user.home") : tempDirProp;
594.46 +
594.47 + System.out.println("Temp directory: " + tempDir);
594.48 +
594.49 + // Create 1000 files
594.50 + for (int i = 0; i < 1000; i++) {
594.51 + new File(tempDir, "temp" + i).createNewFile();
594.52 + }
594.53 +
594.54 + // Init default FileSystemView
594.55 + SwingUtilities.invokeAndWait(new Runnable() {
594.56 + public void run() {
594.57 + FileSystemView.getFileSystemView().getFiles(new File(tempDir), false);
594.58 + }
594.59 + });
594.60 +
594.61 + for (int i = 0; i < COUNT; i++) {
594.62 + Thread thread = new MyThread(tempDir);
594.63 +
594.64 + thread.start();
594.65 +
594.66 + Thread.sleep((long) (Math.random() * 100));
594.67 +
594.68 + thread.interrupt();
594.69 +
594.70 + if (i % 100 == 0) {
594.71 + System.out.print("*");
594.72 + }
594.73 + }
594.74 +
594.75 + System.out.println();
594.76 +
594.77 + // Remove 1000 files
594.78 + for (int i = 0; i < 1000; i++) {
594.79 + new File(tempDir, "temp" + i).delete();
594.80 + }
594.81 + }
594.82 +
594.83 + private static class MyThread extends Thread {
594.84 + private final String dir;
594.85 +
594.86 + private MyThread(String dir) {
594.87 + this.dir = dir;
594.88 + }
594.89 +
594.90 + public void run() {
594.91 + FileSystemView fileSystemView = FileSystemView.getFileSystemView();
594.92 +
594.93 + fileSystemView.getFiles(new File(dir), false);
594.94 + }
594.95 + }
594.96 +}
595.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
595.2 +++ b/test/javax/swing/Security/6657138/ComponentTest.java Wed Nov 25 11:08:25 2009 -0800
595.3 @@ -0,0 +1,76 @@
595.4 +/*
595.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
595.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
595.7 + *
595.8 + * This code is free software; you can redistribute it and/or modify it
595.9 + * under the terms of the GNU General Public License version 2 only, as
595.10 + * published by the Free Software Foundation.
595.11 + *
595.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
595.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
595.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
595.15 + * version 2 for more details (a copy is included in the LICENSE file that
595.16 + * accompanied this code).
595.17 + *
595.18 + * You should have received a copy of the GNU General Public License version
595.19 + * 2 along with this work; if not, write to the Free Software Foundation,
595.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
595.21 + *
595.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
595.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
595.24 + * have any questions.
595.25 + */
595.26 +
595.27 +/*
595.28 + * @test
595.29 + * @bug 6657138
595.30 + * @summary Verifies that buttons and labels work well after the fix for 6657138
595.31 + * @author Alexander Potochkin
595.32 + */
595.33 +
595.34 +import sun.awt.SunToolkit;
595.35 +
595.36 +import javax.swing.*;
595.37 +import java.awt.*;
595.38 +
595.39 +public class ComponentTest extends JFrame {
595.40 + private static JFrame frame;
595.41 +
595.42 + public ComponentTest() {
595.43 + setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
595.44 + setLayout(new FlowLayout());
595.45 + add(new JButton("JButton"));
595.46 + add(new JToggleButton("JToggleButton"));
595.47 + add(new JCheckBox("JCheckBox"));
595.48 + add(new JRadioButton("JRadioButton"));
595.49 + add(new JLabel("JLabel"));
595.50 + pack();
595.51 + setLocationRelativeTo(null);
595.52 + }
595.53 +
595.54 +
595.55 + public static void main(String[] args) throws Exception {
595.56 + SunToolkit toolkit = (SunToolkit) Toolkit.getDefaultToolkit();
595.57 + SwingUtilities.invokeAndWait(new Runnable() {
595.58 + public void run() {
595.59 + frame = new ComponentTest();
595.60 + frame.setVisible(true);
595.61 + }
595.62 + });
595.63 + toolkit.realSync();
595.64 + UIManager.LookAndFeelInfo[] lafs = UIManager.getInstalledLookAndFeels();
595.65 + for (final UIManager.LookAndFeelInfo laf : lafs) {
595.66 + SwingUtilities.invokeAndWait(new Runnable() {
595.67 + public void run() {
595.68 + try {
595.69 + UIManager.setLookAndFeel(laf.getClassName());
595.70 + } catch (Exception e) {
595.71 + new RuntimeException(e);
595.72 + }
595.73 + SwingUtilities.updateComponentTreeUI(frame);
595.74 + }
595.75 + });
595.76 + toolkit.realSync();
595.77 + }
595.78 + }
595.79 +}
596.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
596.2 +++ b/test/javax/swing/Security/6657138/bug6657138.java Wed Nov 25 11:08:25 2009 -0800
596.3 @@ -0,0 +1,103 @@
596.4 +/*
596.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
596.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
596.7 + *
596.8 + * This code is free software; you can redistribute it and/or modify it
596.9 + * under the terms of the GNU General Public License version 2 only, as
596.10 + * published by the Free Software Foundation.
596.11 + *
596.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
596.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
596.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
596.15 + * version 2 for more details (a copy is included in the LICENSE file that
596.16 + * accompanied this code).
596.17 + *
596.18 + * You should have received a copy of the GNU General Public License version
596.19 + * 2 along with this work; if not, write to the Free Software Foundation,
596.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
596.21 + *
596.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
596.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
596.24 + * have any questions.
596.25 + */
596.26 +
596.27 +/*
596.28 + * @test
596.29 + * @bug 6657138
596.30 + * @summary Verifies that buttons and labels don't share their ui's across appContexts
596.31 + * @author Alexander Potochkin
596.32 + */
596.33 +
596.34 +import sun.awt.SunToolkit;
596.35 +
596.36 +import javax.swing.*;
596.37 +import javax.swing.plaf.ButtonUI;
596.38 +import javax.swing.plaf.ComponentUI;
596.39 +import java.util.Collections;
596.40 +import java.util.HashMap;
596.41 +import java.util.Map;
596.42 +import java.util.Set;
596.43 +
596.44 +public class bug6657138 implements Runnable {
596.45 +
596.46 + private static Map<JComponent, Map<String, ComponentUI>> componentMap =
596.47 + Collections.synchronizedMap(
596.48 + new HashMap<JComponent, Map<String, ComponentUI>>());
596.49 +
596.50 + public void run() {
596.51 + SunToolkit.createNewAppContext();
596.52 + try {
596.53 + testUIMap();
596.54 + } catch (Exception e) {
596.55 + throw new RuntimeException(e);
596.56 + }
596.57 + }
596.58 +
596.59 + private static void testUIMap() throws Exception {
596.60 + UIManager.LookAndFeelInfo[] lafs = UIManager.getInstalledLookAndFeels();
596.61 + Set<JComponent> components = componentMap.keySet();
596.62 + for (JComponent c : components) {
596.63 + Map<String, ComponentUI> uiMap = componentMap.get(c);
596.64 +
596.65 + for (UIManager.LookAndFeelInfo laf : lafs) {
596.66 + if ("Nimbus".equals(laf.getName())) {
596.67 + // for some unclear reasons
596.68 + // Nimbus ui delegate for a button is null
596.69 + // when this method is called from the new AppContext
596.70 + continue;
596.71 + }
596.72 + String className = laf.getClassName();
596.73 + UIManager.setLookAndFeel(className);
596.74 + ComponentUI ui = UIManager.getUI(c);
596.75 + if (ui == null) {
596.76 + throw new RuntimeException("UI is null for " + c);
596.77 + }
596.78 + if (ui == uiMap.get(laf.getName())) {
596.79 + throw new RuntimeException(
596.80 + "Two AppContexts share the same UI delegate! \n" +
596.81 + c + "\n" + ui);
596.82 + }
596.83 + uiMap.put(laf.getName(), ui);
596.84 + }
596.85 + }
596.86 + }
596.87 +
596.88 + public static void main(String[] args) throws Exception {
596.89 + componentMap.put(new JButton("JButton"),
596.90 + new HashMap<String, ComponentUI>());
596.91 + componentMap.put(new JToggleButton("JToggleButton"),
596.92 + new HashMap<String, ComponentUI>());
596.93 + componentMap.put(new JRadioButton("JRadioButton"),
596.94 + new HashMap<String, ComponentUI>());
596.95 + componentMap.put(new JCheckBox("JCheckBox"),
596.96 + new HashMap<String, ComponentUI>());
596.97 + componentMap.put(new JCheckBox("JLabel"),
596.98 + new HashMap<String, ComponentUI>());
596.99 + testUIMap();
596.100 + ThreadGroup group = new ThreadGroup("6657138");
596.101 + Thread thread = new Thread(group, new bug6657138());
596.102 + thread.start();
596.103 + thread.join();
596.104 + }
596.105 +}
596.106 +
597.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
597.2 +++ b/test/javax/swing/ToolTipManager/Test6657026.java Wed Nov 25 11:08:25 2009 -0800
597.3 @@ -0,0 +1,74 @@
597.4 +/*
597.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
597.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
597.7 + *
597.8 + * This code is free software; you can redistribute it and/or modify it
597.9 + * under the terms of the GNU General Public License version 2 only, as
597.10 + * published by the Free Software Foundation.
597.11 + *
597.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
597.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
597.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
597.15 + * version 2 for more details (a copy is included in the LICENSE file that
597.16 + * accompanied this code).
597.17 + *
597.18 + * You should have received a copy of the GNU General Public License version
597.19 + * 2 along with this work; if not, write to the Free Software Foundation,
597.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
597.21 + *
597.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
597.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
597.24 + * have any questions.
597.25 + */
597.26 +
597.27 +/*
597.28 + * @test
597.29 + * @bug 6657026
597.30 + * @summary Tests shared ToolTipManager in different application contexts
597.31 + * @author Sergey Malenkov
597.32 + */
597.33 +
597.34 +import sun.awt.SunToolkit;
597.35 +import javax.swing.ToolTipManager;
597.36 +
597.37 +public class Test6657026 implements Runnable {
597.38 +
597.39 + private static final int DISMISS = 4000;
597.40 + private static final int INITIAL = 750;
597.41 + private static final int RESHOW = 500;
597.42 +
597.43 + public static void main(String[] args) throws InterruptedException {
597.44 + ToolTipManager manager = ToolTipManager.sharedInstance();
597.45 + if (DISMISS != manager.getDismissDelay()) {
597.46 + throw new Error("unexpected dismiss delay");
597.47 + }
597.48 + if (INITIAL != manager.getInitialDelay()) {
597.49 + throw new Error("unexpected initial delay");
597.50 + }
597.51 + if (RESHOW != manager.getReshowDelay()) {
597.52 + throw new Error("unexpected reshow delay");
597.53 + }
597.54 + manager.setDismissDelay(DISMISS + 1);
597.55 + manager.setInitialDelay(INITIAL + 1);
597.56 + manager.setReshowDelay(RESHOW + 1);
597.57 +
597.58 + ThreadGroup group = new ThreadGroup("$$$");
597.59 + Thread thread = new Thread(group, new Test6657026());
597.60 + thread.start();
597.61 + thread.join();
597.62 + }
597.63 +
597.64 + public void run() {
597.65 + SunToolkit.createNewAppContext();
597.66 + ToolTipManager manager = ToolTipManager.sharedInstance();
597.67 + if (DISMISS != manager.getDismissDelay()) {
597.68 + throw new Error("shared dismiss delay");
597.69 + }
597.70 + if (INITIAL != manager.getInitialDelay()) {
597.71 + throw new Error("shared initial delay");
597.72 + }
597.73 + if (RESHOW != manager.getReshowDelay()) {
597.74 + throw new Error("shared reshow delay");
597.75 + }
597.76 + }
597.77 +}
598.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
598.2 +++ b/test/javax/swing/UIDefaults/6795356/SwingLazyValueTest.java Wed Nov 25 11:08:25 2009 -0800
598.3 @@ -0,0 +1,44 @@
598.4 +/*
598.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
598.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
598.7 + *
598.8 + * This code is free software; you can redistribute it and/or modify it
598.9 + * under the terms of the GNU General Public License version 2 only, as
598.10 + * published by the Free Software Foundation.
598.11 + *
598.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
598.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
598.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
598.15 + * version 2 for more details (a copy is included in the LICENSE file that
598.16 + * accompanied this code).
598.17 + *
598.18 + * You should have received a copy of the GNU General Public License version
598.19 + * 2 along with this work; if not, write to the Free Software Foundation,
598.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
598.21 + *
598.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
598.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
598.24 + * have any questions.
598.25 + */
598.26 +
598.27 +/*
598.28 + * @test
598.29 + * @bug 6795356
598.30 + * @summary Checks that SwingLazyValue class correclty works
598.31 + * @author Alexander Potochkin
598.32 + * @run main SwingLazyValueTest
598.33 + */
598.34 +
598.35 +import sun.swing.SwingLazyValue;
598.36 +
598.37 +import javax.swing.*;
598.38 +
598.39 +public class SwingLazyValueTest {
598.40 +
598.41 + public static void main(String[] args) throws Exception {
598.42 + if(new SwingLazyValue("javax.swing.JTable$DoubleRenderer").
598.43 + createValue(null) == null) {
598.44 + throw new RuntimeException("SwingLazyValue doesn't work");
598.45 + }
598.46 + }
598.47 +}
599.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
599.2 +++ b/test/javax/swing/UIDefaults/6795356/TableTest.java Wed Nov 25 11:08:25 2009 -0800
599.3 @@ -0,0 +1,52 @@
599.4 +/*
599.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
599.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
599.7 + *
599.8 + * This code is free software; you can redistribute it and/or modify it
599.9 + * under the terms of the GNU General Public License version 2 only, as
599.10 + * published by the Free Software Foundation.
599.11 + *
599.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
599.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
599.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
599.15 + * version 2 for more details (a copy is included in the LICENSE file that
599.16 + * accompanied this code).
599.17 + *
599.18 + * You should have received a copy of the GNU General Public License version
599.19 + * 2 along with this work; if not, write to the Free Software Foundation,
599.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
599.21 + *
599.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
599.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
599.24 + * have any questions.
599.25 + */
599.26 +
599.27 +/*
599.28 + * @test
599.29 + * @bug 6795356
599.30 + * @summary Checks that SwingLazyValue class correclty works
599.31 + * @author Alexander Potochkin
599.32 + * @run main/othervm TableTest
599.33 + */
599.34 +
599.35 +import sun.applet.AppletSecurity;
599.36 +
599.37 +import javax.swing.*;
599.38 +import javax.swing.table.TableCellEditor;
599.39 +import java.awt.*;
599.40 +
599.41 +public class TableTest {
599.42 +
599.43 + public static void main(String[] args) throws Exception {
599.44 +
599.45 + KeyboardFocusManager.getCurrentKeyboardFocusManager();
599.46 + System.setSecurityManager(new AppletSecurity());
599.47 +
599.48 + JTable table = new JTable();
599.49 + TableCellEditor de = table.getDefaultEditor(Double.class);
599.50 + if (de == null) {
599.51 + throw new RuntimeException("Table default editor is null");
599.52 + }
599.53 + }
599.54 +}
599.55 +
600.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
600.2 +++ b/test/javax/swing/UIDefaults/6795356/bug6795356.java Wed Nov 25 11:08:25 2009 -0800
600.3 @@ -0,0 +1,100 @@
600.4 +/*
600.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
600.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
600.7 + *
600.8 + * This code is free software; you can redistribute it and/or modify it
600.9 + * under the terms of the GNU General Public License version 2 only, as
600.10 + * published by the Free Software Foundation.
600.11 + *
600.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
600.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
600.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
600.15 + * version 2 for more details (a copy is included in the LICENSE file that
600.16 + * accompanied this code).
600.17 + *
600.18 + * You should have received a copy of the GNU General Public License version
600.19 + * 2 along with this work; if not, write to the Free Software Foundation,
600.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
600.21 + *
600.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
600.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
600.24 + * have any questions.
600.25 + */
600.26 +
600.27 +/*
600.28 + * @test
600.29 + * @bug 6795356
600.30 + * @summary Leak caused by javax.swing.UIDefaults.ProxyLazyValue.acc
600.31 + * @author Alexander Potochkin
600.32 + * @run main bug6795356
600.33 + */
600.34 +
600.35 +import java.lang.ref.WeakReference;
600.36 +import java.security.ProtectionDomain;
600.37 +import java.security.AccessController;
600.38 +import java.security.PrivilegedAction;
600.39 +import java.security.AccessControlContext;
600.40 +import java.util.LinkedList;
600.41 +import java.util.List;
600.42 +import javax.swing.*;
600.43 +
600.44 +public class bug6795356 {
600.45 + volatile static WeakReference<ProtectionDomain> weakRef;
600.46 +
600.47 + public static void main(String[] args) throws Exception {
600.48 +
600.49 + ProtectionDomain domain = new ProtectionDomain(null, null);
600.50 +
600.51 + AccessController.doPrivileged(new PrivilegedAction<Object>() {
600.52 + public Object run() {
600.53 +
600.54 + // this initialize ProxyLazyValues
600.55 + UIManager.getLookAndFeel();
600.56 +
600.57 + return null;
600.58 + }
600.59 + }, new AccessControlContext(new ProtectionDomain[]{domain}));
600.60 +
600.61 + weakRef = new WeakReference<ProtectionDomain>(domain);
600.62 + domain = null;
600.63 +
600.64 + // Generate OutOfMemory and check the weak ref
600.65 + generateOOME();
600.66 +
600.67 + if (weakRef.get() != null) {
600.68 + throw new RuntimeException("Memory leak found!");
600.69 + }
600.70 + System.out.println("Test passed");
600.71 + }
600.72 +
600.73 + static void generateOOME() {
600.74 + List<Object> bigLeak = new LinkedList<Object>();
600.75 + boolean oome = false;
600.76 + System.out.print("Filling the heap");
600.77 + try {
600.78 + for(int i = 0; true ; i++) {
600.79 + // Now, use up all RAM
600.80 + bigLeak.add(new byte[1024 * 1024]);
600.81 + System.out.print(".");
600.82 +
600.83 + // Give the GC a change at that weakref
600.84 + if (i % 10 == 0) {
600.85 + System.gc();
600.86 + try {
600.87 + Thread.sleep(100);
600.88 + } catch (InterruptedException e) {
600.89 + e.printStackTrace();
600.90 + }
600.91 + }
600.92 + }
600.93 + } catch (OutOfMemoryError e) {
600.94 + bigLeak = null;
600.95 + oome = true;
600.96 + }
600.97 + System.out.println("");
600.98 + if (!oome) {
600.99 + throw new RuntimeException("Problem with test case - never got OOME");
600.100 + }
600.101 + System.out.println("Got OOME");
600.102 + }
600.103 +}
601.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
601.2 +++ b/test/javax/swing/UIManager/Test6657026.java Wed Nov 25 11:08:25 2009 -0800
601.3 @@ -0,0 +1,59 @@
601.4 +/*
601.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
601.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
601.7 + *
601.8 + * This code is free software; you can redistribute it and/or modify it
601.9 + * under the terms of the GNU General Public License version 2 only, as
601.10 + * published by the Free Software Foundation.
601.11 + *
601.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
601.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
601.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
601.15 + * version 2 for more details (a copy is included in the LICENSE file that
601.16 + * accompanied this code).
601.17 + *
601.18 + * You should have received a copy of the GNU General Public License version
601.19 + * 2 along with this work; if not, write to the Free Software Foundation,
601.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
601.21 + *
601.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
601.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
601.24 + * have any questions.
601.25 + */
601.26 +
601.27 +/*
601.28 + * @test
601.29 + * @bug 6657026
601.30 + * @summary Tests shared UIManager in different application contexts
601.31 + * @author Sergey Malenkov
601.32 + */
601.33 +
601.34 +import sun.awt.SunToolkit;
601.35 +
601.36 +import javax.swing.UIManager;
601.37 +import javax.swing.UIManager.LookAndFeelInfo;
601.38 +
601.39 +public class Test6657026 implements Runnable {
601.40 +
601.41 + public static void main(String[] args) throws Exception {
601.42 + if (UIManager.getInstalledLookAndFeels().length == 0) {
601.43 + throw new Error("unexpected amount of look&feels");
601.44 + }
601.45 + UIManager.setInstalledLookAndFeels(new LookAndFeelInfo[0]);
601.46 + if (UIManager.getInstalledLookAndFeels().length != 0) {
601.47 + throw new Error("unexpected amount of look&feels");
601.48 + }
601.49 +
601.50 + ThreadGroup group = new ThreadGroup("$$$");
601.51 + Thread thread = new Thread(group, new Test6657026());
601.52 + thread.start();
601.53 + thread.join();
601.54 + }
601.55 +
601.56 + public void run() {
601.57 + SunToolkit.createNewAppContext();
601.58 + if (UIManager.getInstalledLookAndFeels().length == 0) {
601.59 + throw new Error("shared look&feels");
601.60 + }
601.61 + }
601.62 +}
602.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
602.2 +++ b/test/javax/swing/plaf/basic/BasicSplitPaneUI/Test6657026.java Wed Nov 25 11:08:25 2009 -0800
602.3 @@ -0,0 +1,82 @@
602.4 +/*
602.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
602.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
602.7 + *
602.8 + * This code is free software; you can redistribute it and/or modify it
602.9 + * under the terms of the GNU General Public License version 2 only, as
602.10 + * published by the Free Software Foundation.
602.11 + *
602.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
602.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
602.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
602.15 + * version 2 for more details (a copy is included in the LICENSE file that
602.16 + * accompanied this code).
602.17 + *
602.18 + * You should have received a copy of the GNU General Public License version
602.19 + * 2 along with this work; if not, write to the Free Software Foundation,
602.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
602.21 + *
602.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
602.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
602.24 + * have any questions.
602.25 + */
602.26 +
602.27 +/*
602.28 + * @test
602.29 + * @bug 6657026
602.30 + * @summary Tests shared BasicSplitPaneUI in different application contexts
602.31 + * @author Sergey Malenkov
602.32 + */
602.33 +
602.34 +import sun.awt.SunToolkit;
602.35 +
602.36 +import java.awt.event.ActionEvent;
602.37 +import java.util.Set;
602.38 +import javax.swing.JSplitPane;
602.39 +import javax.swing.plaf.basic.BasicSplitPaneUI;
602.40 +
602.41 +public class Test6657026 extends BasicSplitPaneUI implements Runnable {
602.42 +
602.43 + public static void main(String[] args) throws InterruptedException {
602.44 + if (new JSplitPane().getFocusTraversalKeys(0).isEmpty()){
602.45 + throw new Error("unexpected traversal keys");
602.46 + }
602.47 + new JSplitPane() {
602.48 + public void setFocusTraversalKeys(int id, Set keystrokes) {
602.49 + keystrokes.clear();
602.50 + super.setFocusTraversalKeys(id, keystrokes);
602.51 + }
602.52 + };
602.53 + if (new JSplitPane().getFocusTraversalKeys(0).isEmpty()) {
602.54 + throw new Error("shared traversal keys");
602.55 + }
602.56 + KEYBOARD_DIVIDER_MOVE_OFFSET = -KEYBOARD_DIVIDER_MOVE_OFFSET;
602.57 +
602.58 + ThreadGroup group = new ThreadGroup("$$$");
602.59 + Thread thread = new Thread(group, new Test6657026());
602.60 + thread.start();
602.61 + thread.join();
602.62 + }
602.63 +
602.64 + public void run() {
602.65 + SunToolkit.createNewAppContext();
602.66 + if (new JSplitPane().getFocusTraversalKeys(0).isEmpty()) {
602.67 + throw new Error("shared traversal keys");
602.68 + }
602.69 + JSplitPane pane = new JSplitPane();
602.70 + pane.setUI(this);
602.71 +
602.72 + createFocusListener().focusGained(null); // allows actions
602.73 + test(pane, "positiveIncrement", 3);
602.74 + test(pane, "negativeIncrement", 0);
602.75 + }
602.76 +
602.77 + private static void test(JSplitPane pane, String action, int expected) {
602.78 + ActionEvent event = new ActionEvent(pane, expected, action);
602.79 + pane.getActionMap().get(action).actionPerformed(event);
602.80 + int actual = pane.getDividerLocation();
602.81 + if (actual != expected) {
602.82 + throw new Error(actual + ", but expected " + expected);
602.83 + }
602.84 + }
602.85 +}
603.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
603.2 +++ b/test/javax/swing/plaf/metal/MetalBorders/Test6657026.java Wed Nov 25 11:08:25 2009 -0800
603.3 @@ -0,0 +1,91 @@
603.4 +/*
603.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
603.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
603.7 + *
603.8 + * This code is free software; you can redistribute it and/or modify it
603.9 + * under the terms of the GNU General Public License version 2 only, as
603.10 + * published by the Free Software Foundation.
603.11 + *
603.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
603.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
603.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
603.15 + * version 2 for more details (a copy is included in the LICENSE file that
603.16 + * accompanied this code).
603.17 + *
603.18 + * You should have received a copy of the GNU General Public License version
603.19 + * 2 along with this work; if not, write to the Free Software Foundation,
603.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
603.21 + *
603.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
603.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
603.24 + * have any questions.
603.25 + */
603.26 +
603.27 +/*
603.28 + * @test
603.29 + * @bug 6657026
603.30 + * @summary Tests constancy of borders
603.31 + * @author Sergey Malenkov
603.32 + */
603.33 +
603.34 +import java.awt.Insets;
603.35 +import javax.swing.border.Border;
603.36 +import javax.swing.plaf.metal.MetalBorders.ButtonBorder;
603.37 +import javax.swing.plaf.metal.MetalBorders.MenuBarBorder;
603.38 +import javax.swing.plaf.metal.MetalBorders.MenuItemBorder;
603.39 +import javax.swing.plaf.metal.MetalBorders.PopupMenuBorder;
603.40 +
603.41 +public class Test6657026 {
603.42 +
603.43 + private static final Insets NEGATIVE = new Insets(Integer.MIN_VALUE,
603.44 + Integer.MIN_VALUE,
603.45 + Integer.MIN_VALUE,
603.46 + Integer.MIN_VALUE);
603.47 +
603.48 + public static void main(String[] args) {
603.49 + new ButtonBorder() {{borderInsets = NEGATIVE;}};
603.50 + new MenuBarBorder() {{borderInsets = NEGATIVE;}};
603.51 + new MenuItemBorder() {{borderInsets = NEGATIVE;}};
603.52 + new PopupMenuBorder() {{borderInsets = NEGATIVE;}};
603.53 +
603.54 + test(create("ButtonBorder"));
603.55 + test(create("MenuBarBorder"));
603.56 + test(create("MenuItemBorder"));
603.57 + test(create("PopupMenuBorder"));
603.58 +
603.59 + test(create("Flush3DBorder"));
603.60 + test(create("InternalFrameBorder"));
603.61 + // NOT USED: test(create("FrameBorder"));
603.62 + // NOT USED: test(create("DialogBorder"));
603.63 + test(create("PaletteBorder"));
603.64 + test(create("OptionDialogBorder"));
603.65 + test(create("ScrollPaneBorder"));
603.66 + }
603.67 +
603.68 + private static Border create(String name) {
603.69 + try {
603.70 + name = "javax.swing.plaf.metal.MetalBorders$" + name;
603.71 + return (Border) Class.forName(name).newInstance();
603.72 + }
603.73 + catch (Exception exception) {
603.74 + throw new Error("unexpected exception", exception);
603.75 + }
603.76 + }
603.77 +
603.78 + private static void test(Border border) {
603.79 + Insets actual = border.getBorderInsets(null);
603.80 + if (NEGATIVE.equals(actual)) {
603.81 + throw new Error("unexpected insets in " + border.getClass());
603.82 + }
603.83 + Insets expected = (Insets) actual.clone();
603.84 + // modify
603.85 + actual.top++;
603.86 + actual.left++;
603.87 + actual.right++;
603.88 + actual.bottom++;
603.89 + // validate
603.90 + if (!expected.equals(border.getBorderInsets(null))) {
603.91 + throw new Error("shared insets in " + border.getClass());
603.92 + }
603.93 + }
603.94 +}
604.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
604.2 +++ b/test/javax/swing/plaf/metal/MetalBumps/Test6657026.java Wed Nov 25 11:08:25 2009 -0800
604.3 @@ -0,0 +1,238 @@
604.4 +/*
604.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
604.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
604.7 + *
604.8 + * This code is free software; you can redistribute it and/or modify it
604.9 + * under the terms of the GNU General Public License version 2 only, as
604.10 + * published by the Free Software Foundation.
604.11 + *
604.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
604.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
604.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
604.15 + * version 2 for more details (a copy is included in the LICENSE file that
604.16 + * accompanied this code).
604.17 + *
604.18 + * You should have received a copy of the GNU General Public License version
604.19 + * 2 along with this work; if not, write to the Free Software Foundation,
604.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
604.21 + *
604.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
604.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
604.24 + * have any questions.
604.25 + */
604.26 +
604.27 +/*
604.28 + * @test
604.29 + * @bug 6657026
604.30 + * @summary Tests shared MetalBumps in different application contexts
604.31 + * @author Sergey Malenkov
604.32 + */
604.33 +
604.34 +import sun.awt.SunToolkit;
604.35 +
604.36 +import java.awt.Color;
604.37 +import java.awt.Component;
604.38 +import java.awt.Font;
604.39 +import java.awt.FontMetrics;
604.40 +import java.awt.Graphics;
604.41 +import java.awt.Image;
604.42 +import java.awt.Rectangle;
604.43 +import java.awt.Shape;
604.44 +import java.awt.image.BufferedImage;
604.45 +import java.awt.image.ImageObserver;
604.46 +import java.text.AttributedCharacterIterator;
604.47 +import javax.swing.Icon;
604.48 +import javax.swing.plaf.metal.MetalBorders.ToolBarBorder;
604.49 +
604.50 +public class Test6657026 extends ToolBarBorder implements Runnable {
604.51 +
604.52 + public static void main(String[] args) throws Exception {
604.53 + new Test6657026().test();
604.54 +
604.55 + ThreadGroup group = new ThreadGroup("$$$");
604.56 + Thread thread = new Thread(group, new Test6657026());
604.57 + thread.start();
604.58 + thread.join();
604.59 + }
604.60 +
604.61 + public void run() {
604.62 + SunToolkit.createNewAppContext();
604.63 + test();
604.64 + }
604.65 +
604.66 + private void test() {
604.67 + MyGraphics mg = new MyGraphics();
604.68 + Icon icon = bumps;
604.69 + icon.paintIcon(mg.component, mg, 0, 0);
604.70 + if (mg.image != null) {
604.71 + boolean failed = true;
604.72 + int value = mg.image.getRGB(0, 0);
604.73 + for (int x = 0; x < mg.image.getWidth(); x++) {
604.74 + for (int y = 0; y < mg.image.getHeight(); y++) {
604.75 + int current = mg.image.getRGB(x, y);
604.76 + if (current != value) {
604.77 + mg.image.setRGB(x, y, value);
604.78 + failed = false;
604.79 + }
604.80 +
604.81 + }
604.82 + }
604.83 + if (failed) {
604.84 + throw new Error("shared metal bumps");
604.85 + }
604.86 + }
604.87 + }
604.88 +
604.89 + private static class MyGraphics extends Graphics {
604.90 +
604.91 + private final Component component = new Component() {};
604.92 + private BufferedImage image;
604.93 +
604.94 + public Graphics create() {
604.95 + return null; // TODO: check
604.96 + }
604.97 +
604.98 + public void translate(int x, int y) {
604.99 + // TODO: check
604.100 + }
604.101 +
604.102 + public Color getColor() {
604.103 + return null; // TODO: check
604.104 + }
604.105 +
604.106 + public void setColor(Color color) {
604.107 + // TODO: check
604.108 + }
604.109 +
604.110 + public void setPaintMode() {
604.111 + // TODO: check
604.112 + }
604.113 +
604.114 + public void setXORMode(Color c1) {
604.115 + // TODO: check
604.116 + }
604.117 +
604.118 + public Font getFont() {
604.119 + return null; // TODO: check
604.120 + }
604.121 +
604.122 + public void setFont(Font font) {
604.123 + // TODO: check
604.124 + }
604.125 +
604.126 + public FontMetrics getFontMetrics(Font font) {
604.127 + return null; // TODO: check
604.128 + }
604.129 +
604.130 + public Rectangle getClipBounds() {
604.131 + return null; // TODO: check
604.132 + }
604.133 +
604.134 + public void clipRect(int x, int y, int width, int height) {
604.135 + // TODO: check
604.136 + }
604.137 +
604.138 + public void setClip(int x, int y, int width, int height) {
604.139 + // TODO: check
604.140 + }
604.141 +
604.142 + public Shape getClip() {
604.143 + return null; // TODO: check
604.144 + }
604.145 +
604.146 + public void setClip(Shape clip) {
604.147 + // TODO: check
604.148 + }
604.149 +
604.150 + public void copyArea(int x, int y, int width, int height, int dx, int dy) {
604.151 + // TODO: check
604.152 + }
604.153 +
604.154 + public void drawLine(int x1, int y1, int x2, int y2) {
604.155 + // TODO: check
604.156 + }
604.157 +
604.158 + public void fillRect(int x, int y, int width, int height) {
604.159 + // TODO: check
604.160 + }
604.161 +
604.162 + public void clearRect(int x, int y, int width, int height) {
604.163 + // TODO: check
604.164 + }
604.165 +
604.166 + public void drawRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
604.167 + // TODO: check
604.168 + }
604.169 +
604.170 + public void fillRoundRect(int x, int y, int width, int height, int arcWidth, int arcHeight) {
604.171 + // TODO: check
604.172 + }
604.173 +
604.174 + public void drawOval(int x, int y, int width, int height) {
604.175 + // TODO: check
604.176 + }
604.177 +
604.178 + public void fillOval(int x, int y, int width, int height) {
604.179 + // TODO: check
604.180 + }
604.181 +
604.182 + public void drawArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
604.183 + // TODO: check
604.184 + }
604.185 +
604.186 + public void fillArc(int x, int y, int width, int height, int startAngle, int arcAngle) {
604.187 + // TODO: check
604.188 + }
604.189 +
604.190 + public void drawPolyline(int[] xPoints, int[] yPoints, int nPoints) {
604.191 + // TODO: check
604.192 + }
604.193 +
604.194 + public void drawPolygon(int[] xPoints, int[] yPoints, int nPoints) {
604.195 + // TODO: check
604.196 + }
604.197 +
604.198 + public void fillPolygon(int[] xPoints, int[] yPoints, int nPoints) {
604.199 + // TODO: check
604.200 + }
604.201 +
604.202 + public void drawString(String str, int x, int y) {
604.203 + // TODO: check
604.204 + }
604.205 +
604.206 + public void drawString(AttributedCharacterIterator iterator, int x, int y) {
604.207 + // TODO: check
604.208 + }
604.209 +
604.210 + public boolean drawImage(Image img, int x, int y, ImageObserver observer) {
604.211 + return false; // TODO: check
604.212 + }
604.213 +
604.214 + public boolean drawImage(Image img, int x, int y, int width, int height, ImageObserver observer) {
604.215 + return false; // TODO: check
604.216 + }
604.217 +
604.218 + public boolean drawImage(Image img, int x, int y, Color bgcolor, ImageObserver observer) {
604.219 + return false; // TODO: check
604.220 + }
604.221 +
604.222 + public boolean drawImage(Image img, int x, int y, int width, int height, Color bgcolor, ImageObserver observer) {
604.223 + return false; // TODO: check
604.224 + }
604.225 +
604.226 + public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, ImageObserver observer) {
604.227 + if (img instanceof BufferedImage) {
604.228 + this.image = (BufferedImage) img;
604.229 + }
604.230 + return false; // TODO: check
604.231 + }
604.232 +
604.233 + public boolean drawImage(Image img, int dx1, int dy1, int dx2, int dy2, int sx1, int sy1, int sx2, int sy2, Color bgcolor, ImageObserver observer) {
604.234 + return false; // TODO: check
604.235 + }
604.236 +
604.237 + public void dispose() {
604.238 + // TODO: check
604.239 + }
604.240 + }
604.241 +}
605.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
605.2 +++ b/test/javax/swing/plaf/metal/MetalInternalFrameUI/Test6657026.java Wed Nov 25 11:08:25 2009 -0800
605.3 @@ -0,0 +1,60 @@
605.4 +/*
605.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
605.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
605.7 + *
605.8 + * This code is free software; you can redistribute it and/or modify it
605.9 + * under the terms of the GNU General Public License version 2 only, as
605.10 + * published by the Free Software Foundation.
605.11 + *
605.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
605.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
605.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
605.15 + * version 2 for more details (a copy is included in the LICENSE file that
605.16 + * accompanied this code).
605.17 + *
605.18 + * You should have received a copy of the GNU General Public License version
605.19 + * 2 along with this work; if not, write to the Free Software Foundation,
605.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
605.21 + *
605.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
605.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
605.24 + * have any questions.
605.25 + */
605.26 +
605.27 +/*
605.28 + * @test
605.29 + * @bug 6657026
605.30 + * @summary Tests shared MetalInternalFrameUI in different application contexts
605.31 + * @author Sergey Malenkov
605.32 + */
605.33 +
605.34 +import sun.awt.SunToolkit;
605.35 +
605.36 +import javax.swing.JInternalFrame;
605.37 +import javax.swing.JPanel;
605.38 +import javax.swing.UIManager;
605.39 +import javax.swing.plaf.metal.MetalInternalFrameUI;
605.40 +import javax.swing.plaf.metal.MetalLookAndFeel;
605.41 +
605.42 +public class Test6657026 extends MetalInternalFrameUI implements Runnable {
605.43 +
605.44 + public static void main(String[] args) throws Exception {
605.45 + UIManager.setLookAndFeel(new MetalLookAndFeel());
605.46 +
605.47 + ThreadGroup group = new ThreadGroup("$$$");
605.48 + Thread thread = new Thread(group, new Test6657026());
605.49 + thread.start();
605.50 + thread.join();
605.51 +
605.52 + new JInternalFrame().setContentPane(new JPanel());
605.53 + }
605.54 +
605.55 + public Test6657026() {
605.56 + super(null);
605.57 + }
605.58 +
605.59 + public void run() {
605.60 + SunToolkit.createNewAppContext();
605.61 + IS_PALETTE = JInternalFrame.CONTENT_PANE_PROPERTY;
605.62 + }
605.63 +}
606.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
606.2 +++ b/test/javax/swing/plaf/metal/MetalSliderUI/Test6657026.java Wed Nov 25 11:08:25 2009 -0800
606.3 @@ -0,0 +1,67 @@
606.4 +/*
606.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
606.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
606.7 + *
606.8 + * This code is free software; you can redistribute it and/or modify it
606.9 + * under the terms of the GNU General Public License version 2 only, as
606.10 + * published by the Free Software Foundation.
606.11 + *
606.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
606.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
606.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
606.15 + * version 2 for more details (a copy is included in the LICENSE file that
606.16 + * accompanied this code).
606.17 + *
606.18 + * You should have received a copy of the GNU General Public License version
606.19 + * 2 along with this work; if not, write to the Free Software Foundation,
606.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
606.21 + *
606.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
606.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
606.24 + * have any questions.
606.25 + */
606.26 +
606.27 +/*
606.28 + * @test
606.29 + * @bug 6657026
606.30 + * @summary Tests shared MetalSliderUI in different application contexts
606.31 + * @author Sergey Malenkov
606.32 + */
606.33 +
606.34 +import sun.awt.SunToolkit;
606.35 +
606.36 +import javax.swing.JSlider;
606.37 +import javax.swing.UIManager;
606.38 +import javax.swing.plaf.metal.MetalLookAndFeel;
606.39 +import javax.swing.plaf.metal.MetalSliderUI;
606.40 +
606.41 +public class Test6657026 extends MetalSliderUI implements Runnable {
606.42 +
606.43 + public static void main(String[] args) throws Exception {
606.44 + UIManager.setLookAndFeel(new MetalLookAndFeel());
606.45 + JSlider slider = new JSlider();
606.46 + test(slider);
606.47 +
606.48 + ThreadGroup group = new ThreadGroup("$$$");
606.49 + Thread thread = new Thread(group, new Test6657026());
606.50 + thread.start();
606.51 + thread.join();
606.52 +
606.53 + test(slider);
606.54 + }
606.55 +
606.56 + public void run() {
606.57 + SunToolkit.createNewAppContext();
606.58 + JSlider slider = new JSlider();
606.59 + test(slider);
606.60 + tickLength = -10000;
606.61 + }
606.62 +
606.63 + private static void test(JSlider slider) {
606.64 + MetalSliderUI ui = (MetalSliderUI) slider.getUI();
606.65 + int actual = ui.getTickLength();
606.66 + if (actual != 11) {
606.67 + throw new Error(actual + ", but expected 11");
606.68 + }
606.69 + }
606.70 +}
607.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
607.2 +++ b/test/start-Xvfb.sh Wed Nov 25 11:08:25 2009 -0800
607.3 @@ -0,0 +1,87 @@
607.4 +#!/bin/sh -f
607.5 +#
607.6 +# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
607.7 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
607.8 +#
607.9 +# This code is free software; you can redistribute it and/or modify it
607.10 +# under the terms of the GNU General Public License version 2 only, as
607.11 +# published by the Free Software Foundation. Sun designates this
607.12 +# particular file as subject to the "Classpath" exception as provided
607.13 +# by Sun in the LICENSE file that accompanied this code.
607.14 +#
607.15 +# This code is distributed in the hope that it will be useful, but WITHOUT
607.16 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
607.17 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
607.18 +# version 2 for more details (a copy is included in the LICENSE file that
607.19 +# accompanied this code).
607.20 +#
607.21 +# You should have received a copy of the GNU General Public License version
607.22 +# 2 along with this work; if not, write to the Free Software Foundation,
607.23 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
607.24 +#
607.25 +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
607.26 +# CA 95054 USA or visit www.sun.com if you need additional information or
607.27 +# have any questions.
607.28 +#
607.29 +
607.30 +#
607.31 +# Original Author: Tim Bell
607.32 +#
607.33 +usage() {
607.34 + echo "Starts up an Xvfb dummy X server with fvwm2 window manager"
607.35 + echo " usage:"
607.36 + echo " ${0} display_number_file"
607.37 + echo " display_number_file gets display number when it's ready"
607.38 + exit
607.39 + }
607.40 +#
607.41 +currentDir=`pwd`
607.42 +rm -f $1
607.43 +DD=":$$"
607.44 +DISPLAY=${DD}
607.45 +export DISPLAY
607.46 +cd /tmp
607.47 +#
607.48 +if [ ! -x "/usr/bin/X11/Xvfb" ]; then
607.49 + # We have Solaris-flavored X windows, and the /usr/openwin Xvfb is
607.50 + # a simple wrapper script around the Xsun server. Massage the
607.51 + # arguments: server number must be first; others are slightly
607.52 + # different.
607.53 + #
607.54 + # Also the default Visual Class (DirectColor) triggers an awt bug
607.55 + # (probably 4131533/6505852) and some tests will loop endlessly
607.56 + # when they hit the display. The workaround is:
607.57 + # 1) Ask for PseudoColor instead.
607.58 + # 2) Omit 32-bit depth.
607.59 + /usr/bin/nohup /usr/openwin/bin/Xvfb ${DISPLAY} -dev vfb screen 0 1280x1024x24 pixdepths 8 16 24 defclass PseudoColor > ${currentDir}/nohup.$$ 2>&1 &
607.60 +else
607.61 + # Linux...
607.62 + /usr/bin/nohup /usr/bin/X11/Xvfb -fbdir ${currentDir} -pixdepths 8 16 24 32 ${DISPLAY} > ${currentDir}/nohup.$$ 2>&1 &
607.63 +fi
607.64 +WM="/usr/bin/X11/fvwm2"
607.65 +if [ ! -x ${WM} ] ; then
607.66 + WM="/opt/sfw/bin/fvwm2"
607.67 +fi
607.68 +#
607.69 +# Wait for Xvfb to initialize:
607.70 +sleep 5
607.71 +#
607.72 +if [ -x "${WM}" ]; then
607.73 +# 2 JCK tests require a window manager
607.74 +# mwm fails (key name errors) and twm fails (hangs),
607.75 +# but fvwm2 works well.
607.76 + /usr/bin/nohup ${WM} -display ${DISPLAY} -replace -f /dev/null > ${currentDir}/nohup.$$ 2>&1 &
607.77 +else
607.78 + echo "Error: ${WM} not found"
607.79 + exit 1
607.80 +fi
607.81 +#
607.82 +# Wait some more to see if the xhost command gets through:
607.83 +sleep 10
607.84 +# Allow access to all - this is a brute force approach,
607.85 +# but I do not see how it could be a security problem...
607.86 +DISPLAY="${DD}" xhost +
607.87 +#
607.88 +echo "Virtual frame buffer started on ${DISPLAY}"
607.89 +echo "$$" > $1
607.90 +wait
608.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
608.2 +++ b/test/sun/java2d/pisces/Renderer/TestNPE.java Wed Nov 25 11:08:25 2009 -0800
608.3 @@ -0,0 +1,59 @@
608.4 +/*
608.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
608.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
608.7 + *
608.8 + * This code is free software; you can redistribute it and/or modify it
608.9 + * under the terms of the GNU General Public License version 2 only, as
608.10 + * published by the Free Software Foundation.
608.11 + *
608.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
608.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
608.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
608.15 + * version 2 for more details (a copy is included in the LICENSE file that
608.16 + * accompanied this code).
608.17 + *
608.18 + * You should have received a copy of the GNU General Public License version
608.19 + * 2 along with this work; if not, write to the Free Software Foundation,
608.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
608.21 + *
608.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
608.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
608.24 + * have any questions.
608.25 + */
608.26 +
608.27 +/**
608.28 + * @test
608.29 + * @bug 6887494
608.30 + *
608.31 + * @summary Verifies that no NullPointerException is thrown in Pisces Renderer
608.32 + * under certain circumstances.
608.33 + *
608.34 + * @run main TestNPE
608.35 + */
608.36 +
608.37 +import java.awt.*;
608.38 +import java.awt.geom.*;
608.39 +import java.awt.image.BufferedImage;
608.40 +
608.41 +public class TestNPE {
608.42 +
608.43 + private static void paint(Graphics g) {
608.44 + Graphics2D g2d = (Graphics2D) g;
608.45 + g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING,
608.46 + RenderingHints.VALUE_ANTIALIAS_ON);
608.47 + g2d.setClip(0, 0, 0, 0);
608.48 + g2d.setTransform(
608.49 + new AffineTransform(4.0f, 0.0f, 0.0f, 4.0f, -1248.0f, -744.0f));
608.50 + g2d.draw(new Line2D.Float(131.21428571428572f, 33.0f,
608.51 + 131.21428571428572f, 201.0f));
608.52 + }
608.53 +
608.54 + public static void main(String[] args) {
608.55 + BufferedImage im = new BufferedImage(100, 100,
608.56 + BufferedImage.TYPE_INT_ARGB);
608.57 +
608.58 + // Trigger exception in main thread.
608.59 + Graphics g = im.getGraphics();
608.60 + paint(g);
608.61 + }
608.62 +}
609.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
609.2 +++ b/test/sun/net/www/protocol/http/B6890349.java Wed Nov 25 11:08:25 2009 -0800
609.3 @@ -0,0 +1,68 @@
609.4 +/*
609.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
609.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
609.7 + *
609.8 + * This code is free software; you can redistribute it and/or modify it
609.9 + * under the terms of the GNU General Public License version 2 only, as
609.10 + * published by the Free Software Foundation.
609.11 + *
609.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
609.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
609.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
609.15 + * version 2 for more details (a copy is included in the LICENSE file that
609.16 + * accompanied this code).
609.17 + *
609.18 + * You should have received a copy of the GNU General Public License version
609.19 + * 2 along with this work; if not, write to the Free Software Foundation,
609.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
609.21 + *
609.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
609.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
609.24 + * have any questions.
609.25 + */
609.26 +/**
609.27 + * @test
609.28 + * @bug 6890349
609.29 + * @run main/othervm B6890349
609.30 + * @summary Light weight HTTP server
609.31 + */
609.32 +
609.33 +import java.net.*;
609.34 +import java.io.*;
609.35 +
609.36 +public class B6890349 extends Thread {
609.37 + public static final void main(String[] args) throws Exception {
609.38 +
609.39 + try {
609.40 + ServerSocket server = new ServerSocket (0);
609.41 + int port = server.getLocalPort();
609.42 + System.out.println ("listening on " + port);
609.43 + B6890349 t = new B6890349 (server);
609.44 + t.start();
609.45 + URL u = new URL ("http://127.0.0.1:"+port+"/foo\nbar");
609.46 + HttpURLConnection urlc = (HttpURLConnection)u.openConnection ();
609.47 + InputStream is = urlc.getInputStream();
609.48 + throw new RuntimeException ("Test failed");
609.49 + } catch (IOException e) {
609.50 + System.out.println ("OK");
609.51 + }
609.52 + }
609.53 +
609.54 + ServerSocket server;
609.55 +
609.56 + B6890349 (ServerSocket server) {
609.57 + this.server = server;
609.58 + }
609.59 +
609.60 + String resp = "HTTP/1.1 200 Ok\r\nContent-length: 0\r\n\r\n";
609.61 +
609.62 + public void run () {
609.63 + try {
609.64 + Socket s = server.accept ();
609.65 + OutputStream os = s.getOutputStream();
609.66 + os.write (resp.getBytes());
609.67 + } catch (IOException e) {
609.68 + System.out.println (e);
609.69 + }
609.70 + }
609.71 +}
610.1 --- a/test/sun/security/krb5/auto/Action.java Mon Nov 23 10:04:47 2009 +0000
610.2 +++ b/test/sun/security/krb5/auto/Action.java Wed Nov 25 11:08:25 2009 -0800
610.3 @@ -30,4 +30,3 @@
610.4 */
610.5 byte[] run(Context s, byte[] input) throws Exception;
610.6 }
610.7 -
611.1 --- a/test/sun/security/krb5/auto/HttpNegotiateServer.java Mon Nov 23 10:04:47 2009 +0000
611.2 +++ b/test/sun/security/krb5/auto/HttpNegotiateServer.java Wed Nov 25 11:08:25 2009 -0800
611.3 @@ -302,4 +302,3 @@
611.4 }
611.5 }
611.6 }
611.7 -
612.1 --- a/test/sun/security/krb5/auto/KDC.java Mon Nov 23 10:04:47 2009 +0000
612.2 +++ b/test/sun/security/krb5/auto/KDC.java Wed Nov 25 11:08:25 2009 -0800
612.3 @@ -466,7 +466,17 @@
612.4 // the krb5.conf config file would be loaded.
612.5 Method stringToKey = EncryptionKey.class.getDeclaredMethod("stringToKey", char[].class, String.class, byte[].class, Integer.TYPE);
612.6 stringToKey.setAccessible(true);
612.7 - return new EncryptionKey((byte[]) stringToKey.invoke(null, getPassword(p), getSalt(p), null, etype), etype, null);
612.8 + Integer kvno = null;
612.9 + // For service whose password ending with a number, use it as kvno
612.10 + if (p.toString().indexOf('/') >= 0) {
612.11 + char[] pass = getPassword(p);
612.12 + if (Character.isDigit(pass[pass.length-1])) {
612.13 + kvno = pass[pass.length-1] - '0';
612.14 + }
612.15 + }
612.16 + return new EncryptionKey((byte[]) stringToKey.invoke(
612.17 + null, getPassword(p), getSalt(p), null, etype),
612.18 + etype, kvno);
612.19 } catch (InvocationTargetException ex) {
612.20 KrbException ke = (KrbException)ex.getCause();
612.21 throw ke;
613.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
613.2 +++ b/test/sun/security/krb5/auto/MoreKvno.java Wed Nov 25 11:08:25 2009 -0800
613.3 @@ -0,0 +1,70 @@
613.4 +/*
613.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
613.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
613.7 + *
613.8 + * This code is free software; you can redistribute it and/or modify it
613.9 + * under the terms of the GNU General Public License version 2 only, as
613.10 + * published by the Free Software Foundation.
613.11 + *
613.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
613.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
613.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
613.15 + * version 2 for more details (a copy is included in the LICENSE file that
613.16 + * accompanied this code).
613.17 + *
613.18 + * You should have received a copy of the GNU General Public License version
613.19 + * 2 along with this work; if not, write to the Free Software Foundation,
613.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
613.21 + *
613.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
613.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
613.24 + * have any questions.
613.25 + */
613.26 +
613.27 +/*
613.28 + * @test
613.29 + * @bug 6893158
613.30 + * @summary AP_REQ check should use key version number
613.31 + */
613.32 +
613.33 +import sun.security.jgss.GSSUtil;
613.34 +import sun.security.krb5.PrincipalName;
613.35 +import sun.security.krb5.internal.ktab.KeyTab;
613.36 +
613.37 +public class MoreKvno {
613.38 +
613.39 + public static void main(String[] args)
613.40 + throws Exception {
613.41 +
613.42 + OneKDC kdc = new OneKDC(null);
613.43 + kdc.writeJAASConf();
613.44 +
613.45 + // Rewrite keytab, 3 set of keys with different kvno
613.46 + KeyTab ktab = KeyTab.create(OneKDC.KTAB);
613.47 + PrincipalName p = new PrincipalName(OneKDC.SERVER+"@"+OneKDC.REALM, PrincipalName.KRB_NT_SRV_HST);
613.48 + ktab.addEntry(p, "pass0".toCharArray(), 0);
613.49 + ktab.addEntry(p, "pass2".toCharArray(), 2);
613.50 + ktab.addEntry(p, "pass1".toCharArray(), 1);
613.51 + ktab.save();
613.52 +
613.53 + kdc.addPrincipal(OneKDC.SERVER, "pass1".toCharArray());
613.54 + go(OneKDC.SERVER, "com.sun.security.jgss.krb5.accept");
613.55 + kdc.addPrincipal(OneKDC.SERVER, "pass2".toCharArray());
613.56 + // "server" initiate also, check pass2 is used at authentication
613.57 + go(OneKDC.SERVER, "server");
613.58 + }
613.59 +
613.60 + static void go(String server, String entry) throws Exception {
613.61 + Context c, s;
613.62 + c = Context.fromUserPass("dummy", "bogus".toCharArray(), false);
613.63 + s = Context.fromJAAS(entry);
613.64 +
613.65 + c.startAsClient(server, GSSUtil.GSS_KRB5_MECH_OID);
613.66 + s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
613.67 +
613.68 + Context.handshake(c, s);
613.69 +
613.70 + s.dispose();
613.71 + c.dispose();
613.72 + }
613.73 +}
614.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
614.2 +++ b/test/sun/security/krb5/auto/SSL.java Wed Nov 25 11:08:25 2009 -0800
614.3 @@ -0,0 +1,168 @@
614.4 +/*
614.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
614.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
614.7 + *
614.8 + * This code is free software; you can redistribute it and/or modify it
614.9 + * under the terms of the GNU General Public License version 2 only, as
614.10 + * published by the Free Software Foundation.
614.11 + *
614.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
614.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
614.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
614.15 + * version 2 for more details (a copy is included in the LICENSE file that
614.16 + * accompanied this code).
614.17 + *
614.18 + * You should have received a copy of the GNU General Public License version
614.19 + * 2 along with this work; if not, write to the Free Software Foundation,
614.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
614.21 + *
614.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
614.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
614.24 + * have any questions.
614.25 + */
614.26 +
614.27 +/*
614.28 + * @test
614.29 + * @bug 6894643
614.30 + * @summary Test JSSE Kerberos ciphersuite
614.31 + */
614.32 +import java.io.*;
614.33 +import java.net.InetAddress;
614.34 +import javax.net.ssl.*;
614.35 +import java.security.Principal;
614.36 +import java.util.Date;
614.37 +import sun.security.jgss.GSSUtil;
614.38 +
614.39 +public class SSL {
614.40 +
614.41 + private static final String KRB5_CIPHER = "TLS_KRB5_WITH_3DES_EDE_CBC_SHA";
614.42 + private static final int PORT = 4569;
614.43 + private static final int LOOP_LIMIT = 1;
614.44 + private static final char[] PASS = "secret".toCharArray();
614.45 + private static int loopCount = 0;
614.46 +
614.47 + private static String SERVER;
614.48 +
614.49 + public static void main(String[] args) throws Exception {
614.50 +
614.51 + KDC kdc = KDC.create(OneKDC.REALM);
614.52 + // Run this after KDC, so our own DNS service can be started
614.53 + try {
614.54 + SERVER = InetAddress.getLocalHost().getHostName();
614.55 + } catch (java.net.UnknownHostException e) {
614.56 + SERVER = "localhost";
614.57 + }
614.58 +
614.59 + kdc.addPrincipal(OneKDC.USER, OneKDC.PASS);
614.60 + kdc.addPrincipalRandKey("krbtgt/" + OneKDC.REALM);
614.61 + kdc.addPrincipal("host/" + SERVER, PASS);
614.62 + KDC.saveConfig(OneKDC.KRB5_CONF, kdc);
614.63 + System.setProperty("java.security.krb5.conf", OneKDC.KRB5_CONF);
614.64 +
614.65 + final Context c = Context.fromUserPass(OneKDC.USER, OneKDC.PASS, false);
614.66 + final Context s = Context.fromUserPass("host/" + SERVER, PASS, true);
614.67 +
614.68 + c.startAsClient("host/" + SERVER, GSSUtil.GSS_KRB5_MECH_OID);
614.69 + s.startAsServer(GSSUtil.GSS_KRB5_MECH_OID);
614.70 +
614.71 + new Thread(new Runnable() {
614.72 + public void run() {
614.73 + try {
614.74 + s.doAs(new JsseServerAction(), null);
614.75 + } catch (Exception e) {
614.76 + e.printStackTrace();
614.77 + }
614.78 + }
614.79 + }).start();
614.80 +
614.81 + // Warm the server
614.82 + Thread.sleep(2000);
614.83 +
614.84 + c.doAs(new JsseClientAction(), null);
614.85 + }
614.86 +
614.87 + // Following codes copied from
614.88 + // http://java.sun.com/javase/6/docs/technotes/guides/security/jgss/lab/part2.html#JSSE
614.89 + private static class JsseClientAction implements Action {
614.90 + public byte[] run(Context s, byte[] input) throws Exception {
614.91 + SSLSocketFactory sslsf =
614.92 + (SSLSocketFactory) SSLSocketFactory.getDefault();
614.93 + SSLSocket sslSocket = (SSLSocket) sslsf.createSocket(SERVER, PORT);
614.94 +
614.95 + // Enable only a KRB5 cipher suite.
614.96 + String enabledSuites[] = {KRB5_CIPHER};
614.97 + sslSocket.setEnabledCipherSuites(enabledSuites);
614.98 + // Should check for exception if enabledSuites is not supported
614.99 +
614.100 + BufferedReader in = new BufferedReader(new InputStreamReader(
614.101 + sslSocket.getInputStream()));
614.102 + BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
614.103 + sslSocket.getOutputStream()));
614.104 +
614.105 + String outStr = "Hello There!\n";
614.106 + out.write(outStr);
614.107 + out.flush();
614.108 + System.out.print("Sending " + outStr);
614.109 +
614.110 + String inStr = in.readLine();
614.111 + System.out.println("Received " + inStr);
614.112 +
614.113 + String cipherSuiteChosen = sslSocket.getSession().getCipherSuite();
614.114 + System.out.println("Cipher suite in use: " + cipherSuiteChosen);
614.115 + Principal self = sslSocket.getSession().getLocalPrincipal();
614.116 + System.out.println("I am: " + self.toString());
614.117 + Principal peer = sslSocket.getSession().getPeerPrincipal();
614.118 + System.out.println("Server is: " + peer.toString());
614.119 +
614.120 + sslSocket.close();
614.121 + return null;
614.122 + }
614.123 + }
614.124 +
614.125 + private static class JsseServerAction implements Action {
614.126 + public byte[] run(Context s, byte[] input) throws Exception {
614.127 + SSLServerSocketFactory sslssf =
614.128 + (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
614.129 + SSLServerSocket sslServerSocket =
614.130 + (SSLServerSocket) sslssf.createServerSocket(PORT);
614.131 +
614.132 + // Enable only a KRB5 cipher suite.
614.133 + String enabledSuites[] = {KRB5_CIPHER};
614.134 + sslServerSocket.setEnabledCipherSuites(enabledSuites);
614.135 + // Should check for exception if enabledSuites is not supported
614.136 +
614.137 + while (loopCount++ < LOOP_LIMIT) {
614.138 + System.out.println("Waiting for incoming connection...");
614.139 +
614.140 + SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
614.141 +
614.142 + System.out.println("Got connection from client "
614.143 + + sslSocket.getInetAddress());
614.144 +
614.145 + BufferedReader in = new BufferedReader(new InputStreamReader(
614.146 + sslSocket.getInputStream()));
614.147 + BufferedWriter out = new BufferedWriter(new OutputStreamWriter(
614.148 + sslSocket.getOutputStream()));
614.149 +
614.150 + String inStr = in.readLine();
614.151 + System.out.println("Received " + inStr);
614.152 +
614.153 + String outStr = inStr + " " + new Date().toString() + "\n";
614.154 + out.write(outStr);
614.155 + System.out.println("Sending " + outStr);
614.156 + out.flush();
614.157 +
614.158 + String cipherSuiteChosen =
614.159 + sslSocket.getSession().getCipherSuite();
614.160 + System.out.println("Cipher suite in use: " + cipherSuiteChosen);
614.161 + Principal self = sslSocket.getSession().getLocalPrincipal();
614.162 + System.out.println("I am: " + self.toString());
614.163 + Principal peer = sslSocket.getSession().getPeerPrincipal();
614.164 + System.out.println("Client is: " + peer.toString());
614.165 +
614.166 + sslSocket.close();
614.167 + }
614.168 + return null;
614.169 + }
614.170 + }
614.171 +}
615.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
615.2 +++ b/test/sun/security/provider/certpath/DisabledAlgorithms/CPBuilder.java Wed Nov 25 11:08:25 2009 -0800
615.3 @@ -0,0 +1,442 @@
615.4 +/*
615.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
615.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
615.7 + *
615.8 + * This code is free software; you can redistribute it and/or modify it
615.9 + * under the terms of the GNU General Public License version 2 only, as
615.10 + * published by the Free Software Foundation.
615.11 + *
615.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
615.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
615.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
615.15 + * version 2 for more details (a copy is included in the LICENSE file that
615.16 + * accompanied this code).
615.17 + *
615.18 + * You should have received a copy of the GNU General Public License version
615.19 + * 2 along with this work; if not, write to the Free Software Foundation,
615.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
615.21 + *
615.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
615.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
615.24 + * have any questions.
615.25 + */
615.26 +
615.27 +/**
615.28 + * @test
615.29 + *
615.30 + * @bug 6861062
615.31 + * @summary Disable MD2 support
615.32 + *
615.33 + * @run main/othervm CPBuilder trustAnchor_SHA1withRSA_1024 0 true
615.34 + * @run main/othervm CPBuilder trustAnchor_SHA1withRSA_512 0 true
615.35 + * @run main/othervm CPBuilder intermediate_SHA1withRSA_1024_1024 1 true
615.36 + * @run main/othervm CPBuilder intermediate_SHA1withRSA_1024_512 1 true
615.37 + * @run main/othervm CPBuilder intermediate_SHA1withRSA_512_1024 1 true
615.38 + * @run main/othervm CPBuilder intermediate_SHA1withRSA_512_512 1 true
615.39 + * @run main/othervm CPBuilder intermediate_MD2withRSA_1024_1024 1 false
615.40 + * @run main/othervm CPBuilder intermediate_MD2withRSA_1024_512 1 false
615.41 + * @run main/othervm CPBuilder endentiry_SHA1withRSA_1024_1024 2 true
615.42 + * @run main/othervm CPBuilder endentiry_SHA1withRSA_1024_512 2 true
615.43 + * @run main/othervm CPBuilder endentiry_SHA1withRSA_512_1024 2 true
615.44 + * @run main/othervm CPBuilder endentiry_SHA1withRSA_512_512 2 true
615.45 + * @run main/othervm CPBuilder endentiry_MD2withRSA_1024_1024 2 false
615.46 + * @run main/othervm CPBuilder endentiry_MD2withRSA_1024_512 2 false
615.47 + *
615.48 + * @author Xuelei Fan
615.49 + */
615.50 +
615.51 +import java.io.*;
615.52 +import java.net.SocketException;
615.53 +import java.util.*;
615.54 +import java.security.Security;
615.55 +import java.security.cert.*;
615.56 +import sun.security.util.DerInputStream;
615.57 +
615.58 +public class CPBuilder {
615.59 +
615.60 + // SHA1withRSA 1024
615.61 + static String trustAnchor_SHA1withRSA_1024 =
615.62 + "-----BEGIN CERTIFICATE-----\n" +
615.63 + "MIICPjCCAaegAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
615.64 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa\n" +
615.65 + "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB\n" +
615.66 + "AQUAA4GNADCBiQKBgQC8UdC863pFk1Rvd7xUYd60+e9KsLhb6SqOfU42ZA715FcH\n" +
615.67 + "E1TRvQPmYzAnHcO04TrWZQtO6E+E2RCmeBnetBvIMVka688QkO14wnrIrf2tRodd\n" +
615.68 + "rZNZEBzkX+zyXCRo9tKEUDFf9Qze7Ilbb+Zzm9CUfu4M1Oz6iQcXRx7aM0jEAQID\n" +
615.69 + "AQABo4GJMIGGMB0GA1UdDgQWBBTn0C+xmZY/BTab4W9gBp3dGa7WgjBHBgNVHSME\n" +
615.70 + "QDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEwHzELMAkGA1UEBhMCVVMxEDAO\n" +
615.71 + "BgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAgQw\n" +
615.72 + "DQYJKoZIhvcNAQEFBQADgYEAiCXL2Yp4ruyRXAIJ8zBEaPC9oV2agqgbSbly2z8z\n" +
615.73 + "Ik5SeSRysP+GHBpb8uNyANJnQKv+T0GrJiTLMBjKCOiJl6xzk3EZ2wbQB6G/SQ9+\n" +
615.74 + "UWcsXSC8oGSEPpkj5In/9/UbuUIfT9H8jmdyLNKQvlqgq6kyfnskME7ptGgT95Hc\n" +
615.75 + "tas=\n" +
615.76 + "-----END CERTIFICATE-----";
615.77 +
615.78 + // SHA1withRSA 512
615.79 + static String trustAnchor_SHA1withRSA_512 =
615.80 + "-----BEGIN CERTIFICATE-----\n" +
615.81 + "MIIBuTCCAWOgAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
615.82 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa\n" +
615.83 + "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMFwwDQYJKoZIhvcNAQEB\n" +
615.84 + "BQADSwAwSAJBAM0Kn4ieCdCHsrm78ZMMN4jQEEEqACAMKB7O8j9g4gfz2oAfmHwv\n" +
615.85 + "7JH/hZ0Xen1zUmBbwe+e2J5D/4Fisp9Bn98CAwEAAaOBiTCBhjAdBgNVHQ4EFgQU\n" +
615.86 + "g4Kwd47hdNQBp8grZsRJ5XvhvxAwRwYDVR0jBEAwPoAUg4Kwd47hdNQBp8grZsRJ\n" +
615.87 + "5XvhvxChI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlggEAMA8G\n" +
615.88 + "A1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0GCSqGSIb3DQEBBQUAA0EAn77b\n" +
615.89 + "FJx+HvyRvjZYCzMjnUct3Ql4iLOkURYDh93J5TXi/l9ajvAMEuwzYj0qZ+Ktm/ia\n" +
615.90 + "U5r+8B9nzx+j2Zh3kw==\n" +
615.91 + "-----END CERTIFICATE-----";
615.92 +
615.93 + // SHA1withRSA 1024 signed with RSA 1024
615.94 + static String intermediate_SHA1withRSA_1024_1024 =
615.95 + "-----BEGIN CERTIFICATE-----\n" +
615.96 + "MIICUDCCAbmgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
615.97 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDhaFw0yOTA0MjMwMTExNDha\n" +
615.98 + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
615.99 + "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
615.100 + "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
615.101 + "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
615.102 + "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
615.103 + "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEw\n" +
615.104 + "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
615.105 + "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEFBQADgYEAHze3wAcIe84zNOoN\n" +
615.106 + "P8l9EmlVVoU30z3LB3hxq3m/dC/4gE5Z9Z8EG1wJw4qaxlTZ4dif12nbTTdofVhb\n" +
615.107 + "Bd4syjo6fcUA4q7sfg9TFpoHQ+Ap7PgjK99moMKdMy50Xy8s6FPvaVkF89s66Z6y\n" +
615.108 + "e4q7TSwe6QevGOZaL5N/iy2XGEs=\n" +
615.109 + "-----END CERTIFICATE-----";
615.110 +
615.111 + // SHA1withRSA 1024 signed with RSA 512
615.112 + static String intermediate_SHA1withRSA_1024_512 =
615.113 + "-----BEGIN CERTIFICATE-----\n" +
615.114 + "MIICDzCCAbmgAwIBAgIBAzANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
615.115 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
615.116 + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
615.117 + "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
615.118 + "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
615.119 + "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
615.120 + "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
615.121 + "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBSDgrB3juF01AGnyCtmxEnle+G/EKEjpCEw\n" +
615.122 + "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
615.123 + "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEFBQADQQCYNmdkONfuk07XjRze\n" +
615.124 + "WQyq2cfdae4uIdyUfa2rpgYMtSXuQW3/XrQGiz4G6WBXA2wo7folOOpAKYgvHPrm\n" +
615.125 + "w6Dd\n" +
615.126 + "-----END CERTIFICATE-----";
615.127 +
615.128 + // SHA1withRSA 512 signed with RSA 1024
615.129 + static String intermediate_SHA1withRSA_512_1024 =
615.130 + "-----BEGIN CERTIFICATE-----\n" +
615.131 + "MIICDDCCAXWgAwIBAgIBBDANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
615.132 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
615.133 + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
615.134 + "cy0xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKubXYoEHZpZkhzA9XX+NrpqJ4SV\n" +
615.135 + "lOMBoL3aWExQpJIgrUaZfbGMBBozIHBJMMayokguHbJvq4QigEgLuhfJNqsCAwEA\n" +
615.136 + "AaOBiTCBhjAdBgNVHQ4EFgQUN0CHiTYPtjyvpP2a6y6mhsZ6U40wRwYDVR0jBEAw\n" +
615.137 + "PoAU59AvsZmWPwU2m+FvYAad3Rmu1oKhI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD\n" +
615.138 + "VQQKEwdFeGFtcGxlggEAMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0G\n" +
615.139 + "CSqGSIb3DQEBBQUAA4GBAE2VOlw5ySLT3gUzKCYEga4QPaSrf6lHHPi2g48LscEY\n" +
615.140 + "h9qQXh4nuIVugReBIEf6N49RdT+M2cgRJo4sZ3ukYLGQzxNuttL5nPSuuvrAR1oG\n" +
615.141 + "LUyzOWcUpKHbVHi6zlTt79RvTKZvLcduLutmtPtLJcM9PdiAI1wEooSgxTwZtB/Z\n" +
615.142 + "-----END CERTIFICATE-----";
615.143 +
615.144 + // SHA1withRSA 512 signed with RSA 512
615.145 + static String intermediate_SHA1withRSA_512_512 =
615.146 + "-----BEGIN CERTIFICATE-----\n" +
615.147 + "MIIByzCCAXWgAwIBAgIBBTANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
615.148 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
615.149 + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
615.150 + "cy0xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKubXYoEHZpZkhzA9XX+NrpqJ4SV\n" +
615.151 + "lOMBoL3aWExQpJIgrUaZfbGMBBozIHBJMMayokguHbJvq4QigEgLuhfJNqsCAwEA\n" +
615.152 + "AaOBiTCBhjAdBgNVHQ4EFgQUN0CHiTYPtjyvpP2a6y6mhsZ6U40wRwYDVR0jBEAw\n" +
615.153 + "PoAUg4Kwd47hdNQBp8grZsRJ5XvhvxChI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD\n" +
615.154 + "VQQKEwdFeGFtcGxlggEAMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0G\n" +
615.155 + "CSqGSIb3DQEBBQUAA0EAoCf0Zu559qcB4xPpzqkVsYiyW49S4Yc0mmQXb1yoQgLx\n" +
615.156 + "O+DCkjG5d14+t1MsnkhB2izoQUMxQ3vDc1YnA/tEpw==\n" +
615.157 + "-----END CERTIFICATE-----";
615.158 +
615.159 + // MD2withRSA 1024 signed with RSA 1024
615.160 + static String intermediate_MD2withRSA_1024_1024 =
615.161 + "-----BEGIN CERTIFICATE-----\n" +
615.162 + "MIICUDCCAbmgAwIBAgIBBjANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ\n" +
615.163 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
615.164 + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
615.165 + "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
615.166 + "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
615.167 + "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
615.168 + "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
615.169 + "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEw\n" +
615.170 + "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
615.171 + "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQECBQADgYEAPtEjwbWuC5kc4DPc\n" +
615.172 + "Ttf/wdbD8ZCdAWzcc3XF9q1TlvwVMNk6mbfM05y6ZVsztKTkwZ4EcvFu/yIqw1EB\n" +
615.173 + "E1zlXQCaWXT3/ZMbqYZV4+mx+RUl8spUCb1tda25jnTg3mTOzB1iztm4gy903EMd\n" +
615.174 + "m8omKDKeCgcw5dR4ITQYvyxe1as=\n" +
615.175 + "-----END CERTIFICATE-----";
615.176 +
615.177 + // MD2withRSA 1024 signed with RSA 512
615.178 + static String intermediate_MD2withRSA_1024_512 =
615.179 + "-----BEGIN CERTIFICATE-----\n" +
615.180 + "MIICDzCCAbmgAwIBAgIBBzANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ\n" +
615.181 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
615.182 + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
615.183 + "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
615.184 + "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
615.185 + "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
615.186 + "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
615.187 + "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBSDgrB3juF01AGnyCtmxEnle+G/EKEjpCEw\n" +
615.188 + "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
615.189 + "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQECBQADQQBHok1v6xymtpB7N9xy\n" +
615.190 + "0OmDT27uhmzlP0eOzJvXVxj3Oi9TLQJgCUJ9122MzfRAs1E1uJTtvuu+UmI80NQx\n" +
615.191 + "KQdp\n" +
615.192 + "-----END CERTIFICATE-----";
615.193 +
615.194 + // SHA1withRSA 1024 signed with RSA 1024
615.195 + static String endentiry_SHA1withRSA_1024_1024 =
615.196 + "-----BEGIN CERTIFICATE-----\n" +
615.197 + "MIICNzCCAaCgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ\n" +
615.198 + "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
615.199 + "NTBaFw0yOTA0MjMwMTExNTBaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
615.200 + "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG\n" +
615.201 + "9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt\n" +
615.202 + "vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v\n" +
615.203 + "z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6\n" +
615.204 + "c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07\n" +
615.205 + "OorBleV92TAfBgNVHSMEGDAWgBTfWD9mRTppcUAlUqGuu/R5t8CB5jANBgkqhkiG\n" +
615.206 + "9w0BAQUFAAOBgQAOfIeasDg91CR3jGfuAEVKwncM1OPFmniAUcdPm74cCAyJ90Me\n" +
615.207 + "dhUElWPGoAuXGfiyZlOlGUYWqEroe/dnkmnotJjLWR+MA4ZyX3O1YI8T4W3deWcC\n" +
615.208 + "J4WMCF7mp17SaYYKX9F0AxwNJFpUkbB41IkTxPr0MmzB1871/pbY8dLAvA==\n" +
615.209 + "-----END CERTIFICATE-----";
615.210 +
615.211 + // SHA1withRSA 1024 signed with RSA 512
615.212 + static String endentiry_SHA1withRSA_1024_512 =
615.213 + "-----BEGIN CERTIFICATE-----\n" +
615.214 + "MIIB9jCCAaCgAwIBAgIBAzANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ\n" +
615.215 + "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
615.216 + "NTBaFw0yOTA0MjMwMTExNTBaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
615.217 + "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG\n" +
615.218 + "9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt\n" +
615.219 + "vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v\n" +
615.220 + "z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6\n" +
615.221 + "c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07\n" +
615.222 + "OorBleV92TAfBgNVHSMEGDAWgBQ3QIeJNg+2PK+k/ZrrLqaGxnpTjTANBgkqhkiG\n" +
615.223 + "9w0BAQUFAANBADV6X+ea0ftEKXy7yKNAbdIp35893T6AVwbdclomPkeOs86OtoTG\n" +
615.224 + "1BIzWSK9QE7W6Wbf63e2RdcqoLK+DxsuwUg=\n" +
615.225 + "-----END CERTIFICATE-----";
615.226 +
615.227 + // SHA1withRSA 512 signed with RSA 1024
615.228 + static String endentiry_SHA1withRSA_512_1024 =
615.229 + "-----BEGIN CERTIFICATE-----\n" +
615.230 + "MIIB8zCCAVygAwIBAgIBBDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ\n" +
615.231 + "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
615.232 + "NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
615.233 + "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTBcMA0GCSqGSIb3\n" +
615.234 + "DQEBAQUAA0sAMEgCQQCpfQzhld7w2JhW/aRaLkmrLrc/QAsQE+J4DXioXaajsWPo\n" +
615.235 + "uMmYmuiQolb6OIY/LcivSubKM3G5PkAWoovUPIWLAgMBAAGjTzBNMAsGA1UdDwQE\n" +
615.236 + "AwID6DAdBgNVHQ4EFgQUFWuXLkf4Ji57H9ISycgWi982TUIwHwYDVR0jBBgwFoAU\n" +
615.237 + "31g/ZkU6aXFAJVKhrrv0ebfAgeYwDQYJKoZIhvcNAQEFBQADgYEAUyW8PrEdbzLu\n" +
615.238 + "B+h6UemBOJ024rYq90hJE/5wUEKPvxZ9vPEUgl+io6cGhL3cLfxfh6z5xtEGp4Tb\n" +
615.239 + "NB0Ye3Qi01FBiNDY8s3rQRrmel6VysU8u+0Oi2jmQY6vZXn/zXN5rrTLITCaSicG\n" +
615.240 + "dOMv1xLM83Ee432WWlDwKOUxhzDGpWc=\n" +
615.241 + "-----END CERTIFICATE-----";
615.242 +
615.243 + // SHA1withRSA 512 signed with RSA 512
615.244 + static String endentiry_SHA1withRSA_512_512 =
615.245 + "-----BEGIN CERTIFICATE-----\n" +
615.246 + "MIIBsjCCAVygAwIBAgIBBTANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ\n" +
615.247 + "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
615.248 + "NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
615.249 + "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTBcMA0GCSqGSIb3\n" +
615.250 + "DQEBAQUAA0sAMEgCQQCpfQzhld7w2JhW/aRaLkmrLrc/QAsQE+J4DXioXaajsWPo\n" +
615.251 + "uMmYmuiQolb6OIY/LcivSubKM3G5PkAWoovUPIWLAgMBAAGjTzBNMAsGA1UdDwQE\n" +
615.252 + "AwID6DAdBgNVHQ4EFgQUFWuXLkf4Ji57H9ISycgWi982TUIwHwYDVR0jBBgwFoAU\n" +
615.253 + "N0CHiTYPtjyvpP2a6y6mhsZ6U40wDQYJKoZIhvcNAQEFBQADQQBG4grtrVEHick0\n" +
615.254 + "z/6Lcl/MGyHT0c8KTXE0AMVXG1NRjAicAmYno/yDaJ9OmfymObKZKV9fF7yCW/N/\n" +
615.255 + "TMU6m7N0\n" +
615.256 + "-----END CERTIFICATE-----";
615.257 +
615.258 + // MD2withRSA 1024 signed with RSA 1024
615.259 + static String endentiry_MD2withRSA_1024_1024 =
615.260 + "-----BEGIN CERTIFICATE-----\n" +
615.261 + "MIICNzCCAaCgAwIBAgIBBjANBgkqhkiG9w0BAQIFADAxMQswCQYDVQQGEwJVUzEQ\n" +
615.262 + "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
615.263 + "NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
615.264 + "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG\n" +
615.265 + "9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt\n" +
615.266 + "vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v\n" +
615.267 + "z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6\n" +
615.268 + "c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07\n" +
615.269 + "OorBleV92TAfBgNVHSMEGDAWgBTfWD9mRTppcUAlUqGuu/R5t8CB5jANBgkqhkiG\n" +
615.270 + "9w0BAQIFAAOBgQBxKsFf8NNQcXjDoKJJSG4Rk6ikcrhiGYuUI32+XHvs6hnav1Zc\n" +
615.271 + "aJUpy7J4gMj/MnysMh/4AF9+m6zEEjuisXKUbYZhgtJxz+ukGSo163mJ8QJiAlRb\n" +
615.272 + "Iwsy81r08mlSCR6jx2YhDAUxJIPC92R5Vb4CEutB7tWTwwz7vIHq330erA==\n" +
615.273 + "-----END CERTIFICATE-----";
615.274 +
615.275 + // MD2withRSA 1024 signed with RSA 512
615.276 + static String endentiry_MD2withRSA_1024_512 =
615.277 + "-----BEGIN CERTIFICATE-----\n" +
615.278 + "MIIB9jCCAaCgAwIBAgIBBzANBgkqhkiG9w0BAQIFADAxMQswCQYDVQQGEwJVUzEQ\n" +
615.279 + "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
615.280 + "NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
615.281 + "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG\n" +
615.282 + "9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt\n" +
615.283 + "vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v\n" +
615.284 + "z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6\n" +
615.285 + "c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07\n" +
615.286 + "OorBleV92TAfBgNVHSMEGDAWgBQ3QIeJNg+2PK+k/ZrrLqaGxnpTjTANBgkqhkiG\n" +
615.287 + "9w0BAQIFAANBAIX63Ypi9P71RnC/pcMbhD+wekRFsTzU593X3MC7tyBJtEXwvAZG\n" +
615.288 + "iMxXF5A+ohlr7/CrkV7ZTL8PLxnJdY5Y8rQ=\n" +
615.289 + "-----END CERTIFICATE-----";
615.290 +
615.291 + static HashMap<String, String> certmap = new HashMap<String, String>();
615.292 + static {
615.293 + certmap.put("trustAnchor_SHA1withRSA_1024",
615.294 + trustAnchor_SHA1withRSA_1024);
615.295 + certmap.put("trustAnchor_SHA1withRSA_512",
615.296 + trustAnchor_SHA1withRSA_512);
615.297 + certmap.put("intermediate_SHA1withRSA_1024_1024",
615.298 + intermediate_SHA1withRSA_1024_1024);
615.299 + certmap.put("intermediate_SHA1withRSA_1024_512",
615.300 + intermediate_SHA1withRSA_1024_512);
615.301 + certmap.put("intermediate_SHA1withRSA_512_1024",
615.302 + intermediate_SHA1withRSA_512_1024);
615.303 + certmap.put("intermediate_SHA1withRSA_512_512",
615.304 + intermediate_SHA1withRSA_512_512);
615.305 + certmap.put("intermediate_MD2withRSA_1024_1024",
615.306 + intermediate_MD2withRSA_1024_1024);
615.307 + certmap.put("intermediate_MD2withRSA_1024_512",
615.308 + intermediate_MD2withRSA_1024_512);
615.309 + certmap.put("endentiry_SHA1withRSA_1024_1024",
615.310 + endentiry_SHA1withRSA_1024_1024);
615.311 + certmap.put("endentiry_SHA1withRSA_1024_512",
615.312 + endentiry_SHA1withRSA_1024_512);
615.313 + certmap.put("endentiry_SHA1withRSA_512_1024",
615.314 + endentiry_SHA1withRSA_512_1024);
615.315 + certmap.put("endentiry_SHA1withRSA_512_512",
615.316 + endentiry_SHA1withRSA_512_512);
615.317 + certmap.put("endentiry_MD2withRSA_1024_1024",
615.318 + endentiry_MD2withRSA_1024_1024);
615.319 + certmap.put("endentiry_MD2withRSA_1024_512",
615.320 + endentiry_MD2withRSA_1024_512);
615.321 + }
615.322 +
615.323 + private static Set<TrustAnchor> generateTrustAnchors()
615.324 + throws CertificateException {
615.325 + // generate certificate from cert string
615.326 + CertificateFactory cf = CertificateFactory.getInstance("X.509");
615.327 + HashSet<TrustAnchor> anchors = new HashSet<TrustAnchor>();
615.328 +
615.329 + ByteArrayInputStream is =
615.330 + new ByteArrayInputStream(trustAnchor_SHA1withRSA_1024.getBytes());
615.331 + Certificate cert = cf.generateCertificate(is);
615.332 + TrustAnchor anchor = new TrustAnchor((X509Certificate)cert, null);
615.333 + anchors.add(anchor);
615.334 +
615.335 + is = new ByteArrayInputStream(trustAnchor_SHA1withRSA_512.getBytes());
615.336 + cert = cf.generateCertificate(is);
615.337 + anchor = new TrustAnchor((X509Certificate)cert, null);
615.338 + anchors.add(anchor);
615.339 +
615.340 + return anchors;
615.341 + }
615.342 +
615.343 + private static CertStore generateCertificateStore() throws Exception {
615.344 + Collection entries = new HashSet();
615.345 +
615.346 + // generate certificate from certificate string
615.347 + CertificateFactory cf = CertificateFactory.getInstance("X.509");
615.348 +
615.349 + for (String key : certmap.keySet()) {
615.350 + String certStr = certmap.get(key);
615.351 + ByteArrayInputStream is =
615.352 + new ByteArrayInputStream(certStr.getBytes());;
615.353 + Certificate cert = cf.generateCertificate(is);
615.354 + entries.add(cert);
615.355 + }
615.356 +
615.357 + return CertStore.getInstance("Collection",
615.358 + new CollectionCertStoreParameters(entries));
615.359 + }
615.360 +
615.361 + private static X509CertSelector generateSelector(String name)
615.362 + throws Exception {
615.363 + X509CertSelector selector = new X509CertSelector();
615.364 +
615.365 + String certStr = certmap.get(name);
615.366 + if (certStr == null) {
615.367 + return null;
615.368 + }
615.369 +
615.370 + // generate certificate from certificate string
615.371 + CertificateFactory cf = CertificateFactory.getInstance("X.509");
615.372 + ByteArrayInputStream is = new ByteArrayInputStream(certStr.getBytes());
615.373 + X509Certificate target = (X509Certificate)cf.generateCertificate(is);
615.374 +
615.375 + selector.setCertificate(target);
615.376 +
615.377 + return selector;
615.378 + }
615.379 +
615.380 + private static boolean match(String name, Certificate cert)
615.381 + throws Exception {
615.382 + X509CertSelector selector = new X509CertSelector();
615.383 +
615.384 + String certStr = certmap.get(name);
615.385 + if (certStr == null) {
615.386 + return false;
615.387 + }
615.388 +
615.389 + // generate certificate from certificate string
615.390 + CertificateFactory cf = CertificateFactory.getInstance("X.509");
615.391 + ByteArrayInputStream is = new ByteArrayInputStream(certStr.getBytes());
615.392 + X509Certificate target = (X509Certificate)cf.generateCertificate(is);
615.393 +
615.394 + return target.equals(cert);
615.395 + }
615.396 +
615.397 + public static void main(String args[]) throws Exception {
615.398 +
615.399 + CertPathBuilder builder = CertPathBuilder.getInstance("PKIX");
615.400 +
615.401 + X509CertSelector selector = generateSelector(args[0]);
615.402 + if (selector == null) {
615.403 + // no target certificate, ignore it
615.404 + return;
615.405 + }
615.406 +
615.407 + Set<TrustAnchor> anchors = generateTrustAnchors();
615.408 + CertStore certs = generateCertificateStore();
615.409 +
615.410 + PKIXBuilderParameters params =
615.411 + new PKIXBuilderParameters(anchors, selector);
615.412 + params.addCertStore(certs);
615.413 + params.setRevocationEnabled(false);
615.414 + params.setDate(new Date(109, 9, 1)); // 2009-09-01
615.415 +
615.416 + boolean success = Boolean.valueOf(args[2]);
615.417 + try {
615.418 + PKIXCertPathBuilderResult result =
615.419 + (PKIXCertPathBuilderResult)builder.build(params);
615.420 + if (!success) {
615.421 + throw new Exception("expected algorithm disabled exception");
615.422 + }
615.423 +
615.424 + int length = Integer.parseInt(args[1]);
615.425 + List<? extends Certificate> path =
615.426 + result.getCertPath().getCertificates();
615.427 + if (length != path.size()) {
615.428 + throw new Exception("unexpected certification path length");
615.429 + }
615.430 +
615.431 + if (!path.isEmpty()) { // the target is not a trust anchor
615.432 + if (!match(args[0], path.get(0))) {
615.433 + throw new Exception("unexpected certificate");
615.434 + }
615.435 + }
615.436 + } catch (CertPathBuilderException cpbe) {
615.437 + if (success) {
615.438 + throw new Exception("unexpected exception");
615.439 + } else {
615.440 + System.out.println("Get the expected exception " + cpbe);
615.441 + }
615.442 + }
615.443 + }
615.444 +
615.445 +}
616.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
616.2 +++ b/test/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorEndEntity.java Wed Nov 25 11:08:25 2009 -0800
616.3 @@ -0,0 +1,363 @@
616.4 +/*
616.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
616.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
616.7 + *
616.8 + * This code is free software; you can redistribute it and/or modify it
616.9 + * under the terms of the GNU General Public License version 2 only, as
616.10 + * published by the Free Software Foundation.
616.11 + *
616.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
616.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
616.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
616.15 + * version 2 for more details (a copy is included in the LICENSE file that
616.16 + * accompanied this code).
616.17 + *
616.18 + * You should have received a copy of the GNU General Public License version
616.19 + * 2 along with this work; if not, write to the Free Software Foundation,
616.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
616.21 + *
616.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
616.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
616.24 + * have any questions.
616.25 + */
616.26 +
616.27 +/**
616.28 + * @test
616.29 + *
616.30 + * @bug 6861062
616.31 + * @summary Disable MD2 support
616.32 + *
616.33 + * @author Xuelei Fan
616.34 + */
616.35 +
616.36 +import java.io.*;
616.37 +import java.net.SocketException;
616.38 +import java.util.*;
616.39 +import java.security.Security;
616.40 +import java.security.cert.*;
616.41 +
616.42 +public class CPValidatorEndEntity {
616.43 +
616.44 + // SHA1withRSA 1024
616.45 + static String trustAnchor_SHA1withRSA_1024 =
616.46 + "-----BEGIN CERTIFICATE-----\n" +
616.47 + "MIICPjCCAaegAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
616.48 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa\n" +
616.49 + "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB\n" +
616.50 + "AQUAA4GNADCBiQKBgQC8UdC863pFk1Rvd7xUYd60+e9KsLhb6SqOfU42ZA715FcH\n" +
616.51 + "E1TRvQPmYzAnHcO04TrWZQtO6E+E2RCmeBnetBvIMVka688QkO14wnrIrf2tRodd\n" +
616.52 + "rZNZEBzkX+zyXCRo9tKEUDFf9Qze7Ilbb+Zzm9CUfu4M1Oz6iQcXRx7aM0jEAQID\n" +
616.53 + "AQABo4GJMIGGMB0GA1UdDgQWBBTn0C+xmZY/BTab4W9gBp3dGa7WgjBHBgNVHSME\n" +
616.54 + "QDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEwHzELMAkGA1UEBhMCVVMxEDAO\n" +
616.55 + "BgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAgQw\n" +
616.56 + "DQYJKoZIhvcNAQEFBQADgYEAiCXL2Yp4ruyRXAIJ8zBEaPC9oV2agqgbSbly2z8z\n" +
616.57 + "Ik5SeSRysP+GHBpb8uNyANJnQKv+T0GrJiTLMBjKCOiJl6xzk3EZ2wbQB6G/SQ9+\n" +
616.58 + "UWcsXSC8oGSEPpkj5In/9/UbuUIfT9H8jmdyLNKQvlqgq6kyfnskME7ptGgT95Hc\n" +
616.59 + "tas=\n" +
616.60 + "-----END CERTIFICATE-----";
616.61 +
616.62 + // SHA1withRSA 512
616.63 + static String trustAnchor_SHA1withRSA_512 =
616.64 + "-----BEGIN CERTIFICATE-----\n" +
616.65 + "MIIBuTCCAWOgAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
616.66 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa\n" +
616.67 + "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMFwwDQYJKoZIhvcNAQEB\n" +
616.68 + "BQADSwAwSAJBAM0Kn4ieCdCHsrm78ZMMN4jQEEEqACAMKB7O8j9g4gfz2oAfmHwv\n" +
616.69 + "7JH/hZ0Xen1zUmBbwe+e2J5D/4Fisp9Bn98CAwEAAaOBiTCBhjAdBgNVHQ4EFgQU\n" +
616.70 + "g4Kwd47hdNQBp8grZsRJ5XvhvxAwRwYDVR0jBEAwPoAUg4Kwd47hdNQBp8grZsRJ\n" +
616.71 + "5XvhvxChI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlggEAMA8G\n" +
616.72 + "A1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0GCSqGSIb3DQEBBQUAA0EAn77b\n" +
616.73 + "FJx+HvyRvjZYCzMjnUct3Ql4iLOkURYDh93J5TXi/l9ajvAMEuwzYj0qZ+Ktm/ia\n" +
616.74 + "U5r+8B9nzx+j2Zh3kw==\n" +
616.75 + "-----END CERTIFICATE-----";
616.76 +
616.77 + // SHA1withRSA 1024 signed with RSA 1024
616.78 + static String intermediate_SHA1withRSA_1024_1024 =
616.79 + "-----BEGIN CERTIFICATE-----\n" +
616.80 + "MIICUDCCAbmgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
616.81 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDhaFw0yOTA0MjMwMTExNDha\n" +
616.82 + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
616.83 + "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
616.84 + "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
616.85 + "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
616.86 + "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
616.87 + "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEw\n" +
616.88 + "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
616.89 + "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEFBQADgYEAHze3wAcIe84zNOoN\n" +
616.90 + "P8l9EmlVVoU30z3LB3hxq3m/dC/4gE5Z9Z8EG1wJw4qaxlTZ4dif12nbTTdofVhb\n" +
616.91 + "Bd4syjo6fcUA4q7sfg9TFpoHQ+Ap7PgjK99moMKdMy50Xy8s6FPvaVkF89s66Z6y\n" +
616.92 + "e4q7TSwe6QevGOZaL5N/iy2XGEs=\n" +
616.93 + "-----END CERTIFICATE-----";
616.94 +
616.95 + // SHA1withRSA 1024 signed with RSA 512
616.96 + static String intermediate_SHA1withRSA_1024_512 =
616.97 + "-----BEGIN CERTIFICATE-----\n" +
616.98 + "MIICDzCCAbmgAwIBAgIBAzANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
616.99 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
616.100 + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
616.101 + "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
616.102 + "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
616.103 + "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
616.104 + "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
616.105 + "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBSDgrB3juF01AGnyCtmxEnle+G/EKEjpCEw\n" +
616.106 + "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
616.107 + "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEFBQADQQCYNmdkONfuk07XjRze\n" +
616.108 + "WQyq2cfdae4uIdyUfa2rpgYMtSXuQW3/XrQGiz4G6WBXA2wo7folOOpAKYgvHPrm\n" +
616.109 + "w6Dd\n" +
616.110 + "-----END CERTIFICATE-----";
616.111 +
616.112 + // SHA1withRSA 512 signed with RSA 1024
616.113 + static String intermediate_SHA1withRSA_512_1024 =
616.114 + "-----BEGIN CERTIFICATE-----\n" +
616.115 + "MIICDDCCAXWgAwIBAgIBBDANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
616.116 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
616.117 + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
616.118 + "cy0xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKubXYoEHZpZkhzA9XX+NrpqJ4SV\n" +
616.119 + "lOMBoL3aWExQpJIgrUaZfbGMBBozIHBJMMayokguHbJvq4QigEgLuhfJNqsCAwEA\n" +
616.120 + "AaOBiTCBhjAdBgNVHQ4EFgQUN0CHiTYPtjyvpP2a6y6mhsZ6U40wRwYDVR0jBEAw\n" +
616.121 + "PoAU59AvsZmWPwU2m+FvYAad3Rmu1oKhI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD\n" +
616.122 + "VQQKEwdFeGFtcGxlggEAMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0G\n" +
616.123 + "CSqGSIb3DQEBBQUAA4GBAE2VOlw5ySLT3gUzKCYEga4QPaSrf6lHHPi2g48LscEY\n" +
616.124 + "h9qQXh4nuIVugReBIEf6N49RdT+M2cgRJo4sZ3ukYLGQzxNuttL5nPSuuvrAR1oG\n" +
616.125 + "LUyzOWcUpKHbVHi6zlTt79RvTKZvLcduLutmtPtLJcM9PdiAI1wEooSgxTwZtB/Z\n" +
616.126 + "-----END CERTIFICATE-----";
616.127 +
616.128 + // SHA1withRSA 512 signed with RSA 512
616.129 + static String intermediate_SHA1withRSA_512_512 =
616.130 + "-----BEGIN CERTIFICATE-----\n" +
616.131 + "MIIByzCCAXWgAwIBAgIBBTANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
616.132 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
616.133 + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
616.134 + "cy0xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKubXYoEHZpZkhzA9XX+NrpqJ4SV\n" +
616.135 + "lOMBoL3aWExQpJIgrUaZfbGMBBozIHBJMMayokguHbJvq4QigEgLuhfJNqsCAwEA\n" +
616.136 + "AaOBiTCBhjAdBgNVHQ4EFgQUN0CHiTYPtjyvpP2a6y6mhsZ6U40wRwYDVR0jBEAw\n" +
616.137 + "PoAUg4Kwd47hdNQBp8grZsRJ5XvhvxChI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD\n" +
616.138 + "VQQKEwdFeGFtcGxlggEAMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0G\n" +
616.139 + "CSqGSIb3DQEBBQUAA0EAoCf0Zu559qcB4xPpzqkVsYiyW49S4Yc0mmQXb1yoQgLx\n" +
616.140 + "O+DCkjG5d14+t1MsnkhB2izoQUMxQ3vDc1YnA/tEpw==\n" +
616.141 + "-----END CERTIFICATE-----";
616.142 +
616.143 + // MD2withRSA 1024 signed with RSA 1024
616.144 + static String intermediate_MD2withRSA_1024_1024 =
616.145 + "-----BEGIN CERTIFICATE-----\n" +
616.146 + "MIICUDCCAbmgAwIBAgIBBjANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ\n" +
616.147 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
616.148 + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
616.149 + "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
616.150 + "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
616.151 + "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
616.152 + "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
616.153 + "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEw\n" +
616.154 + "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
616.155 + "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQECBQADgYEAPtEjwbWuC5kc4DPc\n" +
616.156 + "Ttf/wdbD8ZCdAWzcc3XF9q1TlvwVMNk6mbfM05y6ZVsztKTkwZ4EcvFu/yIqw1EB\n" +
616.157 + "E1zlXQCaWXT3/ZMbqYZV4+mx+RUl8spUCb1tda25jnTg3mTOzB1iztm4gy903EMd\n" +
616.158 + "m8omKDKeCgcw5dR4ITQYvyxe1as=\n" +
616.159 + "-----END CERTIFICATE-----";
616.160 +
616.161 + // MD2withRSA 1024 signed with RSA 512
616.162 + static String intermediate_MD2withRSA_1024_512 =
616.163 + "-----BEGIN CERTIFICATE-----\n" +
616.164 + "MIICDzCCAbmgAwIBAgIBBzANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ\n" +
616.165 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
616.166 + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
616.167 + "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
616.168 + "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
616.169 + "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
616.170 + "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
616.171 + "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBSDgrB3juF01AGnyCtmxEnle+G/EKEjpCEw\n" +
616.172 + "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
616.173 + "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQECBQADQQBHok1v6xymtpB7N9xy\n" +
616.174 + "0OmDT27uhmzlP0eOzJvXVxj3Oi9TLQJgCUJ9122MzfRAs1E1uJTtvuu+UmI80NQx\n" +
616.175 + "KQdp\n" +
616.176 + "-----END CERTIFICATE-----";
616.177 +
616.178 + // SHA1withRSA 1024 signed with RSA 1024
616.179 + static String endentiry_SHA1withRSA_1024_1024 =
616.180 + "-----BEGIN CERTIFICATE-----\n" +
616.181 + "MIICNzCCAaCgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ\n" +
616.182 + "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
616.183 + "NTBaFw0yOTA0MjMwMTExNTBaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
616.184 + "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG\n" +
616.185 + "9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt\n" +
616.186 + "vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v\n" +
616.187 + "z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6\n" +
616.188 + "c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07\n" +
616.189 + "OorBleV92TAfBgNVHSMEGDAWgBTfWD9mRTppcUAlUqGuu/R5t8CB5jANBgkqhkiG\n" +
616.190 + "9w0BAQUFAAOBgQAOfIeasDg91CR3jGfuAEVKwncM1OPFmniAUcdPm74cCAyJ90Me\n" +
616.191 + "dhUElWPGoAuXGfiyZlOlGUYWqEroe/dnkmnotJjLWR+MA4ZyX3O1YI8T4W3deWcC\n" +
616.192 + "J4WMCF7mp17SaYYKX9F0AxwNJFpUkbB41IkTxPr0MmzB1871/pbY8dLAvA==\n" +
616.193 + "-----END CERTIFICATE-----";
616.194 +
616.195 + // SHA1withRSA 1024 signed with RSA 512
616.196 + static String endentiry_SHA1withRSA_1024_512 =
616.197 + "-----BEGIN CERTIFICATE-----\n" +
616.198 + "MIIB9jCCAaCgAwIBAgIBAzANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ\n" +
616.199 + "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
616.200 + "NTBaFw0yOTA0MjMwMTExNTBaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
616.201 + "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG\n" +
616.202 + "9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt\n" +
616.203 + "vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v\n" +
616.204 + "z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6\n" +
616.205 + "c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07\n" +
616.206 + "OorBleV92TAfBgNVHSMEGDAWgBQ3QIeJNg+2PK+k/ZrrLqaGxnpTjTANBgkqhkiG\n" +
616.207 + "9w0BAQUFAANBADV6X+ea0ftEKXy7yKNAbdIp35893T6AVwbdclomPkeOs86OtoTG\n" +
616.208 + "1BIzWSK9QE7W6Wbf63e2RdcqoLK+DxsuwUg=\n" +
616.209 + "-----END CERTIFICATE-----";
616.210 +
616.211 + // SHA1withRSA 512 signed with RSA 1024
616.212 + static String endentiry_SHA1withRSA_512_1024 =
616.213 + "-----BEGIN CERTIFICATE-----\n" +
616.214 + "MIIB8zCCAVygAwIBAgIBBDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ\n" +
616.215 + "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
616.216 + "NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
616.217 + "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTBcMA0GCSqGSIb3\n" +
616.218 + "DQEBAQUAA0sAMEgCQQCpfQzhld7w2JhW/aRaLkmrLrc/QAsQE+J4DXioXaajsWPo\n" +
616.219 + "uMmYmuiQolb6OIY/LcivSubKM3G5PkAWoovUPIWLAgMBAAGjTzBNMAsGA1UdDwQE\n" +
616.220 + "AwID6DAdBgNVHQ4EFgQUFWuXLkf4Ji57H9ISycgWi982TUIwHwYDVR0jBBgwFoAU\n" +
616.221 + "31g/ZkU6aXFAJVKhrrv0ebfAgeYwDQYJKoZIhvcNAQEFBQADgYEAUyW8PrEdbzLu\n" +
616.222 + "B+h6UemBOJ024rYq90hJE/5wUEKPvxZ9vPEUgl+io6cGhL3cLfxfh6z5xtEGp4Tb\n" +
616.223 + "NB0Ye3Qi01FBiNDY8s3rQRrmel6VysU8u+0Oi2jmQY6vZXn/zXN5rrTLITCaSicG\n" +
616.224 + "dOMv1xLM83Ee432WWlDwKOUxhzDGpWc=\n" +
616.225 + "-----END CERTIFICATE-----";
616.226 +
616.227 + // SHA1withRSA 512 signed with RSA 512
616.228 + static String endentiry_SHA1withRSA_512_512 =
616.229 + "-----BEGIN CERTIFICATE-----\n" +
616.230 + "MIIBsjCCAVygAwIBAgIBBTANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ\n" +
616.231 + "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
616.232 + "NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
616.233 + "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTBcMA0GCSqGSIb3\n" +
616.234 + "DQEBAQUAA0sAMEgCQQCpfQzhld7w2JhW/aRaLkmrLrc/QAsQE+J4DXioXaajsWPo\n" +
616.235 + "uMmYmuiQolb6OIY/LcivSubKM3G5PkAWoovUPIWLAgMBAAGjTzBNMAsGA1UdDwQE\n" +
616.236 + "AwID6DAdBgNVHQ4EFgQUFWuXLkf4Ji57H9ISycgWi982TUIwHwYDVR0jBBgwFoAU\n" +
616.237 + "N0CHiTYPtjyvpP2a6y6mhsZ6U40wDQYJKoZIhvcNAQEFBQADQQBG4grtrVEHick0\n" +
616.238 + "z/6Lcl/MGyHT0c8KTXE0AMVXG1NRjAicAmYno/yDaJ9OmfymObKZKV9fF7yCW/N/\n" +
616.239 + "TMU6m7N0\n" +
616.240 + "-----END CERTIFICATE-----";
616.241 +
616.242 + // MD2withRSA 1024 signed with RSA 1024
616.243 + static String endentiry_MD2withRSA_1024_1024 =
616.244 + "-----BEGIN CERTIFICATE-----\n" +
616.245 + "MIICNzCCAaCgAwIBAgIBBjANBgkqhkiG9w0BAQIFADAxMQswCQYDVQQGEwJVUzEQ\n" +
616.246 + "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
616.247 + "NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
616.248 + "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG\n" +
616.249 + "9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt\n" +
616.250 + "vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v\n" +
616.251 + "z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6\n" +
616.252 + "c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07\n" +
616.253 + "OorBleV92TAfBgNVHSMEGDAWgBTfWD9mRTppcUAlUqGuu/R5t8CB5jANBgkqhkiG\n" +
616.254 + "9w0BAQIFAAOBgQBxKsFf8NNQcXjDoKJJSG4Rk6ikcrhiGYuUI32+XHvs6hnav1Zc\n" +
616.255 + "aJUpy7J4gMj/MnysMh/4AF9+m6zEEjuisXKUbYZhgtJxz+ukGSo163mJ8QJiAlRb\n" +
616.256 + "Iwsy81r08mlSCR6jx2YhDAUxJIPC92R5Vb4CEutB7tWTwwz7vIHq330erA==\n" +
616.257 + "-----END CERTIFICATE-----";
616.258 +
616.259 + // MD2withRSA 1024 signed with RSA 512
616.260 + static String endentiry_MD2withRSA_1024_512 =
616.261 + "-----BEGIN CERTIFICATE-----\n" +
616.262 + "MIIB9jCCAaCgAwIBAgIBBzANBgkqhkiG9w0BAQIFADAxMQswCQYDVQQGEwJVUzEQ\n" +
616.263 + "MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx\n" +
616.264 + "NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt\n" +
616.265 + "cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG\n" +
616.266 + "9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt\n" +
616.267 + "vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v\n" +
616.268 + "z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6\n" +
616.269 + "c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07\n" +
616.270 + "OorBleV92TAfBgNVHSMEGDAWgBQ3QIeJNg+2PK+k/ZrrLqaGxnpTjTANBgkqhkiG\n" +
616.271 + "9w0BAQIFAANBAIX63Ypi9P71RnC/pcMbhD+wekRFsTzU593X3MC7tyBJtEXwvAZG\n" +
616.272 + "iMxXF5A+ohlr7/CrkV7ZTL8PLxnJdY5Y8rQ=\n" +
616.273 + "-----END CERTIFICATE-----";
616.274 +
616.275 + private static CertPath generateCertificatePath(String castr,
616.276 + String eestr) throws CertificateException {
616.277 + // generate certificate from cert strings
616.278 + CertificateFactory cf = CertificateFactory.getInstance("X.509");
616.279 +
616.280 + ByteArrayInputStream is;
616.281 +
616.282 + is = new ByteArrayInputStream(castr.getBytes());
616.283 + Certificate cacert = cf.generateCertificate(is);
616.284 +
616.285 + is = new ByteArrayInputStream(eestr.getBytes());
616.286 + Certificate eecert = cf.generateCertificate(is);
616.287 +
616.288 + // generate certification path
616.289 + List<Certificate> list = Arrays.asList(new Certificate[] {
616.290 + eecert, cacert});
616.291 +
616.292 + return cf.generateCertPath(list);
616.293 + }
616.294 +
616.295 + private static Set<TrustAnchor> generateTrustAnchors()
616.296 + throws CertificateException {
616.297 + // generate certificate from cert string
616.298 + CertificateFactory cf = CertificateFactory.getInstance("X.509");
616.299 + HashSet<TrustAnchor> anchors = new HashSet<TrustAnchor>();
616.300 +
616.301 + ByteArrayInputStream is =
616.302 + new ByteArrayInputStream(trustAnchor_SHA1withRSA_1024.getBytes());
616.303 + Certificate cert = cf.generateCertificate(is);
616.304 + TrustAnchor anchor = new TrustAnchor((X509Certificate)cert, null);
616.305 + anchors.add(anchor);
616.306 +
616.307 + is = new ByteArrayInputStream(trustAnchor_SHA1withRSA_512.getBytes());
616.308 + cert = cf.generateCertificate(is);
616.309 + anchor = new TrustAnchor((X509Certificate)cert, null);
616.310 + anchors.add(anchor);
616.311 +
616.312 + return anchors;
616.313 + }
616.314 +
616.315 + public static void main(String args[]) throws Exception {
616.316 + try {
616.317 + validate(endentiry_SHA1withRSA_1024_1024,
616.318 + intermediate_SHA1withRSA_1024_1024);
616.319 + validate(endentiry_SHA1withRSA_1024_512,
616.320 + intermediate_SHA1withRSA_512_1024);
616.321 + validate(endentiry_SHA1withRSA_512_1024,
616.322 + intermediate_SHA1withRSA_1024_1024);
616.323 + validate(endentiry_SHA1withRSA_512_512,
616.324 + intermediate_SHA1withRSA_512_1024);
616.325 + } catch (CertPathValidatorException cpve) {
616.326 + throw new Exception(
616.327 + "unexpect exception, it is valid cert", cpve);
616.328 + }
616.329 +
616.330 + try {
616.331 + validate(endentiry_MD2withRSA_1024_1024,
616.332 + intermediate_SHA1withRSA_1024_1024);
616.333 + throw new Exception("expected algorithm disabled exception");
616.334 + } catch (CertPathValidatorException cpve) {
616.335 + System.out.println("Get the expected exception " + cpve);
616.336 + }
616.337 +
616.338 + try {
616.339 + validate(endentiry_MD2withRSA_1024_512,
616.340 + intermediate_SHA1withRSA_512_1024);
616.341 + throw new Exception("expected algorithm disabled exception");
616.342 + } catch (CertPathValidatorException cpve) {
616.343 + System.out.println("Get the expected exception " + cpve);
616.344 + }
616.345 + }
616.346 +
616.347 + private static void validate(String eecert, String cacert)
616.348 + throws CertPathValidatorException, Exception {
616.349 +
616.350 + CertPath path = generateCertificatePath(cacert, eecert);
616.351 + Set<TrustAnchor> anchors = generateTrustAnchors();
616.352 +
616.353 + PKIXParameters params = new PKIXParameters(anchors);
616.354 +
616.355 + // disable certificate revocation checking
616.356 + params.setRevocationEnabled(false);
616.357 +
616.358 + // set the validation time
616.359 + params.setDate(new Date(109, 9, 1)); // 2009-09-01
616.360 +
616.361 + CertPathValidator validator = CertPathValidator.getInstance("PKIX");
616.362 +
616.363 + validator.validate(path, params);
616.364 + }
616.365 +
616.366 +}
617.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
617.2 +++ b/test/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorIntermediate.java Wed Nov 25 11:08:25 2009 -0800
617.3 @@ -0,0 +1,256 @@
617.4 +/*
617.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
617.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
617.7 + *
617.8 + * This code is free software; you can redistribute it and/or modify it
617.9 + * under the terms of the GNU General Public License version 2 only, as
617.10 + * published by the Free Software Foundation.
617.11 + *
617.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
617.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
617.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
617.15 + * version 2 for more details (a copy is included in the LICENSE file that
617.16 + * accompanied this code).
617.17 + *
617.18 + * You should have received a copy of the GNU General Public License version
617.19 + * 2 along with this work; if not, write to the Free Software Foundation,
617.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
617.21 + *
617.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
617.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
617.24 + * have any questions.
617.25 + */
617.26 +
617.27 +/**
617.28 + * @test
617.29 + *
617.30 + * @bug 6861062
617.31 + * @summary Disable MD2 support
617.32 + *
617.33 + * @author Xuelei Fan
617.34 + */
617.35 +
617.36 +import java.io.*;
617.37 +import java.net.SocketException;
617.38 +import java.util.*;
617.39 +import java.security.Security;
617.40 +import java.security.cert.*;
617.41 +
617.42 +public class CPValidatorIntermediate {
617.43 +
617.44 + // SHA1withRSA 1024
617.45 + static String trustAnchor_SHA1withRSA_1024 =
617.46 + "-----BEGIN CERTIFICATE-----\n" +
617.47 + "MIICPjCCAaegAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
617.48 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa\n" +
617.49 + "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB\n" +
617.50 + "AQUAA4GNADCBiQKBgQC8UdC863pFk1Rvd7xUYd60+e9KsLhb6SqOfU42ZA715FcH\n" +
617.51 + "E1TRvQPmYzAnHcO04TrWZQtO6E+E2RCmeBnetBvIMVka688QkO14wnrIrf2tRodd\n" +
617.52 + "rZNZEBzkX+zyXCRo9tKEUDFf9Qze7Ilbb+Zzm9CUfu4M1Oz6iQcXRx7aM0jEAQID\n" +
617.53 + "AQABo4GJMIGGMB0GA1UdDgQWBBTn0C+xmZY/BTab4W9gBp3dGa7WgjBHBgNVHSME\n" +
617.54 + "QDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEwHzELMAkGA1UEBhMCVVMxEDAO\n" +
617.55 + "BgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAgQw\n" +
617.56 + "DQYJKoZIhvcNAQEFBQADgYEAiCXL2Yp4ruyRXAIJ8zBEaPC9oV2agqgbSbly2z8z\n" +
617.57 + "Ik5SeSRysP+GHBpb8uNyANJnQKv+T0GrJiTLMBjKCOiJl6xzk3EZ2wbQB6G/SQ9+\n" +
617.58 + "UWcsXSC8oGSEPpkj5In/9/UbuUIfT9H8jmdyLNKQvlqgq6kyfnskME7ptGgT95Hc\n" +
617.59 + "tas=\n" +
617.60 + "-----END CERTIFICATE-----";
617.61 +
617.62 + // SHA1withRSA 512
617.63 + static String trustAnchor_SHA1withRSA_512 =
617.64 + "-----BEGIN CERTIFICATE-----\n" +
617.65 + "MIIBuTCCAWOgAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
617.66 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa\n" +
617.67 + "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMFwwDQYJKoZIhvcNAQEB\n" +
617.68 + "BQADSwAwSAJBAM0Kn4ieCdCHsrm78ZMMN4jQEEEqACAMKB7O8j9g4gfz2oAfmHwv\n" +
617.69 + "7JH/hZ0Xen1zUmBbwe+e2J5D/4Fisp9Bn98CAwEAAaOBiTCBhjAdBgNVHQ4EFgQU\n" +
617.70 + "g4Kwd47hdNQBp8grZsRJ5XvhvxAwRwYDVR0jBEAwPoAUg4Kwd47hdNQBp8grZsRJ\n" +
617.71 + "5XvhvxChI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlggEAMA8G\n" +
617.72 + "A1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0GCSqGSIb3DQEBBQUAA0EAn77b\n" +
617.73 + "FJx+HvyRvjZYCzMjnUct3Ql4iLOkURYDh93J5TXi/l9ajvAMEuwzYj0qZ+Ktm/ia\n" +
617.74 + "U5r+8B9nzx+j2Zh3kw==\n" +
617.75 + "-----END CERTIFICATE-----";
617.76 +
617.77 + // SHA1withRSA 1024 signed with RSA 1024
617.78 + static String intermediate_SHA1withRSA_1024_1024 =
617.79 + "-----BEGIN CERTIFICATE-----\n" +
617.80 + "MIICUDCCAbmgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
617.81 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDhaFw0yOTA0MjMwMTExNDha\n" +
617.82 + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
617.83 + "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
617.84 + "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
617.85 + "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
617.86 + "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
617.87 + "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEw\n" +
617.88 + "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
617.89 + "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEFBQADgYEAHze3wAcIe84zNOoN\n" +
617.90 + "P8l9EmlVVoU30z3LB3hxq3m/dC/4gE5Z9Z8EG1wJw4qaxlTZ4dif12nbTTdofVhb\n" +
617.91 + "Bd4syjo6fcUA4q7sfg9TFpoHQ+Ap7PgjK99moMKdMy50Xy8s6FPvaVkF89s66Z6y\n" +
617.92 + "e4q7TSwe6QevGOZaL5N/iy2XGEs=\n" +
617.93 + "-----END CERTIFICATE-----";
617.94 +
617.95 + // SHA1withRSA 1024 signed with RSA 512
617.96 + static String intermediate_SHA1withRSA_1024_512 =
617.97 + "-----BEGIN CERTIFICATE-----\n" +
617.98 + "MIICDzCCAbmgAwIBAgIBAzANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
617.99 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
617.100 + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
617.101 + "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
617.102 + "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
617.103 + "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
617.104 + "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
617.105 + "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBSDgrB3juF01AGnyCtmxEnle+G/EKEjpCEw\n" +
617.106 + "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
617.107 + "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEFBQADQQCYNmdkONfuk07XjRze\n" +
617.108 + "WQyq2cfdae4uIdyUfa2rpgYMtSXuQW3/XrQGiz4G6WBXA2wo7folOOpAKYgvHPrm\n" +
617.109 + "w6Dd\n" +
617.110 + "-----END CERTIFICATE-----";
617.111 +
617.112 + // SHA1withRSA 512 signed with RSA 1024
617.113 + static String intermediate_SHA1withRSA_512_1024 =
617.114 + "-----BEGIN CERTIFICATE-----\n" +
617.115 + "MIICDDCCAXWgAwIBAgIBBDANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
617.116 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
617.117 + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
617.118 + "cy0xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKubXYoEHZpZkhzA9XX+NrpqJ4SV\n" +
617.119 + "lOMBoL3aWExQpJIgrUaZfbGMBBozIHBJMMayokguHbJvq4QigEgLuhfJNqsCAwEA\n" +
617.120 + "AaOBiTCBhjAdBgNVHQ4EFgQUN0CHiTYPtjyvpP2a6y6mhsZ6U40wRwYDVR0jBEAw\n" +
617.121 + "PoAU59AvsZmWPwU2m+FvYAad3Rmu1oKhI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD\n" +
617.122 + "VQQKEwdFeGFtcGxlggEAMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0G\n" +
617.123 + "CSqGSIb3DQEBBQUAA4GBAE2VOlw5ySLT3gUzKCYEga4QPaSrf6lHHPi2g48LscEY\n" +
617.124 + "h9qQXh4nuIVugReBIEf6N49RdT+M2cgRJo4sZ3ukYLGQzxNuttL5nPSuuvrAR1oG\n" +
617.125 + "LUyzOWcUpKHbVHi6zlTt79RvTKZvLcduLutmtPtLJcM9PdiAI1wEooSgxTwZtB/Z\n" +
617.126 + "-----END CERTIFICATE-----";
617.127 +
617.128 + // SHA1withRSA 512 signed with RSA 512
617.129 + static String intermediate_SHA1withRSA_512_512 =
617.130 + "-----BEGIN CERTIFICATE-----\n" +
617.131 + "MIIByzCCAXWgAwIBAgIBBTANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
617.132 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
617.133 + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
617.134 + "cy0xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKubXYoEHZpZkhzA9XX+NrpqJ4SV\n" +
617.135 + "lOMBoL3aWExQpJIgrUaZfbGMBBozIHBJMMayokguHbJvq4QigEgLuhfJNqsCAwEA\n" +
617.136 + "AaOBiTCBhjAdBgNVHQ4EFgQUN0CHiTYPtjyvpP2a6y6mhsZ6U40wRwYDVR0jBEAw\n" +
617.137 + "PoAUg4Kwd47hdNQBp8grZsRJ5XvhvxChI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD\n" +
617.138 + "VQQKEwdFeGFtcGxlggEAMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0G\n" +
617.139 + "CSqGSIb3DQEBBQUAA0EAoCf0Zu559qcB4xPpzqkVsYiyW49S4Yc0mmQXb1yoQgLx\n" +
617.140 + "O+DCkjG5d14+t1MsnkhB2izoQUMxQ3vDc1YnA/tEpw==\n" +
617.141 + "-----END CERTIFICATE-----";
617.142 +
617.143 + // MD2withRSA 1024 signed with RSA 1024
617.144 + static String intermediate_MD2withRSA_1024_1024 =
617.145 + "-----BEGIN CERTIFICATE-----\n" +
617.146 + "MIICUDCCAbmgAwIBAgIBBjANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ\n" +
617.147 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
617.148 + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
617.149 + "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
617.150 + "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
617.151 + "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
617.152 + "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
617.153 + "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEw\n" +
617.154 + "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
617.155 + "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQECBQADgYEAPtEjwbWuC5kc4DPc\n" +
617.156 + "Ttf/wdbD8ZCdAWzcc3XF9q1TlvwVMNk6mbfM05y6ZVsztKTkwZ4EcvFu/yIqw1EB\n" +
617.157 + "E1zlXQCaWXT3/ZMbqYZV4+mx+RUl8spUCb1tda25jnTg3mTOzB1iztm4gy903EMd\n" +
617.158 + "m8omKDKeCgcw5dR4ITQYvyxe1as=\n" +
617.159 + "-----END CERTIFICATE-----";
617.160 +
617.161 + // MD2withRSA 1024 signed with RSA 512
617.162 + static String intermediate_MD2withRSA_1024_512 =
617.163 + "-----BEGIN CERTIFICATE-----\n" +
617.164 + "MIICDzCCAbmgAwIBAgIBBzANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ\n" +
617.165 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla\n" +
617.166 + "MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz\n" +
617.167 + "cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8\n" +
617.168 + "BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg\n" +
617.169 + "bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82\n" +
617.170 + "AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl\n" +
617.171 + "UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBSDgrB3juF01AGnyCtmxEnle+G/EKEjpCEw\n" +
617.172 + "HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw\n" +
617.173 + "AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQECBQADQQBHok1v6xymtpB7N9xy\n" +
617.174 + "0OmDT27uhmzlP0eOzJvXVxj3Oi9TLQJgCUJ9122MzfRAs1E1uJTtvuu+UmI80NQx\n" +
617.175 + "KQdp\n" +
617.176 + "-----END CERTIFICATE-----";
617.177 +
617.178 + private static CertPath generateCertificatePath(String certStr)
617.179 + throws CertificateException {
617.180 + // generate certificate from cert strings
617.181 + CertificateFactory cf = CertificateFactory.getInstance("X.509");
617.182 +
617.183 + ByteArrayInputStream is;
617.184 +
617.185 + is = new ByteArrayInputStream(certStr.getBytes());
617.186 + Certificate cert = cf.generateCertificate(is);
617.187 +
617.188 + // generate certification path
617.189 + List<Certificate> list = Arrays.asList(new Certificate[] {cert});
617.190 +
617.191 + return cf.generateCertPath(list);
617.192 + }
617.193 +
617.194 + private static Set<TrustAnchor> generateTrustAnchors()
617.195 + throws CertificateException {
617.196 + // generate certificate from cert string
617.197 + CertificateFactory cf = CertificateFactory.getInstance("X.509");
617.198 + HashSet<TrustAnchor> anchors = new HashSet<TrustAnchor>();
617.199 +
617.200 + ByteArrayInputStream is =
617.201 + new ByteArrayInputStream(trustAnchor_SHA1withRSA_1024.getBytes());
617.202 + Certificate cert = cf.generateCertificate(is);
617.203 + TrustAnchor anchor = new TrustAnchor((X509Certificate)cert, null);
617.204 + anchors.add(anchor);
617.205 +
617.206 + is = new ByteArrayInputStream(trustAnchor_SHA1withRSA_512.getBytes());
617.207 + cert = cf.generateCertificate(is);
617.208 + anchor = new TrustAnchor((X509Certificate)cert, null);
617.209 + anchors.add(anchor);
617.210 +
617.211 + return anchors;
617.212 + }
617.213 +
617.214 + public static void main(String args[]) throws Exception {
617.215 + try {
617.216 + validate(intermediate_SHA1withRSA_1024_1024);
617.217 + validate(intermediate_SHA1withRSA_1024_512);
617.218 + validate(intermediate_SHA1withRSA_512_1024);
617.219 + validate(intermediate_SHA1withRSA_512_512);
617.220 + } catch (CertPathValidatorException cpve) {
617.221 + throw new Exception(
617.222 + "unexpect exception, it is valid cert", cpve);
617.223 + }
617.224 +
617.225 + try {
617.226 + validate(intermediate_MD2withRSA_1024_1024);
617.227 + throw new Exception("expected algorithm disabled exception");
617.228 + } catch (CertPathValidatorException cpve) {
617.229 + System.out.println("Get the expected exception " + cpve);
617.230 + }
617.231 +
617.232 + try {
617.233 + validate(intermediate_MD2withRSA_1024_512);
617.234 + throw new Exception("expected algorithm disabled exception");
617.235 + } catch (CertPathValidatorException cpve) {
617.236 + System.out.println("Get the expected exception " + cpve);
617.237 + }
617.238 + }
617.239 +
617.240 + private static void validate(String intermediate)
617.241 + throws CertPathValidatorException, Exception {
617.242 +
617.243 + CertPath path = generateCertificatePath(intermediate);
617.244 + Set<TrustAnchor> anchors = generateTrustAnchors();
617.245 +
617.246 + PKIXParameters params = new PKIXParameters(anchors);
617.247 +
617.248 + // disable certificate revocation checking
617.249 + params.setRevocationEnabled(false);
617.250 +
617.251 + // set the validation time
617.252 + params.setDate(new Date(109, 9, 1)); // 2009-09-01
617.253 +
617.254 + CertPathValidator validator = CertPathValidator.getInstance("PKIX");
617.255 +
617.256 + validator.validate(path, params);
617.257 + }
617.258 +
617.259 +}
618.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
618.2 +++ b/test/sun/security/provider/certpath/DisabledAlgorithms/CPValidatorTrustAnchor.java Wed Nov 25 11:08:25 2009 -0800
618.3 @@ -0,0 +1,169 @@
618.4 +/*
618.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
618.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
618.7 + *
618.8 + * This code is free software; you can redistribute it and/or modify it
618.9 + * under the terms of the GNU General Public License version 2 only, as
618.10 + * published by the Free Software Foundation.
618.11 + *
618.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
618.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
618.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
618.15 + * version 2 for more details (a copy is included in the LICENSE file that
618.16 + * accompanied this code).
618.17 + *
618.18 + * You should have received a copy of the GNU General Public License version
618.19 + * 2 along with this work; if not, write to the Free Software Foundation,
618.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
618.21 + *
618.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
618.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
618.24 + * have any questions.
618.25 + */
618.26 +
618.27 +/**
618.28 + * @test
618.29 + *
618.30 + * @bug 6861062
618.31 + * @summary Disable MD2 support
618.32 + *
618.33 + * @author Xuelei Fan
618.34 + */
618.35 +
618.36 +import java.io.*;
618.37 +import java.net.SocketException;
618.38 +import java.util.*;
618.39 +import java.security.Security;
618.40 +import java.security.cert.*;
618.41 +
618.42 +public class CPValidatorTrustAnchor {
618.43 +
618.44 + static String selfSignedCertStr = null;
618.45 +
618.46 + // SHA1withRSA 1024
618.47 + static String trustAnchor_SHA1withRSA_1024 =
618.48 + "-----BEGIN CERTIFICATE-----\n" +
618.49 + "MIICPjCCAaegAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
618.50 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa\n" +
618.51 + "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB\n" +
618.52 + "AQUAA4GNADCBiQKBgQC8UdC863pFk1Rvd7xUYd60+e9KsLhb6SqOfU42ZA715FcH\n" +
618.53 + "E1TRvQPmYzAnHcO04TrWZQtO6E+E2RCmeBnetBvIMVka688QkO14wnrIrf2tRodd\n" +
618.54 + "rZNZEBzkX+zyXCRo9tKEUDFf9Qze7Ilbb+Zzm9CUfu4M1Oz6iQcXRx7aM0jEAQID\n" +
618.55 + "AQABo4GJMIGGMB0GA1UdDgQWBBTn0C+xmZY/BTab4W9gBp3dGa7WgjBHBgNVHSME\n" +
618.56 + "QDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEwHzELMAkGA1UEBhMCVVMxEDAO\n" +
618.57 + "BgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAgQw\n" +
618.58 + "DQYJKoZIhvcNAQEFBQADgYEAiCXL2Yp4ruyRXAIJ8zBEaPC9oV2agqgbSbly2z8z\n" +
618.59 + "Ik5SeSRysP+GHBpb8uNyANJnQKv+T0GrJiTLMBjKCOiJl6xzk3EZ2wbQB6G/SQ9+\n" +
618.60 + "UWcsXSC8oGSEPpkj5In/9/UbuUIfT9H8jmdyLNKQvlqgq6kyfnskME7ptGgT95Hc\n" +
618.61 + "tas=\n" +
618.62 + "-----END CERTIFICATE-----";
618.63 +
618.64 + // SHA1withRSA 512
618.65 + static String trustAnchor_SHA1withRSA_512 =
618.66 + "-----BEGIN CERTIFICATE-----\n" +
618.67 + "MIIBuTCCAWOgAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ\n" +
618.68 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa\n" +
618.69 + "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMFwwDQYJKoZIhvcNAQEB\n" +
618.70 + "BQADSwAwSAJBAM0Kn4ieCdCHsrm78ZMMN4jQEEEqACAMKB7O8j9g4gfz2oAfmHwv\n" +
618.71 + "7JH/hZ0Xen1zUmBbwe+e2J5D/4Fisp9Bn98CAwEAAaOBiTCBhjAdBgNVHQ4EFgQU\n" +
618.72 + "g4Kwd47hdNQBp8grZsRJ5XvhvxAwRwYDVR0jBEAwPoAUg4Kwd47hdNQBp8grZsRJ\n" +
618.73 + "5XvhvxChI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlggEAMA8G\n" +
618.74 + "A1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0GCSqGSIb3DQEBBQUAA0EAn77b\n" +
618.75 + "FJx+HvyRvjZYCzMjnUct3Ql4iLOkURYDh93J5TXi/l9ajvAMEuwzYj0qZ+Ktm/ia\n" +
618.76 + "U5r+8B9nzx+j2Zh3kw==\n" +
618.77 + "-----END CERTIFICATE-----";
618.78 +
618.79 + // MD2withRSA 2048
618.80 + static String trustAnchor_MD2withRSA_2048 =
618.81 + "-----BEGIN CERTIFICATE-----\n" +
618.82 + "MIIDQzCCAiugAwIBAgIBADANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ\n" +
618.83 + "MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDdaFw0zMDA3MTcwMTExNDda\n" +
618.84 + "MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIIBIjANBgkqhkiG9w0B\n" +
618.85 + "AQEFAAOCAQ8AMIIBCgKCAQEArF5pINc5s+aUlmdYlxtAQ3V4TXFnP/XOYHxjfLuX\n" +
618.86 + "eKO/kh78LMvbDisTPQ2yo9YEawwwbUU40xcuzgi0axXgKveHXYdUmTr0hEapq3rv\n" +
618.87 + "g/q2EbOjyXvq4qK2RDoVCN8R3wXiytnY2OFALTx6zc2tW4imJ20svdNVtWhv2syj\n" +
618.88 + "ZTmmRXAeFUbD4qKWAFij0I6pnSgVssvWzeyJUNemym+oiYyaSd7n5j1RNAqUKioo\n" +
618.89 + "K/T0FOOiuPGMqottgx5YRHa6yapCP5QVWRQ+WBIYJY3Wyq7N+Es20LT6761Pk3to\n" +
618.90 + "EFCzM7+zqT/c+pC079HOKXz+m2us+HKp5BKWNnbvgaYPOQIDAQABo4GJMIGGMB0G\n" +
618.91 + "A1UdDgQWBBSrSukJf+mO5LTRasAGD9RRs7SASTBHBgNVHSMEQDA+gBSrSukJf+mO\n" +
618.92 + "5LTRasAGD9RRs7SASaEjpCEwHzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1w\n" +
618.93 + "bGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEC\n" +
618.94 + "BQADggEBAHvsv+DqMJeIW/D+ltkhw37OdMzkMPp4E6Hbp03O3GZ5LfNGczHCb2uL\n" +
618.95 + "sr5T7e/jaBFn6QfmqbOAYAHJSNq2bNNtTbatnHBLuVx13cfxmwk89Cg/tFeoUdcf\n" +
618.96 + "m5hzurB6Ub6SsYMOxZHUYp/KxM9x9a7llC1bK3SKXwd4rVDlXh8DOBvdQNr5Q3yq\n" +
618.97 + "JjY86bSXO14VzNxL/1rqHiszQdPyR/28SBsQVYSi0Zeyc4Yy1ui/cXu1+PWYw3YZ\n" +
618.98 + "QUPHTnkVdPGwRiUqeZIcps+q+ePlQQmDu5qiLD6d8gsyGyY/RvCHWKO5Y9DuX9hs\n" +
618.99 + "he/AhCWQx+TQYGLu0liQqLkGZydyRnA=\n" +
618.100 + "-----END CERTIFICATE-----";
618.101 +
618.102 + private static CertPath generateCertificatePath()
618.103 + throws CertificateException {
618.104 + // generate certificate from cert strings
618.105 + CertificateFactory cf = CertificateFactory.getInstance("X.509");
618.106 +
618.107 + ByteArrayInputStream is;
618.108 +
618.109 + is = new ByteArrayInputStream(selfSignedCertStr.getBytes());
618.110 + Certificate selfSignedCert = cf.generateCertificate(is);
618.111 +
618.112 + // generate certification path
618.113 + List<Certificate> list = Arrays.asList(new Certificate[] {
618.114 + selfSignedCert});
618.115 +
618.116 + return cf.generateCertPath(list);
618.117 + }
618.118 +
618.119 + private static Set<TrustAnchor> generateTrustAnchors()
618.120 + throws CertificateException {
618.121 + // generate certificate from cert string
618.122 + CertificateFactory cf = CertificateFactory.getInstance("X.509");
618.123 +
618.124 + ByteArrayInputStream is =
618.125 + new ByteArrayInputStream(selfSignedCertStr.getBytes());
618.126 + Certificate selfSignedCert = cf.generateCertificate(is);
618.127 +
618.128 + // generate a trust anchor
618.129 + TrustAnchor anchor =
618.130 + new TrustAnchor((X509Certificate)selfSignedCert, null);
618.131 +
618.132 + return Collections.singleton(anchor);
618.133 + }
618.134 +
618.135 + public static void main(String args[]) throws Exception {
618.136 + try {
618.137 + validate(trustAnchor_SHA1withRSA_1024);
618.138 + validate(trustAnchor_SHA1withRSA_512);
618.139 + } catch (CertPathValidatorException cpve) {
618.140 + throw new Exception(
618.141 + "unexpect exception, it is valid cert", cpve);
618.142 + }
618.143 +
618.144 + try {
618.145 + validate(trustAnchor_MD2withRSA_2048);
618.146 + throw new Exception("expected algorithm disabled exception");
618.147 + } catch (CertPathValidatorException cpve) {
618.148 + System.out.println("Get the expected exception " + cpve);
618.149 + }
618.150 + }
618.151 +
618.152 + private static void validate(String trustAnchor)
618.153 + throws CertPathValidatorException, Exception {
618.154 + selfSignedCertStr = trustAnchor;
618.155 +
618.156 + CertPath path = generateCertificatePath();
618.157 + Set<TrustAnchor> anchors = generateTrustAnchors();
618.158 +
618.159 + PKIXParameters params = new PKIXParameters(anchors);
618.160 +
618.161 + // disable certificate revocation checking
618.162 + params.setRevocationEnabled(false);
618.163 +
618.164 + // set the validation time
618.165 + params.setDate(new Date(109, 9, 1)); // 2009-09-01
618.166 +
618.167 + CertPathValidator validator = CertPathValidator.getInstance("PKIX");
618.168 +
618.169 + validator.validate(path, params);
618.170 + }
618.171 +
618.172 +}
619.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
619.2 +++ b/test/sun/security/provider/certpath/DisabledAlgorithms/README Wed Nov 25 11:08:25 2009 -0800
619.3 @@ -0,0 +1,640 @@
619.4 +/*
619.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
619.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
619.7 + *
619.8 + * This code is free software; you can redistribute it and/or modify it
619.9 + * under the terms of the GNU General Public License version 2 only, as
619.10 + * published by the Free Software Foundation.
619.11 + *
619.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
619.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
619.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
619.15 + * version 2 for more details (a copy is included in the LICENSE file that
619.16 + * accompanied this code).
619.17 + *
619.18 + * You should have received a copy of the GNU General Public License version
619.19 + * 2 along with this work; if not, write to the Free Software Foundation,
619.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
619.21 + *
619.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
619.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
619.24 + * have any questions.
619.25 + */
619.26 +
619.27 + Certificates and CRLs
619.28 +
619.29 +Here lists the Certificates, which was generated by generate.sh, used in the
619.30 +test cases.
619.31 +
619.32 +The generate.sh depends on openssl, and it should be run under ksh. The
619.33 +script will create many directories and files, please run it in a
619.34 +directory outside of JDK workspace.
619.35 +
619.36 +1. root certifiate and key (SHA1withRSA 1024, root_cert_sha1_1024.pem)
619.37 +-----BEGIN CERTIFICATE-----
619.38 +MIICPjCCAaegAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ
619.39 +MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa
619.40 +MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB
619.41 +AQUAA4GNADCBiQKBgQC8UdC863pFk1Rvd7xUYd60+e9KsLhb6SqOfU42ZA715FcH
619.42 +E1TRvQPmYzAnHcO04TrWZQtO6E+E2RCmeBnetBvIMVka688QkO14wnrIrf2tRodd
619.43 +rZNZEBzkX+zyXCRo9tKEUDFf9Qze7Ilbb+Zzm9CUfu4M1Oz6iQcXRx7aM0jEAQID
619.44 +AQABo4GJMIGGMB0GA1UdDgQWBBTn0C+xmZY/BTab4W9gBp3dGa7WgjBHBgNVHSME
619.45 +QDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEwHzELMAkGA1UEBhMCVVMxEDAO
619.46 +BgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAgQw
619.47 +DQYJKoZIhvcNAQEFBQADgYEAiCXL2Yp4ruyRXAIJ8zBEaPC9oV2agqgbSbly2z8z
619.48 +Ik5SeSRysP+GHBpb8uNyANJnQKv+T0GrJiTLMBjKCOiJl6xzk3EZ2wbQB6G/SQ9+
619.49 +UWcsXSC8oGSEPpkj5In/9/UbuUIfT9H8jmdyLNKQvlqgq6kyfnskME7ptGgT95Hc
619.50 +tas=
619.51 +-----END CERTIFICATE-----
619.52 +
619.53 +-----BEGIN RSA PRIVATE KEY-----
619.54 +Proc-Type: 4,ENCRYPTED
619.55 +DEK-Info: DES-EDE3-CBC,DF5249E009A0FD79
619.56 +
619.57 +rc316yLipp/vH0i6rhEbEwZpZ+HfKIXnnp/bIIZv2+4lyGUDWrxN0Hk0TcSgWEKm
619.58 +dRGI2fsyWjTgaiHwwmusofXPAjB3s0I2rUUAHXk8/sEuiLLTICx2UAL8k6R33CSQ
619.59 +NKR8t+TluBW3Us71vibWauuMHa5860KiiLWdhkQVLin7m/JBGLtz0zQ0/lZ8CgEm
619.60 +p7eDupPi8FBClCyVewdpmKjgI2KPI4fVIZLMzLeGcWLaOQPN1ERcFWQ1CS/qjfMb
619.61 +F4rtpZ+AzCqP75XPhitT2CnZgaVDxHBtAZQVPuKONMdijKphjqiT/Sd86Gx6OEVE
619.62 +EwwmQya2Q/5aCuH96S00mj00oeIZ7ZtUcVQcch+saJy4vpuxK8pFcEDKmgsvL9+8
619.63 +Hho9RUXVUKRH67uA1NjQSK5+syEIj5sJCDcxOda4QGXeIq9ygaZswxF3nfvffrsa
619.64 +S6IVBXrx0G+Ascu29SHoI+zi3feQszQJIzijHoTTq6FacLHUWzfVuaYa47uaj5qa
619.65 +VYsMVCzi1eX486o7YKPKWiclNczQN86v5n9+c9uggXY12wSOmnf6BB1Ds+oL8JlU
619.66 +IZa67lAyg6G9joAb9rTXN2EE5OTArcFuImK8GHse/3wkIPMglBNnfwpvjC1U+vQm
619.67 +F7iXp+OxnZ5d9sBcrTBEZ9BDlTVlpiZI7EeS1oC8x6DDTdbJR/40Y3wJIDMI9q9T
619.68 +O5EnyXqbmQziO0Tgal43w6mMTUnhG34kqovwxy03mAOZb3yz/RgWlez9wQmPseiI
619.69 +2p2fQIjCPbGFNJt3rdyXOW/BRCii0970HEZeov/TVV/A0vUVajNAjA==
619.70 +-----END RSA PRIVATE KEY-----
619.71 +
619.72 +2. root certifiate and key (SHA1withRSA 512, root_cert_sha1_512.pem)
619.73 +-----BEGIN CERTIFICATE-----
619.74 +MIIBuTCCAWOgAwIBAgIBADANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ
619.75 +MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDRaFw0zMDA3MTcwMTExNDRa
619.76 +MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMFwwDQYJKoZIhvcNAQEB
619.77 +BQADSwAwSAJBAM0Kn4ieCdCHsrm78ZMMN4jQEEEqACAMKB7O8j9g4gfz2oAfmHwv
619.78 +7JH/hZ0Xen1zUmBbwe+e2J5D/4Fisp9Bn98CAwEAAaOBiTCBhjAdBgNVHQ4EFgQU
619.79 +g4Kwd47hdNQBp8grZsRJ5XvhvxAwRwYDVR0jBEAwPoAUg4Kwd47hdNQBp8grZsRJ
619.80 +5XvhvxChI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlggEAMA8G
619.81 +A1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0GCSqGSIb3DQEBBQUAA0EAn77b
619.82 +FJx+HvyRvjZYCzMjnUct3Ql4iLOkURYDh93J5TXi/l9ajvAMEuwzYj0qZ+Ktm/ia
619.83 +U5r+8B9nzx+j2Zh3kw==
619.84 +-----END CERTIFICATE-----
619.85 +
619.86 +-----BEGIN RSA PRIVATE KEY-----
619.87 +Proc-Type: 4,ENCRYPTED
619.88 +DEK-Info: DES-EDE3-CBC,B8BDE38F08C6BB76
619.89 +
619.90 +eJzx2oZE0UXxWpzssSWtKBOCbm3ZXR6iBKX8iKoDUB5SzzmKr+XzxI7kyv92y0pe
619.91 +rNTuuCWpBsLdlz7h8Ipn4pBDYswGU5F9MQOEgIYx60OvGhZODHGRzJ05FXTeCmmu
619.92 +LLp6lGW4SWALcd8g/gJUn1/vp7f1VzQ7RwXWBn4/b34RRYtwr3E6nl4Hc2tEI1in
619.93 +OL+lCdAAyxjGK7KYFHJQK+1E8tYNrer3cejQDcNysGx4o0H123vfp3NtJ6U7LXyi
619.94 +D21y3zmPueJos8LluJiLRsONcrcI3mIfpPBsO+Yl2EJtzS9V6Aaq/YdPkwPHH6Y5
619.95 +lazGMPXq/nffb12fWLL7m5aFb3FNLwWi/qwEynWCEv7Vl/6kLk+aHhjTnYkLvLNH
619.96 +9maQFn6j0S3wqogRfW9BDbfC3fRHP6+8YjEEmQ0RTfE=
619.97 +-----END RSA PRIVATE KEY-----
619.98 +
619.99 +3. root certifiate and key (MD2withRSA 2048, root_cert_md2_2048.pem)
619.100 +-----BEGIN CERTIFICATE-----
619.101 +MIIDQzCCAiugAwIBAgIBADANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ
619.102 +MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDdaFw0zMDA3MTcwMTExNDda
619.103 +MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIIBIjANBgkqhkiG9w0B
619.104 +AQEFAAOCAQ8AMIIBCgKCAQEArF5pINc5s+aUlmdYlxtAQ3V4TXFnP/XOYHxjfLuX
619.105 +eKO/kh78LMvbDisTPQ2yo9YEawwwbUU40xcuzgi0axXgKveHXYdUmTr0hEapq3rv
619.106 +g/q2EbOjyXvq4qK2RDoVCN8R3wXiytnY2OFALTx6zc2tW4imJ20svdNVtWhv2syj
619.107 +ZTmmRXAeFUbD4qKWAFij0I6pnSgVssvWzeyJUNemym+oiYyaSd7n5j1RNAqUKioo
619.108 +K/T0FOOiuPGMqottgx5YRHa6yapCP5QVWRQ+WBIYJY3Wyq7N+Es20LT6761Pk3to
619.109 +EFCzM7+zqT/c+pC079HOKXz+m2us+HKp5BKWNnbvgaYPOQIDAQABo4GJMIGGMB0G
619.110 +A1UdDgQWBBSrSukJf+mO5LTRasAGD9RRs7SASTBHBgNVHSMEQDA+gBSrSukJf+mO
619.111 +5LTRasAGD9RRs7SASaEjpCEwHzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1w
619.112 +bGWCAQAwDwYDVR0TAQH/BAUwAwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEC
619.113 +BQADggEBAHvsv+DqMJeIW/D+ltkhw37OdMzkMPp4E6Hbp03O3GZ5LfNGczHCb2uL
619.114 +sr5T7e/jaBFn6QfmqbOAYAHJSNq2bNNtTbatnHBLuVx13cfxmwk89Cg/tFeoUdcf
619.115 +m5hzurB6Ub6SsYMOxZHUYp/KxM9x9a7llC1bK3SKXwd4rVDlXh8DOBvdQNr5Q3yq
619.116 +JjY86bSXO14VzNxL/1rqHiszQdPyR/28SBsQVYSi0Zeyc4Yy1ui/cXu1+PWYw3YZ
619.117 +QUPHTnkVdPGwRiUqeZIcps+q+ePlQQmDu5qiLD6d8gsyGyY/RvCHWKO5Y9DuX9hs
619.118 +he/AhCWQx+TQYGLu0liQqLkGZydyRnA=
619.119 +-----END CERTIFICATE-----
619.120 +
619.121 +-----BEGIN RSA PRIVATE KEY-----
619.122 +Proc-Type: 4,ENCRYPTED
619.123 +DEK-Info: DES-EDE3-CBC,3910D329AD49ECFC
619.124 +
619.125 +6K0OU3Xrl2H6kz7x7EHXkM0/Wd6jXBBwWsaroUIGnbIMmljJXPfgcuDUu6f5Imk1
619.126 +ndoU0GWjxa1QNjteAQQtFoLDP8rienLs0b969OcAxB0EOffQFkEfsfXdyEIgdwkD
619.127 +ETczwDIyd8Wj62ClydJES3jKB9Nc9kMIlsoZ+h24TyJeeRsHAtMrz+mlOHsUWDQ5
619.128 +FyYZelnx+fQ5maD3bura7xLiNl8CvgWz0wt2Wt4djdMGhQ3OWd0/GWweP+2xnL6n
619.129 +5tDJ5On50+Z5T8Jhx62yg+wQiBKAYnYw6OX3skJwWknuAvYz3Z3e12DHFx6w5EAU
619.130 +K7lg7fHMqHNirUkJOlYzgJ21ybV4uQmFRNQJwI9h6GVfdZWPEU+Ni42AlNgNYskF
619.131 +K19dONNNt0Gwkcm2VOYzwYGDyaQW2YIGDk1fbZdVSu/h/lyOC/RmorGWroAbYsyB
619.132 +/GUIilcLtQHPGI8XuojTS2/UWcKactpceN3UOnQkus3/smViEqqB/NQ/lcozgs0o
619.133 +7ZG6H6to7w1yb5VR2d7B2bS7MNJt1AsOB5ydAMYIccdHDTI7CfRK6axQ70O/JPnJ
619.134 +WLY2e41ig2uAWk/3fRb8L6d3keVcN7y4WnkXPbHhulqtxQo78iSQQAf7tDMBxWKx
619.135 +C5LQW3CxLkHKp6g22SDxl2LjJyu5nDbtIh3Pq+BCoA25uqXC4rPoWwV7EWYv8Z+Y
619.136 +E6dS98SEa+cDhpllvGzbTKgcP1VqtQbb9VT92UT1mFrklqRuQIxROeCe4wjp5TKo
619.137 +D2losUDdzpqBHkBNo2I8qZkgybeCvWEq73my2+JG1AAIFFB1kzfBNaBDGiGSuUuS
619.138 +5peV8156aaLg5pxdieoRJ3Y7eaWN1wH5CnRnafoB+lxSUsQO1a7y2LbpedrKjs+2
619.139 +AryPHQw7HLd8IQevmvd7BhJLdvlt+kXzWID/pUsSAYvI7aP4daQJuAt/kwmU27Gd
619.140 +wqhV8Tjbb84vFGmqGHtb2YbKfUrsPUNOLBF+U4SDAgBhEyhINQZyRDcqqoywO5Dr
619.141 +sV46nTEfwAgt88KFt2CEhiyvoJbtCj1iMJeAzuljwF4z4RzB1i3TK0MaJYID2rxB
619.142 +E1vK9EZIssk/NeImN2YCbuqOhU58jtOwYh3ruS+mZQm1APvJF9N4tCCVQsjWC6zY
619.143 +4eqs7T6VDFH4AaT7b3J3rTsEpWIDUfagetZs5kR9SiWJC7dU7r53gGg4avVyIIHD
619.144 ++MYCS+auD9/nmVf4iYstVgJFMUJXC2EUOLi0r8KmDkCILl/K3X/W7QwFTnC07gLh
619.145 +/9HjWFJ0R6cyODzvE8NGPMeuJGUT2F+mA1vaAC/PBGz+61AF0BjWTZ7x2sH+tSPP
619.146 +/GVEaCgyzrKRX5XX+7DulTcmFj1JNfMmtbDaJa9WnwOI4qszBGrAcYeYTHXR6Yov
619.147 +Ux/P6RStfa+UwSjo8i3nfdgLk+RXCpN0srMjSmiQx8d5R/kISqXKDtQfS5M6gsoh
619.148 +ROz+6zZP8Gh8yakr1p4C6JUSiLDYP5qXzxr8bp+oxvpY7anEDAqx21HyExEAu+gy
619.149 +IrNl75FWqV8BbKxoFfe9LqyDaryXXA8oy6F+4BT/zRrxp+dym9pbd+OZR423BIij
619.150 +-----END RSA PRIVATE KEY-----
619.151 +
619.152 +4. subca certificate and key (SHA1withRSA 1024, root_cert_sha1_1024.pem signed)
619.153 +-----BEGIN CERTIFICATE-----
619.154 +MIICUDCCAbmgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ
619.155 +MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDhaFw0yOTA0MjMwMTExNDha
619.156 +MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz
619.157 +cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8
619.158 +BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg
619.159 +bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82
619.160 +AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl
619.161 +UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEw
619.162 +HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw
619.163 +AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEFBQADgYEAHze3wAcIe84zNOoN
619.164 +P8l9EmlVVoU30z3LB3hxq3m/dC/4gE5Z9Z8EG1wJw4qaxlTZ4dif12nbTTdofVhb
619.165 +Bd4syjo6fcUA4q7sfg9TFpoHQ+Ap7PgjK99moMKdMy50Xy8s6FPvaVkF89s66Z6y
619.166 +e4q7TSwe6QevGOZaL5N/iy2XGEs=
619.167 +-----END CERTIFICATE-----
619.168 +
619.169 +-----BEGIN RSA PRIVATE KEY-----
619.170 +Proc-Type: 4,ENCRYPTED
619.171 +DEK-Info: DES-EDE3-CBC,0480E76FD259323B
619.172 +
619.173 +npiifBm1mHq1Z9QgAV5T35Xbnea9VnwqYQWNfRRKmpfYSdkQJ0few18YtnfZwh9e
619.174 +LKCWx+lq1V4yDG4SbxXDq71Dyvx1vZY+w4h+6M1+6KGFG1VDBfN3e5aLgK8EG9pZ
619.175 +yHZH7iB7HiQXH5q53jL6NUZn55C3XEk1sErpK7R1c0Y8Qp2TGiu+lck3K+zR9GiO
619.176 +5aJMKbShReB0Nfy3JJNKRFSd95QMTTjbq6iIvhN8O02bo4I4I3HTyD8qyR7ViiHl
619.177 +FmOukjwn4fjJvK0WYKYUjod8oEiMdR2nr73eOGZBAnEorDGQ8VnnCAleSv74is1k
619.178 +W7M07UP7EJJq9hSZfeMqk5QivtWrqvWG1SWxpTowKTEAyTn7u5U13k0DiRcsg0WT
619.179 +4mSMiLOhUNgIWcHElbTQPSVDcVznhNk0dWPDwKoUjp+orCuH+NvHKBAu+hnuip3e
619.180 +Ji7WGrHXI7QxAr5qr5ogl5x4yH4drIbq9fUea3NTuGPuPyu9fWjOSDmqPRKRMJFR
619.181 +UxxVFcyrW8iSBV5cvB7M1ADS40y6l4ryYmKjXbsOI4Ci8LJWJ4ZB61WQP7TvPQGS
619.182 +mNFmTTB2dwbpimr4KjV9j2bA9x0jAsjlcQZ5j1GOeyYCEDGKDJw0XD/zI+j0dpVc
619.183 +eu8YtuJGTyO1h+HiI3D9LrMuyUxxckvFHKe00+4xMz1hpqVo/kxe6gqf/9ES4M/h
619.184 +6/NeTzeqyJF2rgxK6KJJdmaKVYI+bvAQ3cKl+RZmgOjx4eig58N5uthqFgU7rQ+e
619.185 +GM9/y8C9WpPqITcJlY7I/7AkqvYDBwBsH/9mf4g9OUbC1Ah+MX8UIQ==
619.186 +-----END RSA PRIVATE KEY-----
619.187 +
619.188 +
619.189 +5. subca certificate and key (SHA1withRSA 1024, root_cert_sha1_512.pem signed)
619.190 +-----BEGIN CERTIFICATE-----
619.191 +MIICDzCCAbmgAwIBAgIBAzANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ
619.192 +MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla
619.193 +MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz
619.194 +cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8
619.195 +BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg
619.196 +bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82
619.197 +AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl
619.198 +UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBSDgrB3juF01AGnyCtmxEnle+G/EKEjpCEw
619.199 +HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw
619.200 +AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQEFBQADQQCYNmdkONfuk07XjRze
619.201 +WQyq2cfdae4uIdyUfa2rpgYMtSXuQW3/XrQGiz4G6WBXA2wo7folOOpAKYgvHPrm
619.202 +w6Dd
619.203 +-----END CERTIFICATE-----
619.204 +
619.205 +-----BEGIN RSA PRIVATE KEY-----
619.206 +Proc-Type: 4,ENCRYPTED
619.207 +DEK-Info: DES-EDE3-CBC,0480E76FD259323B
619.208 +
619.209 +npiifBm1mHq1Z9QgAV5T35Xbnea9VnwqYQWNfRRKmpfYSdkQJ0few18YtnfZwh9e
619.210 +LKCWx+lq1V4yDG4SbxXDq71Dyvx1vZY+w4h+6M1+6KGFG1VDBfN3e5aLgK8EG9pZ
619.211 +yHZH7iB7HiQXH5q53jL6NUZn55C3XEk1sErpK7R1c0Y8Qp2TGiu+lck3K+zR9GiO
619.212 +5aJMKbShReB0Nfy3JJNKRFSd95QMTTjbq6iIvhN8O02bo4I4I3HTyD8qyR7ViiHl
619.213 +FmOukjwn4fjJvK0WYKYUjod8oEiMdR2nr73eOGZBAnEorDGQ8VnnCAleSv74is1k
619.214 +W7M07UP7EJJq9hSZfeMqk5QivtWrqvWG1SWxpTowKTEAyTn7u5U13k0DiRcsg0WT
619.215 +4mSMiLOhUNgIWcHElbTQPSVDcVznhNk0dWPDwKoUjp+orCuH+NvHKBAu+hnuip3e
619.216 +Ji7WGrHXI7QxAr5qr5ogl5x4yH4drIbq9fUea3NTuGPuPyu9fWjOSDmqPRKRMJFR
619.217 +UxxVFcyrW8iSBV5cvB7M1ADS40y6l4ryYmKjXbsOI4Ci8LJWJ4ZB61WQP7TvPQGS
619.218 +mNFmTTB2dwbpimr4KjV9j2bA9x0jAsjlcQZ5j1GOeyYCEDGKDJw0XD/zI+j0dpVc
619.219 +eu8YtuJGTyO1h+HiI3D9LrMuyUxxckvFHKe00+4xMz1hpqVo/kxe6gqf/9ES4M/h
619.220 +6/NeTzeqyJF2rgxK6KJJdmaKVYI+bvAQ3cKl+RZmgOjx4eig58N5uthqFgU7rQ+e
619.221 +GM9/y8C9WpPqITcJlY7I/7AkqvYDBwBsH/9mf4g9OUbC1Ah+MX8UIQ==
619.222 +-----END RSA PRIVATE KEY-----
619.223 +
619.224 +
619.225 +6. subca certificate and key (SHA1withRSA 512, root_cert_sha1_1024.pem signed)
619.226 +-----BEGIN CERTIFICATE-----
619.227 +MIICDDCCAXWgAwIBAgIBBDANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ
619.228 +MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla
619.229 +MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz
619.230 +cy0xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKubXYoEHZpZkhzA9XX+NrpqJ4SV
619.231 +lOMBoL3aWExQpJIgrUaZfbGMBBozIHBJMMayokguHbJvq4QigEgLuhfJNqsCAwEA
619.232 +AaOBiTCBhjAdBgNVHQ4EFgQUN0CHiTYPtjyvpP2a6y6mhsZ6U40wRwYDVR0jBEAw
619.233 +PoAU59AvsZmWPwU2m+FvYAad3Rmu1oKhI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD
619.234 +VQQKEwdFeGFtcGxlggEAMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0G
619.235 +CSqGSIb3DQEBBQUAA4GBAE2VOlw5ySLT3gUzKCYEga4QPaSrf6lHHPi2g48LscEY
619.236 +h9qQXh4nuIVugReBIEf6N49RdT+M2cgRJo4sZ3ukYLGQzxNuttL5nPSuuvrAR1oG
619.237 +LUyzOWcUpKHbVHi6zlTt79RvTKZvLcduLutmtPtLJcM9PdiAI1wEooSgxTwZtB/Z
619.238 +-----END CERTIFICATE-----
619.239 +
619.240 +-----BEGIN RSA PRIVATE KEY-----
619.241 +Proc-Type: 4,ENCRYPTED
619.242 +DEK-Info: DES-EDE3-CBC,0A94F7EA4C89CA33
619.243 +
619.244 +tfKdAZVSrpeS/hU4+mGYcGGx3nNqrE+CzDAfLadVuXz5ju5p9oFhLTZj99wK+uHn
619.245 +prrWmDNOdYKRBJn7h40WV6zi4lR3JgnuYNxH8fxO3PI+HQ9IuvdoTyqUeXTP4Zj1
619.246 +BCnr1k1D2WGDXvnh+saq9qRpMKThjK/OF0YmDa07PI5NOBdMA3EmkNYfwib2GfBV
619.247 +el4FVkfnPQkLGahTh3SC62TzPlnsAgirCeua7ZLPqN3fkZkYbXZd9op2D31n7cBP
619.248 +zztg0ah8WF4gPOd/BBZeR9XDog5qm/wzyBj0F6ClHRPjpGYhAm2Vw66xOBlGFYI9
619.249 +lVmFQzrPcDNlFTybzhl5C6Qy4cPQh+QErDWxljVI52oYYmY/KRmUGGL7hEG8ZGOn
619.250 +EUgFrEJyAY7w4wpBC5n9SotwyPXhwKQ1uCBq+1zElPw=
619.251 +-----END RSA PRIVATE KEY-----
619.252 +
619.253 +7. subca certificate and key (SHA1withRSA 512, root_cert_sha1_512.pem signed)
619.254 +-----BEGIN CERTIFICATE-----
619.255 +MIIByzCCAXWgAwIBAgIBBTANBgkqhkiG9w0BAQUFADAfMQswCQYDVQQGEwJVUzEQ
619.256 +MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla
619.257 +MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz
619.258 +cy0xMFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAKubXYoEHZpZkhzA9XX+NrpqJ4SV
619.259 +lOMBoL3aWExQpJIgrUaZfbGMBBozIHBJMMayokguHbJvq4QigEgLuhfJNqsCAwEA
619.260 +AaOBiTCBhjAdBgNVHQ4EFgQUN0CHiTYPtjyvpP2a6y6mhsZ6U40wRwYDVR0jBEAw
619.261 +PoAUg4Kwd47hdNQBp8grZsRJ5XvhvxChI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD
619.262 +VQQKEwdFeGFtcGxlggEAMA8GA1UdEwEB/wQFMAMBAf8wCwYDVR0PBAQDAgIEMA0G
619.263 +CSqGSIb3DQEBBQUAA0EAoCf0Zu559qcB4xPpzqkVsYiyW49S4Yc0mmQXb1yoQgLx
619.264 +O+DCkjG5d14+t1MsnkhB2izoQUMxQ3vDc1YnA/tEpw==
619.265 +-----END CERTIFICATE-----
619.266 +
619.267 +-----BEGIN RSA PRIVATE KEY-----
619.268 +Proc-Type: 4,ENCRYPTED
619.269 +DEK-Info: DES-EDE3-CBC,0A94F7EA4C89CA33
619.270 +
619.271 +tfKdAZVSrpeS/hU4+mGYcGGx3nNqrE+CzDAfLadVuXz5ju5p9oFhLTZj99wK+uHn
619.272 +prrWmDNOdYKRBJn7h40WV6zi4lR3JgnuYNxH8fxO3PI+HQ9IuvdoTyqUeXTP4Zj1
619.273 +BCnr1k1D2WGDXvnh+saq9qRpMKThjK/OF0YmDa07PI5NOBdMA3EmkNYfwib2GfBV
619.274 +el4FVkfnPQkLGahTh3SC62TzPlnsAgirCeua7ZLPqN3fkZkYbXZd9op2D31n7cBP
619.275 +zztg0ah8WF4gPOd/BBZeR9XDog5qm/wzyBj0F6ClHRPjpGYhAm2Vw66xOBlGFYI9
619.276 +lVmFQzrPcDNlFTybzhl5C6Qy4cPQh+QErDWxljVI52oYYmY/KRmUGGL7hEG8ZGOn
619.277 +EUgFrEJyAY7w4wpBC5n9SotwyPXhwKQ1uCBq+1zElPw=
619.278 +-----END RSA PRIVATE KEY-----
619.279 +
619.280 +8. subca certificate and key (MD2withRSA 1024, root_cert_sha1_1024.pem signed)
619.281 +-----BEGIN CERTIFICATE-----
619.282 +MIICUDCCAbmgAwIBAgIBBjANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ
619.283 +MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla
619.284 +MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz
619.285 +cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8
619.286 +BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg
619.287 +bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82
619.288 +AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl
619.289 +UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBTn0C+xmZY/BTab4W9gBp3dGa7WgqEjpCEw
619.290 +HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw
619.291 +AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQECBQADgYEAPtEjwbWuC5kc4DPc
619.292 +Ttf/wdbD8ZCdAWzcc3XF9q1TlvwVMNk6mbfM05y6ZVsztKTkwZ4EcvFu/yIqw1EB
619.293 +E1zlXQCaWXT3/ZMbqYZV4+mx+RUl8spUCb1tda25jnTg3mTOzB1iztm4gy903EMd
619.294 +m8omKDKeCgcw5dR4ITQYvyxe1as=
619.295 +-----END CERTIFICATE-----
619.296 +
619.297 +-----BEGIN RSA PRIVATE KEY-----
619.298 +Proc-Type: 4,ENCRYPTED
619.299 +DEK-Info: DES-EDE3-CBC,0480E76FD259323B
619.300 +
619.301 +npiifBm1mHq1Z9QgAV5T35Xbnea9VnwqYQWNfRRKmpfYSdkQJ0few18YtnfZwh9e
619.302 +LKCWx+lq1V4yDG4SbxXDq71Dyvx1vZY+w4h+6M1+6KGFG1VDBfN3e5aLgK8EG9pZ
619.303 +yHZH7iB7HiQXH5q53jL6NUZn55C3XEk1sErpK7R1c0Y8Qp2TGiu+lck3K+zR9GiO
619.304 +5aJMKbShReB0Nfy3JJNKRFSd95QMTTjbq6iIvhN8O02bo4I4I3HTyD8qyR7ViiHl
619.305 +FmOukjwn4fjJvK0WYKYUjod8oEiMdR2nr73eOGZBAnEorDGQ8VnnCAleSv74is1k
619.306 +W7M07UP7EJJq9hSZfeMqk5QivtWrqvWG1SWxpTowKTEAyTn7u5U13k0DiRcsg0WT
619.307 +4mSMiLOhUNgIWcHElbTQPSVDcVznhNk0dWPDwKoUjp+orCuH+NvHKBAu+hnuip3e
619.308 +Ji7WGrHXI7QxAr5qr5ogl5x4yH4drIbq9fUea3NTuGPuPyu9fWjOSDmqPRKRMJFR
619.309 +UxxVFcyrW8iSBV5cvB7M1ADS40y6l4ryYmKjXbsOI4Ci8LJWJ4ZB61WQP7TvPQGS
619.310 +mNFmTTB2dwbpimr4KjV9j2bA9x0jAsjlcQZ5j1GOeyYCEDGKDJw0XD/zI+j0dpVc
619.311 +eu8YtuJGTyO1h+HiI3D9LrMuyUxxckvFHKe00+4xMz1hpqVo/kxe6gqf/9ES4M/h
619.312 +6/NeTzeqyJF2rgxK6KJJdmaKVYI+bvAQ3cKl+RZmgOjx4eig58N5uthqFgU7rQ+e
619.313 +GM9/y8C9WpPqITcJlY7I/7AkqvYDBwBsH/9mf4g9OUbC1Ah+MX8UIQ==
619.314 +-----END RSA PRIVATE KEY-----
619.315 +
619.316 +
619.317 +9. subca certificate and key (MD2withRSA 1024, root_cert_sha1_512.pem signed)
619.318 +-----BEGIN CERTIFICATE-----
619.319 +MIICDzCCAbmgAwIBAgIBBzANBgkqhkiG9w0BAQIFADAfMQswCQYDVQQGEwJVUzEQ
619.320 +MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDYwMTExNDlaFw0yOTA0MjMwMTExNDla
619.321 +MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz
619.322 +cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCVOqnlZspyAEr90ELFaUo8
619.323 +BF0O2Kn0yTdUeyiLOth4RA3qxWrjxJq45VmEBjZpEzPHfnp3PhnfmLcLfhoPONFg
619.324 +bcHzlkj75ZaKCgHoyV456fMBmj348fcoUkH2WdSQ82pmxHOiHqquYNUSTimFIq82
619.325 +AayhbKqDmhfx5lJdYNqd5QIDAQABo4GJMIGGMB0GA1UdDgQWBBTfWD9mRTppcUAl
619.326 +UqGuu/R5t8CB5jBHBgNVHSMEQDA+gBSDgrB3juF01AGnyCtmxEnle+G/EKEjpCEw
619.327 +HzELMAkGA1UEBhMCVVMxEDAOBgNVBAoTB0V4YW1wbGWCAQAwDwYDVR0TAQH/BAUw
619.328 +AwEB/zALBgNVHQ8EBAMCAgQwDQYJKoZIhvcNAQECBQADQQBHok1v6xymtpB7N9xy
619.329 +0OmDT27uhmzlP0eOzJvXVxj3Oi9TLQJgCUJ9122MzfRAs1E1uJTtvuu+UmI80NQx
619.330 +KQdp
619.331 +-----END CERTIFICATE-----
619.332 +
619.333 +-----BEGIN RSA PRIVATE KEY-----
619.334 +Proc-Type: 4,ENCRYPTED
619.335 +DEK-Info: DES-EDE3-CBC,0480E76FD259323B
619.336 +
619.337 +npiifBm1mHq1Z9QgAV5T35Xbnea9VnwqYQWNfRRKmpfYSdkQJ0few18YtnfZwh9e
619.338 +LKCWx+lq1V4yDG4SbxXDq71Dyvx1vZY+w4h+6M1+6KGFG1VDBfN3e5aLgK8EG9pZ
619.339 +yHZH7iB7HiQXH5q53jL6NUZn55C3XEk1sErpK7R1c0Y8Qp2TGiu+lck3K+zR9GiO
619.340 +5aJMKbShReB0Nfy3JJNKRFSd95QMTTjbq6iIvhN8O02bo4I4I3HTyD8qyR7ViiHl
619.341 +FmOukjwn4fjJvK0WYKYUjod8oEiMdR2nr73eOGZBAnEorDGQ8VnnCAleSv74is1k
619.342 +W7M07UP7EJJq9hSZfeMqk5QivtWrqvWG1SWxpTowKTEAyTn7u5U13k0DiRcsg0WT
619.343 +4mSMiLOhUNgIWcHElbTQPSVDcVznhNk0dWPDwKoUjp+orCuH+NvHKBAu+hnuip3e
619.344 +Ji7WGrHXI7QxAr5qr5ogl5x4yH4drIbq9fUea3NTuGPuPyu9fWjOSDmqPRKRMJFR
619.345 +UxxVFcyrW8iSBV5cvB7M1ADS40y6l4ryYmKjXbsOI4Ci8LJWJ4ZB61WQP7TvPQGS
619.346 +mNFmTTB2dwbpimr4KjV9j2bA9x0jAsjlcQZ5j1GOeyYCEDGKDJw0XD/zI+j0dpVc
619.347 +eu8YtuJGTyO1h+HiI3D9LrMuyUxxckvFHKe00+4xMz1hpqVo/kxe6gqf/9ES4M/h
619.348 +6/NeTzeqyJF2rgxK6KJJdmaKVYI+bvAQ3cKl+RZmgOjx4eig58N5uthqFgU7rQ+e
619.349 +GM9/y8C9WpPqITcJlY7I/7AkqvYDBwBsH/9mf4g9OUbC1Ah+MX8UIQ==
619.350 +-----END RSA PRIVATE KEY-----
619.351 +
619.352 +
619.353 +a. end entity certificate and key
619.354 + (SHA1withRSA 1024, subca_cert_sha1_1024_1024.pem signed)
619.355 +-----BEGIN CERTIFICATE-----
619.356 +MIICNzCCAaCgAwIBAgIBAjANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ
619.357 +MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx
619.358 +NTBaFw0yOTA0MjMwMTExNTBaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt
619.359 +cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG
619.360 +9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt
619.361 +vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v
619.362 +z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6
619.363 +c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07
619.364 +OorBleV92TAfBgNVHSMEGDAWgBTfWD9mRTppcUAlUqGuu/R5t8CB5jANBgkqhkiG
619.365 +9w0BAQUFAAOBgQAOfIeasDg91CR3jGfuAEVKwncM1OPFmniAUcdPm74cCAyJ90Me
619.366 +dhUElWPGoAuXGfiyZlOlGUYWqEroe/dnkmnotJjLWR+MA4ZyX3O1YI8T4W3deWcC
619.367 +J4WMCF7mp17SaYYKX9F0AxwNJFpUkbB41IkTxPr0MmzB1871/pbY8dLAvA==
619.368 +-----END CERTIFICATE-----
619.369 +
619.370 +-----BEGIN RSA PRIVATE KEY-----
619.371 +Proc-Type: 4,ENCRYPTED
619.372 +DEK-Info: DES-EDE3-CBC,1FE5A37B770AF83D
619.373 +
619.374 +042bWtt4q0cB8pRuPUlMVncTP/WAz+mmPw3jXI3LFOBZeK6zFEDpI5M9c2JO+rqp
619.375 +Za5UkYuIg69V7LngriqRynkRGGQp3xASMLr5NVbKHTE/Ol/iIuxKaCkumZmGXB/z
619.376 +8bxQF5XN4tbKT4s3sWWmmKMicg6MHvySi3QVRG11PHRu/q7CEFPzJKRQ3fpaNcKD
619.377 +NTBI5F6GP9ENa/eog4WGENjXS0v4Wa3IfaOhjKXrSxjLUqLH0C8g5WWg5IrXXtuI
619.378 +pgyJ2kkE3Y/ChU7p7R42we6tBZqF5SiL5kFDn86DmHgCslTiZkIoE5i644sp03Sd
619.379 +XkHyHu0VIeYp3nDwRA7S98837W4F6i1BnXA5f3EaE3rNGjsxK8zL2pvdCcDYbese
619.380 +ETfba16HMzLXe1b4RSI3gwhlQ2MNKBwvskkQESf/Ew1DskBY0MCYFxo6hIp6LqMo
619.381 +HAl5kvCwvuYL2jBdQhkKxU+Leu5Ei8Ie9XYNVy4yUeUAMnSUkVaEs/I8z+Mk8oYq
619.382 +4QWqOc66XLcI13coDoxmv54kye3RjqdmZI8mg/3LCFotwceDuXyD43/vVhoTPEnp
619.383 +CqXafV2pw4y95skMHmktI2qvSahaM4P6GGXl8HqmP3b+8V5mxMhNtVnuUha2kouw
619.384 +DLNFUTg1cCLahM5SRolyA/XTGh7JOkJMYWPeJwN7l3K+lBtHHfj6DHtKEjUcyZFd
619.385 ++Z55pDoAERumB6+BCnt6X2/0kEDV219RmsgxkGTWdFs+M7Y6EYYRtlinH4nqL6UD
619.386 +eHWitYIatAHOvdHeNrbXN9L5P3tsUB4HzFa46WWtKqRtbCVTuPVZdw==
619.387 +-----END RSA PRIVATE KEY-----
619.388 +
619.389 +b. end entity certificate and key
619.390 + (SHA1withRSA 1024, subca_cert_sha1_512_1024.pem signed)
619.391 +-----BEGIN CERTIFICATE-----
619.392 +MIIB9jCCAaCgAwIBAgIBAzANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ
619.393 +MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx
619.394 +NTBaFw0yOTA0MjMwMTExNTBaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt
619.395 +cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG
619.396 +9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt
619.397 +vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v
619.398 +z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6
619.399 +c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07
619.400 +OorBleV92TAfBgNVHSMEGDAWgBQ3QIeJNg+2PK+k/ZrrLqaGxnpTjTANBgkqhkiG
619.401 +9w0BAQUFAANBADV6X+ea0ftEKXy7yKNAbdIp35893T6AVwbdclomPkeOs86OtoTG
619.402 +1BIzWSK9QE7W6Wbf63e2RdcqoLK+DxsuwUg=
619.403 +-----END CERTIFICATE-----
619.404 +
619.405 +-----BEGIN RSA PRIVATE KEY-----
619.406 +Proc-Type: 4,ENCRYPTED
619.407 +DEK-Info: DES-EDE3-CBC,1FE5A37B770AF83D
619.408 +
619.409 +042bWtt4q0cB8pRuPUlMVncTP/WAz+mmPw3jXI3LFOBZeK6zFEDpI5M9c2JO+rqp
619.410 +Za5UkYuIg69V7LngriqRynkRGGQp3xASMLr5NVbKHTE/Ol/iIuxKaCkumZmGXB/z
619.411 +8bxQF5XN4tbKT4s3sWWmmKMicg6MHvySi3QVRG11PHRu/q7CEFPzJKRQ3fpaNcKD
619.412 +NTBI5F6GP9ENa/eog4WGENjXS0v4Wa3IfaOhjKXrSxjLUqLH0C8g5WWg5IrXXtuI
619.413 +pgyJ2kkE3Y/ChU7p7R42we6tBZqF5SiL5kFDn86DmHgCslTiZkIoE5i644sp03Sd
619.414 +XkHyHu0VIeYp3nDwRA7S98837W4F6i1BnXA5f3EaE3rNGjsxK8zL2pvdCcDYbese
619.415 +ETfba16HMzLXe1b4RSI3gwhlQ2MNKBwvskkQESf/Ew1DskBY0MCYFxo6hIp6LqMo
619.416 +HAl5kvCwvuYL2jBdQhkKxU+Leu5Ei8Ie9XYNVy4yUeUAMnSUkVaEs/I8z+Mk8oYq
619.417 +4QWqOc66XLcI13coDoxmv54kye3RjqdmZI8mg/3LCFotwceDuXyD43/vVhoTPEnp
619.418 +CqXafV2pw4y95skMHmktI2qvSahaM4P6GGXl8HqmP3b+8V5mxMhNtVnuUha2kouw
619.419 +DLNFUTg1cCLahM5SRolyA/XTGh7JOkJMYWPeJwN7l3K+lBtHHfj6DHtKEjUcyZFd
619.420 ++Z55pDoAERumB6+BCnt6X2/0kEDV219RmsgxkGTWdFs+M7Y6EYYRtlinH4nqL6UD
619.421 +eHWitYIatAHOvdHeNrbXN9L5P3tsUB4HzFa46WWtKqRtbCVTuPVZdw==
619.422 +-----END RSA PRIVATE KEY-----
619.423 +
619.424 +c. end entity certificate and key
619.425 + (SHA1withRSA 512, subca_cert_sha1_1024_1024.pem signed)
619.426 +-----BEGIN CERTIFICATE-----
619.427 +MIIB8zCCAVygAwIBAgIBBDANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ
619.428 +MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx
619.429 +NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt
619.430 +cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTBcMA0GCSqGSIb3
619.431 +DQEBAQUAA0sAMEgCQQCpfQzhld7w2JhW/aRaLkmrLrc/QAsQE+J4DXioXaajsWPo
619.432 +uMmYmuiQolb6OIY/LcivSubKM3G5PkAWoovUPIWLAgMBAAGjTzBNMAsGA1UdDwQE
619.433 +AwID6DAdBgNVHQ4EFgQUFWuXLkf4Ji57H9ISycgWi982TUIwHwYDVR0jBBgwFoAU
619.434 +31g/ZkU6aXFAJVKhrrv0ebfAgeYwDQYJKoZIhvcNAQEFBQADgYEAUyW8PrEdbzLu
619.435 +B+h6UemBOJ024rYq90hJE/5wUEKPvxZ9vPEUgl+io6cGhL3cLfxfh6z5xtEGp4Tb
619.436 +NB0Ye3Qi01FBiNDY8s3rQRrmel6VysU8u+0Oi2jmQY6vZXn/zXN5rrTLITCaSicG
619.437 +dOMv1xLM83Ee432WWlDwKOUxhzDGpWc=
619.438 +-----END CERTIFICATE-----
619.439 +
619.440 +-----BEGIN RSA PRIVATE KEY-----
619.441 +Proc-Type: 4,ENCRYPTED
619.442 +DEK-Info: DES-EDE3-CBC,153918982D82A26E
619.443 +
619.444 +5w5MNd16M1draSfIFAuWNfP3869l9y8vMI1kOcxqsxjeG6YfgKUyu6PEYlj1R7d1
619.445 +/+UwVs9RGm3V7AwV4G1Qpnd+jaMLpgPVMP12sHPnslBE4SQe9bAZ+X5i2/5uesHv
619.446 +bF7OBMqsYW8+Kgsy1Ac0pBx/8yoFYdD3KYFnIP20kV2Xxy4PtQQ6tHJ33dGslTNU
619.447 +qrcJsyUyYj6wORlb7huuP5Ua8f28Xs/KvnNJG0094kC1WHi3Raf4AoD/rvraVtCQ
619.448 +5jrK9se8D6su+S3SEW0YndxivbNx3xJu2O72e7lS6yb5ht3U7xNSSWTffIlW1okI
619.449 +zjscK0iv9S+x452mLIFUgkmriVJLFfjTMRCbhS1J6q9FXLDdre/2O18FO2TvwRIE
619.450 +6Bwt2utfOAGccRHLsdgcXkv+ngCTCkuCnmh2XZWqmvA=
619.451 +-----END RSA PRIVATE KEY-----
619.452 +
619.453 +d. end entity certificate and key
619.454 + (SHA1withRSA 512, subca_cert_sha1_512_1024.pem signed)
619.455 +-----BEGIN CERTIFICATE-----
619.456 +MIIBsjCCAVygAwIBAgIBBTANBgkqhkiG9w0BAQUFADAxMQswCQYDVQQGEwJVUzEQ
619.457 +MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx
619.458 +NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt
619.459 +cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTBcMA0GCSqGSIb3
619.460 +DQEBAQUAA0sAMEgCQQCpfQzhld7w2JhW/aRaLkmrLrc/QAsQE+J4DXioXaajsWPo
619.461 +uMmYmuiQolb6OIY/LcivSubKM3G5PkAWoovUPIWLAgMBAAGjTzBNMAsGA1UdDwQE
619.462 +AwID6DAdBgNVHQ4EFgQUFWuXLkf4Ji57H9ISycgWi982TUIwHwYDVR0jBBgwFoAU
619.463 +N0CHiTYPtjyvpP2a6y6mhsZ6U40wDQYJKoZIhvcNAQEFBQADQQBG4grtrVEHick0
619.464 +z/6Lcl/MGyHT0c8KTXE0AMVXG1NRjAicAmYno/yDaJ9OmfymObKZKV9fF7yCW/N/
619.465 +TMU6m7N0
619.466 +-----END CERTIFICATE-----
619.467 +
619.468 +-----BEGIN RSA PRIVATE KEY-----
619.469 +Proc-Type: 4,ENCRYPTED
619.470 +DEK-Info: DES-EDE3-CBC,153918982D82A26E
619.471 +
619.472 +5w5MNd16M1draSfIFAuWNfP3869l9y8vMI1kOcxqsxjeG6YfgKUyu6PEYlj1R7d1
619.473 +/+UwVs9RGm3V7AwV4G1Qpnd+jaMLpgPVMP12sHPnslBE4SQe9bAZ+X5i2/5uesHv
619.474 +bF7OBMqsYW8+Kgsy1Ac0pBx/8yoFYdD3KYFnIP20kV2Xxy4PtQQ6tHJ33dGslTNU
619.475 +qrcJsyUyYj6wORlb7huuP5Ua8f28Xs/KvnNJG0094kC1WHi3Raf4AoD/rvraVtCQ
619.476 +5jrK9se8D6su+S3SEW0YndxivbNx3xJu2O72e7lS6yb5ht3U7xNSSWTffIlW1okI
619.477 +zjscK0iv9S+x452mLIFUgkmriVJLFfjTMRCbhS1J6q9FXLDdre/2O18FO2TvwRIE
619.478 +6Bwt2utfOAGccRHLsdgcXkv+ngCTCkuCnmh2XZWqmvA=
619.479 +-----END RSA PRIVATE KEY-----
619.480 +
619.481 +e. end entity certificate and key
619.482 + (MD2withRSA 1024, subca_cert_sha1_1024_1024.pem signed)
619.483 +-----BEGIN CERTIFICATE-----
619.484 +MIICNzCCAaCgAwIBAgIBBjANBgkqhkiG9w0BAQIFADAxMQswCQYDVQQGEwJVUzEQ
619.485 +MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx
619.486 +NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt
619.487 +cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG
619.488 +9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt
619.489 +vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v
619.490 +z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6
619.491 +c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07
619.492 +OorBleV92TAfBgNVHSMEGDAWgBTfWD9mRTppcUAlUqGuu/R5t8CB5jANBgkqhkiG
619.493 +9w0BAQIFAAOBgQBxKsFf8NNQcXjDoKJJSG4Rk6ikcrhiGYuUI32+XHvs6hnav1Zc
619.494 +aJUpy7J4gMj/MnysMh/4AF9+m6zEEjuisXKUbYZhgtJxz+ukGSo163mJ8QJiAlRb
619.495 +Iwsy81r08mlSCR6jx2YhDAUxJIPC92R5Vb4CEutB7tWTwwz7vIHq330erA==
619.496 +-----END CERTIFICATE-----
619.497 +
619.498 +-----BEGIN RSA PRIVATE KEY-----
619.499 +Proc-Type: 4,ENCRYPTED
619.500 +DEK-Info: DES-EDE3-CBC,1FE5A37B770AF83D
619.501 +
619.502 +042bWtt4q0cB8pRuPUlMVncTP/WAz+mmPw3jXI3LFOBZeK6zFEDpI5M9c2JO+rqp
619.503 +Za5UkYuIg69V7LngriqRynkRGGQp3xASMLr5NVbKHTE/Ol/iIuxKaCkumZmGXB/z
619.504 +8bxQF5XN4tbKT4s3sWWmmKMicg6MHvySi3QVRG11PHRu/q7CEFPzJKRQ3fpaNcKD
619.505 +NTBI5F6GP9ENa/eog4WGENjXS0v4Wa3IfaOhjKXrSxjLUqLH0C8g5WWg5IrXXtuI
619.506 +pgyJ2kkE3Y/ChU7p7R42we6tBZqF5SiL5kFDn86DmHgCslTiZkIoE5i644sp03Sd
619.507 +XkHyHu0VIeYp3nDwRA7S98837W4F6i1BnXA5f3EaE3rNGjsxK8zL2pvdCcDYbese
619.508 +ETfba16HMzLXe1b4RSI3gwhlQ2MNKBwvskkQESf/Ew1DskBY0MCYFxo6hIp6LqMo
619.509 +HAl5kvCwvuYL2jBdQhkKxU+Leu5Ei8Ie9XYNVy4yUeUAMnSUkVaEs/I8z+Mk8oYq
619.510 +4QWqOc66XLcI13coDoxmv54kye3RjqdmZI8mg/3LCFotwceDuXyD43/vVhoTPEnp
619.511 +CqXafV2pw4y95skMHmktI2qvSahaM4P6GGXl8HqmP3b+8V5mxMhNtVnuUha2kouw
619.512 +DLNFUTg1cCLahM5SRolyA/XTGh7JOkJMYWPeJwN7l3K+lBtHHfj6DHtKEjUcyZFd
619.513 ++Z55pDoAERumB6+BCnt6X2/0kEDV219RmsgxkGTWdFs+M7Y6EYYRtlinH4nqL6UD
619.514 +eHWitYIatAHOvdHeNrbXN9L5P3tsUB4HzFa46WWtKqRtbCVTuPVZdw==
619.515 +-----END RSA PRIVATE KEY-----
619.516 +
619.517 +f. end entity certificate and key
619.518 + (MD2withRSA 1024, subca_cert_sha1_512_1024.pem signed)
619.519 +-----BEGIN CERTIFICATE-----
619.520 +MIIB9jCCAaCgAwIBAgIBBzANBgkqhkiG9w0BAQIFADAxMQswCQYDVQQGEwJVUzEQ
619.521 +MA4GA1UEChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMTAeFw0wOTA4MDYwMTEx
619.522 +NTFaFw0yOTA0MjMwMTExNTFaMEExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFt
619.523 +cGxlMRAwDgYDVQQLEwdDbGFzcy0xMQ4wDAYDVQQDEwVBbGljZTCBnzANBgkqhkiG
619.524 +9w0BAQEFAAOBjQAwgYkCgYEAy6/2g3rxQzJEvTyOnBcEnZthmAD0AnP6LG8b35jt
619.525 +vh71LHbF1FhkOT42Rfg20aBfWTMRf+FeOJBXpD4gCNjQA40vy8FaQxgYNAf7ho5v
619.526 +z6yAEE6SG7YviE+XGcvpQo47w8c6QSQjpBzdw7JxwbVlzUT7pF8x3RnXlGhWnWv6
619.527 +c1ECAwEAAaNPME0wCwYDVR0PBAQDAgPoMB0GA1UdDgQWBBSaXXERsow2Wm/6uT07
619.528 +OorBleV92TAfBgNVHSMEGDAWgBQ3QIeJNg+2PK+k/ZrrLqaGxnpTjTANBgkqhkiG
619.529 +9w0BAQIFAANBAIX63Ypi9P71RnC/pcMbhD+wekRFsTzU593X3MC7tyBJtEXwvAZG
619.530 +iMxXF5A+ohlr7/CrkV7ZTL8PLxnJdY5Y8rQ=
619.531 +-----END CERTIFICATE-----
619.532 +
619.533 +-----BEGIN RSA PRIVATE KEY-----
619.534 +Proc-Type: 4,ENCRYPTED
619.535 +DEK-Info: DES-EDE3-CBC,1FE5A37B770AF83D
619.536 +
619.537 +042bWtt4q0cB8pRuPUlMVncTP/WAz+mmPw3jXI3LFOBZeK6zFEDpI5M9c2JO+rqp
619.538 +Za5UkYuIg69V7LngriqRynkRGGQp3xASMLr5NVbKHTE/Ol/iIuxKaCkumZmGXB/z
619.539 +8bxQF5XN4tbKT4s3sWWmmKMicg6MHvySi3QVRG11PHRu/q7CEFPzJKRQ3fpaNcKD
619.540 +NTBI5F6GP9ENa/eog4WGENjXS0v4Wa3IfaOhjKXrSxjLUqLH0C8g5WWg5IrXXtuI
619.541 +pgyJ2kkE3Y/ChU7p7R42we6tBZqF5SiL5kFDn86DmHgCslTiZkIoE5i644sp03Sd
619.542 +XkHyHu0VIeYp3nDwRA7S98837W4F6i1BnXA5f3EaE3rNGjsxK8zL2pvdCcDYbese
619.543 +ETfba16HMzLXe1b4RSI3gwhlQ2MNKBwvskkQESf/Ew1DskBY0MCYFxo6hIp6LqMo
619.544 +HAl5kvCwvuYL2jBdQhkKxU+Leu5Ei8Ie9XYNVy4yUeUAMnSUkVaEs/I8z+Mk8oYq
619.545 +4QWqOc66XLcI13coDoxmv54kye3RjqdmZI8mg/3LCFotwceDuXyD43/vVhoTPEnp
619.546 +CqXafV2pw4y95skMHmktI2qvSahaM4P6GGXl8HqmP3b+8V5mxMhNtVnuUha2kouw
619.547 +DLNFUTg1cCLahM5SRolyA/XTGh7JOkJMYWPeJwN7l3K+lBtHHfj6DHtKEjUcyZFd
619.548 ++Z55pDoAERumB6+BCnt6X2/0kEDV219RmsgxkGTWdFs+M7Y6EYYRtlinH4nqL6UD
619.549 +eHWitYIatAHOvdHeNrbXN9L5P3tsUB4HzFa46WWtKqRtbCVTuPVZdw==
619.550 +-----END RSA PRIVATE KEY-----
619.551 +
619.552 +h. root CRL issuer
619.553 +-----BEGIN CERTIFICATE-----
619.554 +MIICKzCCAZSgAwIBAgIBCjANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ
619.555 +MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDgxNjMwNTdaFw0yOTA0MjUxNjMwNTda
619.556 +MB8xCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMIGfMA0GCSqGSIb3DQEB
619.557 +AQUAA4GNADCBiQKBgQCy6RoQ6nMdeGJ6ijfjqDu3tDmeGLgnvfBcUKvcsvz9Ji3m
619.558 +oGnTzECo1oLV+A4/TJxOlak+ZiQ5KVyvfMcXLJeT6dRpXQZ+uc6TT3SkBq94VFzX
619.559 +qkk08z42JNdk1s5uyW8nRfg7+xntajQVrysoPYNDhu21cPnjDkRiBsIdS7+75QID
619.560 +AQABo3cwdTAdBgNVHQ4EFgQUGcJU6xWo66kI1QBvlfTQKxxmx9IwRwYDVR0jBEAw
619.561 +PoAU59AvsZmWPwU2m+FvYAad3Rmu1oKhI6QhMB8xCzAJBgNVBAYTAlVTMRAwDgYD
619.562 +VQQKEwdFeGFtcGxlggEAMAsGA1UdDwQEAwIBAjANBgkqhkiG9w0BAQQFAAOBgQBx
619.563 +uKL59VInPdCi+8JL4B+S5YjlPL4ZOBHTjS0JlNxtjbGZdfs+3E9PUAdqhMJO4vq7
619.564 +XD+hGtgZtwSqGaSUYAtpLdoCr7vvPkcrxYTG2Ak+UiTbZhmJeSswKgFaCmjjdMCy
619.565 +y64UP2DQfn6Zi0wCfeao0m9s3zRLuJpgaQGiSHTQKA==
619.566 +-----END CERTIFICATE-----
619.567 +
619.568 +-----BEGIN RSA PRIVATE KEY-----
619.569 +Proc-Type: 4,ENCRYPTED
619.570 +DEK-Info: DES-EDE3-CBC,41E4237825CE0148
619.571 +
619.572 +9nbfd7dsaS+fkFYrU1+wTcevjdRLF/j9DUVQh/2bsFlVEYgeL8A+XpvpbXHYBd7H
619.573 +oBreofDNseibHe4EgISGPK8RymjYutQqPpbHwXd25jlUuUapvvuCj8V6qnhgpqEo
619.574 +zXL1Nd2c6KZgdySosyWy8JfIBZJ3kwiSkXVwzs8R4bAGrg1VS80GuszvCv8Fzjoc
619.575 +LuesX6fViE9yFzLsyOvn/W12DKhTXwiXTQYLUupM8zI9Kpozbea52ZIPMJ9HEiaY
619.576 +JgwNj05w33VxTe/tq3R9vS2Ee6aM4odi6CQEheLsUAnyE0BTsITKzwwTI25WTv25
619.577 +W+gwSF3V49a34MojTdlORq5iH0b3rYl7OMdk+99elJSkyQIbVwwOCFrKuSXYXvV7
619.578 +s9iMPFUbi+bZ3oP6zM5kVUcH6KyVeYfkuLf2+k1vPlav8/W5v+WfnvUNOBx76Ira
619.579 +BzVPYmm2V+YFiFL1hugm5Wv+yyx8QcfgXbvhNHoIEj7hh6Ac48FhtqEcBHjuT/gy
619.580 +7atJJUdOH6hhmD34hkHGnhcDE15ZOczxTLRC9450h5HKsZ0FILRlCBZLmiedycs2
619.581 +zqhUpR4jzDG9jKrlDU4ErfMgPLjveZc3/VT3bc+TYfuC8szCaQ5XX1JVcabZ+HQw
619.582 +pwmA1ONZDVsFzwbJy9+5bgXX+wLD5kaez8EHNDS5PgqgL0UdrWjdRi6e1RwlTDEw
619.583 +g/d7TZm/iQeL1iUIfkPA1f0ByYIiyd3XQqiQ/Mf1C16lQkhTHDwofFJdL8otT2Ha
619.584 +dk6fa7lBOnrpbRKUdpJpYfyqHg80BYNPu6BacVXlYqtJtkFK04qHbA==
619.585 +-----END RSA PRIVATE KEY-----
619.586 +
619.587 +i. CRL issued by root CRL issuer
619.588 +-----BEGIN X509 CRL-----
619.589 +MIH2MGECAQEwDQYJKoZIhvcNAQEFBQAwHzELMAkGA1UEBhMCVVMxEDAOBgNVBAoT
619.590 +B0V4YW1wbGUXDTA5MDgwODE2MzU1MFoXDTI4MTAwNzE2MzU1MFqgDjAMMAoGA1Ud
619.591 +FAQDAgEAMA0GCSqGSIb3DQEBBQUAA4GBAJCd7e25MruuWJP/KmenGC6CR22pQuG+
619.592 +XhRaAtpHkNRls8+TfBxm2PtRrXCAcDb68kNLdwvlAlCUwmL6HOx4VB3r+8QRUlDa
619.593 +T48wVp1ojGU2b2XbPtXiYZBXW6hBsFHGDJM/IAGJPE2PbVYGlBc23A9V9WyPyThi
619.594 +9XXG1iOTIJ6u
619.595 +-----END X509 CRL-----
619.596 +
619.597 +j. subca CRL issuer
619.598 +-----BEGIN CERTIFICATE-----
619.599 +MIICPTCCAaagAwIBAgIBCzANBgkqhkiG9w0BAQQFADAfMQswCQYDVQQGEwJVUzEQ
619.600 +MA4GA1UEChMHRXhhbXBsZTAeFw0wOTA4MDgxNjMwNThaFw0yOTA0MjUxNjMwNTha
619.601 +MDExCzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlMRAwDgYDVQQLEwdDbGFz
619.602 +cy0xMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8KICP0bdOZVlR9gZu7TgD
619.603 +znXgSMER1IQtompgr1mWeZjX4LmRck3/ogHoxwC4RbNPKI3KIihcVdFHw2jgvE0M
619.604 +mpf2lI50tmhnLitM8P0/q8xUU/KncipADo4hkM5TbpjPeGUBTGLKzGrq7yyT9Uli
619.605 +Z74rrp1mS59TxcEI2YQMIQIDAQABo3cwdTAdBgNVHQ4EFgQUDGgpD4L8V3aBJPLx
619.606 +C7diZ0M0wWMwRwYDVR0jBEAwPoAU59AvsZmWPwU2m+FvYAad3Rmu1oKhI6QhMB8x
619.607 +CzAJBgNVBAYTAlVTMRAwDgYDVQQKEwdFeGFtcGxlggEAMAsGA1UdDwQEAwIBAjAN
619.608 +BgkqhkiG9w0BAQQFAAOBgQCcXqRge5UuW0duf/XnUWP4hrm4Q9EHJaiHZDYxI+WW
619.609 +Ca3OXdsrpgGi+RSgeMtQzlZ7YAwyYVV91U4BnX6s/97Vp5xbR3wr8Qbx67inM8Lp
619.610 +Tuo+e0nyTxwlwi9cSyy5MfJ8jfzaD+n8akhV+sx0Mmiv77YlrShP24lod55gJHKC
619.611 +vQ==
619.612 +-----END CERTIFICATE-----
619.613 +
619.614 +-----BEGIN RSA PRIVATE KEY-----
619.615 +Proc-Type: 4,ENCRYPTED
619.616 +DEK-Info: DES-EDE3-CBC,16EC4E2C0855BD5C
619.617 +
619.618 +dJHcUsnACMhfESAalWrWrfARnUgGhpp3vupjePUiBJ86YmKaNNr6GAwDukg3EJvs
619.619 +tboO1QQziLSf9pP7gw82Vp5YctEkk7vJVvCcq3QkZAsjNUHf3m3ne2qg8HngufzY
619.620 +IS/C3EtKuMr3oqa7P8wvMcsBs1G1ga/YqCWoKzowXhybaYPe20fwUNRtgqgdS5Gy
619.621 +bAzQB9R+Ua2tCaXb3CBYnrczsYFPhjuULr4qbWgHVBWhnkS3OIz71WqcCoXmvD3s
619.622 +bsjoZRCJUM6Zavyzs0kVGZogiPdr+KUyzjNNsnxle5cEET6nqkYR16UT/Fvemz9Q
619.623 +szh/y0gCi1nZb6cw5e9BJyF1GlobzxWyMwwY9L4vZNaBNaVRun+6dRWy0svaPuEy
619.624 +fV/9Y0/la9scyA5yNHz8xud3Njhj2ghyG5Nqbs3N/pPXRVdh7WNFBnc+L/SIBhhB
619.625 +/Ha9+OZdqyuMf3G+I1+WVADQr8xQP8/yLEvybZYtssjnuCmQSLPDDQFnp2Z3spax
619.626 ++AT+T4dRimMjf0mZK/NlRJU9PWqMHzsJGBY1A903oAiiHiRFD10z8vyPBigSDF2W
619.627 +ct6a8WI1prKho6HbMqeIlSPk+HkdCGZedNNbvRlKl4Y56IsHGAhb3wvQ+94049P9
619.628 +wu5thK69jNb7ie3YEefAZTb5kD0h+oB8BILOJ5B29C04JdDe6P6hjGKD7x3nRhHM
619.629 +nyCUMB/fhYpoXdDhz8CeJ77hFt2zFZRstlDctQsDqLkC0AdvlOFsEFqGM4AkBGcV
619.630 +f6Y+ykNQB3vEWPZsWqVXHB2vQvk00R55tgu+R5JJ45NLG2TqyOp/4A==
619.631 +-----END RSA PRIVATE KEY-----
619.632 +
619.633 +k. CRL issued by subca CRL issuer
619.634 +-----BEGIN X509 CRL-----
619.635 +MIIBLTCBlwIBATANBgkqhkiG9w0BAQIFADAxMQswCQYDVQQGEwJVUzEQMA4GA1UE
619.636 +ChMHRXhhbXBsZTEQMA4GA1UECxMHQ2xhc3MtMRcNMDkwODA4MTYzNTUxWhcNMjgx
619.637 +MDA3MTYzNTUxWjAiMCACAQIXDTA5MDgwODE2MzU1MFowDDAKBgNVHRUEAwoBBKAO
619.638 +MAwwCgYDVR0UBAMCAQAwDQYJKoZIhvcNAQECBQADgYEAbIs7ws4/M24NYrIO0XY6
619.639 +UVxni0ZoQa+1R7NwU6unr4jFEVD+W/b+JEMfm0RUmpSa7HrUYsw+NycD3m5CD6VJ
619.640 +U4iuGGeJvHdrYJiPIYkEiFQnhAGOj8oS/nWtPvDKbuBMZI9atKkypby9At8h9URq
619.641 +1g/KSIM3rd1PYADdcPsok4I=
619.642 +-----END X509 CRL-----
619.643 +
620.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
620.2 +++ b/test/sun/security/provider/certpath/DisabledAlgorithms/generate.sh Wed Nov 25 11:08:25 2009 -0800
620.3 @@ -0,0 +1,255 @@
620.4 +#
620.5 +# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
620.6 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
620.7 +#
620.8 +# This code is free software; you can redistribute it and/or modify it
620.9 +# under the terms of the GNU General Public License version 2 only, as
620.10 +# published by the Free Software Foundation. Sun designates this
620.11 +# particular file as subject to the "Classpath" exception as provided
620.12 +# by Sun in the LICENSE file that accompanied this code.
620.13 +#
620.14 +# This code is distributed in the hope that it will be useful, but WITHOUT
620.15 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
620.16 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
620.17 +# version 2 for more details (a copy is included in the LICENSE file that
620.18 +# accompanied this code).
620.19 +#
620.20 +# You should have received a copy of the GNU General Public License version
620.21 +# 2 along with this work; if not, write to the Free Software Foundation,
620.22 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
620.23 +#
620.24 +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
620.25 +# CA 95054 USA or visit www.sun.com if you need additional information or
620.26 +# have any questions.
620.27 +#
620.28 +
620.29 +#!/bin/ksh
620.30 +#
620.31 +# needs ksh to run the script.
620.32 +set -e
620.33 +
620.34 +OPENSSL=openssl
620.35 +
620.36 +# generate a self-signed root certificate
620.37 +if [ ! -f root/finished ]; then
620.38 + if [ ! -d root ]; then
620.39 + mkdir root
620.40 + fi
620.41 +
620.42 + # SHA1withRSA 1024
620.43 + ${OPENSSL} req -x509 -newkey rsa:1024 -keyout root/root_key_1024.pem \
620.44 + -out root/root_cert_sha1_1024.pem -subj "/C=US/O=Example" \
620.45 + -config openssl.cnf -reqexts cert_issuer -days 7650 -sha1 \
620.46 + -passin pass:passphrase -passout pass:passphrase
620.47 +
620.48 + # SHA1withRSA 512
620.49 + ${OPENSSL} req -x509 -newkey rsa:512 -keyout root/root_key_512.pem \
620.50 + -out root/root_cert_sha1_512.pem -subj "/C=US/O=Example" \
620.51 + -config openssl.cnf -reqexts cert_issuer -days 7650 -sha1 \
620.52 + -passin pass:passphrase -passout pass:passphrase
620.53 +
620.54 + # MD2withRSA 2048
620.55 + ${OPENSSL} req -x509 -newkey rsa:2048 -keyout root/root_key_2048.pem \
620.56 + -out root/root_cert_md2_2048.pem -subj "/C=US/O=Example" \
620.57 + -config openssl.cnf -reqexts cert_issuer -days 7650 -md2 \
620.58 + -passin pass:passphrase -passout pass:passphrase
620.59 +
620.60 + openssl req -newkey rsa:1024 -keyout root/root_crlissuer_key.pem \
620.61 + -out root/root_crlissuer_req.pem -subj "/C=US/O=Example" -days 7650 \
620.62 + -passin pass:passphrase -passout pass:passphrase
620.63 +
620.64 + openssl x509 -req -in root/root_crlissuer_req.pem -extfile openssl.cnf \
620.65 + -extensions crl_issuer -CA root/root_cert_sha1_1024.pem \
620.66 + -CAkey root/root_key_1024.pem -out root/root_crlissuer_cert.pem \
620.67 + -CAcreateserial -CAserial root/root_cert.srl -days 7200 \
620.68 + -passin pass:passphrase
620.69 +
620.70 + touch root/finished
620.71 +fi
620.72 +
620.73 +
620.74 +# generate subca cert issuer
620.75 +if [ ! -f subca/finished ]; then
620.76 + if [ ! -d subca ]; then
620.77 + mkdir subca
620.78 + fi
620.79 +
620.80 + # RSA 1024
620.81 + ${OPENSSL} req -newkey rsa:1024 -keyout subca/subca_key_1024.pem \
620.82 + -out subca/subca_req_1024.pem -subj "/C=US/O=Example/OU=Class-1" \
620.83 + -days 7650 -passin pass:passphrase -passout pass:passphrase
620.84 +
620.85 + # RSA 512
620.86 + ${OPENSSL} req -newkey rsa:512 -keyout subca/subca_key_512.pem \
620.87 + -out subca/subca_req_512.pem -subj "/C=US/O=Example/OU=Class-1" \
620.88 + -days 7650 -passin pass:passphrase -passout pass:passphrase
620.89 +
620.90 + # SHA1withRSA 1024 signed with RSA 1024
620.91 + ${OPENSSL} x509 -req -in subca/subca_req_1024.pem -extfile openssl.cnf \
620.92 + -extensions cert_issuer -CA root/root_cert_sha1_1024.pem \
620.93 + -CAkey root/root_key_1024.pem -out subca/subca_cert_sha1_1024_1024.pem \
620.94 + -CAcreateserial -sha1 \
620.95 + -CAserial root/root_cert.srl -days 7200 -passin pass:passphrase
620.96 +
620.97 + # SHA1withRSA 1024 signed with RSA 512
620.98 + ${OPENSSL} x509 -req -in subca/subca_req_1024.pem -extfile openssl.cnf \
620.99 + -extensions cert_issuer -CA root/root_cert_sha1_512.pem \
620.100 + -CAkey root/root_key_512.pem -out subca/subca_cert_sha1_1024_512.pem \
620.101 + -CAcreateserial -sha1 \
620.102 + -CAserial root/root_cert.srl -days 7200 -passin pass:passphrase
620.103 +
620.104 + # SHA1withRSA 512 signed with RSA 1024
620.105 + ${OPENSSL} x509 -req -in subca/subca_req_512.pem -extfile openssl.cnf \
620.106 + -extensions cert_issuer -CA root/root_cert_sha1_1024.pem \
620.107 + -CAkey root/root_key_1024.pem -out subca/subca_cert_sha1_512_1024.pem \
620.108 + -CAcreateserial -sha1 \
620.109 + -CAserial root/root_cert.srl -days 7200 -passin pass:passphrase
620.110 +
620.111 + # SHA1withRSA 512 signed with RSA 512
620.112 + ${OPENSSL} x509 -req -in subca/subca_req_512.pem -extfile openssl.cnf \
620.113 + -extensions cert_issuer -CA root/root_cert_sha1_512.pem \
620.114 + -CAkey root/root_key_512.pem -out subca/subca_cert_sha1_512_512.pem \
620.115 + -CAcreateserial -sha1 \
620.116 + -CAserial root/root_cert.srl -days 7200 -passin pass:passphrase
620.117 +
620.118 + # MD2withRSA 1024 signed with RSA 1024
620.119 + ${OPENSSL} x509 -req -in subca/subca_req_1024.pem -extfile openssl.cnf \
620.120 + -extensions cert_issuer -CA root/root_cert_sha1_1024.pem \
620.121 + -CAkey root/root_key_1024.pem -out subca/subca_cert_md2_1024_1024.pem \
620.122 + -CAcreateserial -md2 \
620.123 + -CAserial root/root_cert.srl -days 7200 -passin pass:passphrase
620.124 +
620.125 + # MD2withRSA 1024 signed with RSA 512
620.126 + ${OPENSSL} x509 -req -in subca/subca_req_1024.pem -extfile openssl.cnf \
620.127 + -extensions cert_issuer -CA root/root_cert_sha1_512.pem \
620.128 + -CAkey root/root_key_512.pem -out subca/subca_cert_md2_1024_512.pem \
620.129 + -CAcreateserial -md2 \
620.130 + -CAserial root/root_cert.srl -days 7200 -passin pass:passphrase
620.131 +
620.132 + openssl req -newkey rsa:1024 -keyout subca/subca_crlissuer_key.pem \
620.133 + -out subca/subca_crlissuer_req.pem -subj "/C=US/O=Example/OU=Class-1" \
620.134 + -days 7650 -passin pass:passphrase -passout pass:passphrase
620.135 +
620.136 + openssl x509 -req -in subca/subca_crlissuer_req.pem -extfile openssl.cnf \
620.137 + -extensions crl_issuer -CA root/root_cert_sha1_1024.pem \
620.138 + -CAkey root/root_key_1024.pem -out subca/subca_crlissuer_cert.pem \
620.139 + -CAcreateserial -CAserial root/root_cert.srl -days 7200 \
620.140 + -passin pass:passphrase
620.141 +
620.142 + touch subca/finished
620.143 +fi
620.144 +
620.145 +
620.146 +# generate certifiacte for Alice
620.147 +if [ ! -f subca/alice/finished ]; then
620.148 + if [ ! -d subca/alice ]; then
620.149 + mkdir -p subca/alice
620.150 + fi
620.151 +
620.152 + # RSA 1024
620.153 + ${OPENSSL} req -newkey rsa:1024 -keyout subca/alice/alice_key_1024.pem \
620.154 + -out subca/alice/alice_req_1024.pem \
620.155 + -subj "/C=US/O=Example/OU=Class-1/CN=Alice" -days 7650 \
620.156 + -passin pass:passphrase -passout pass:passphrase
620.157 +
620.158 + # RSA 512
620.159 + ${OPENSSL} req -newkey rsa:512 -keyout subca/alice/alice_key_512.pem \
620.160 + -out subca/alice/alice_req_512.pem \
620.161 + -subj "/C=US/O=Example/OU=Class-1/CN=Alice" -days 7650 \
620.162 + -passin pass:passphrase -passout pass:passphrase
620.163 +
620.164 + # SHA1withRSA 1024 signed with RSA 1024
620.165 + ${OPENSSL} x509 -req -in subca/alice/alice_req_1024.pem \
620.166 + -extfile openssl.cnf -extensions ee_of_subca \
620.167 + -CA subca/subca_cert_sha1_1024_1024.pem \
620.168 + -CAkey subca/subca_key_1024.pem \
620.169 + -out subca/alice/alice_cert_sha1_1024_1024.pem -CAcreateserial -sha1 \
620.170 + -CAserial subca/subca_cert.srl -days 7200 -passin pass:passphrase
620.171 +
620.172 + # SHA1withRSA 1024 signed with RSA 512
620.173 + ${OPENSSL} x509 -req -in subca/alice/alice_req_1024.pem \
620.174 + -extfile openssl.cnf -extensions ee_of_subca \
620.175 + -CA subca/subca_cert_sha1_512_1024.pem \
620.176 + -CAkey subca/subca_key_512.pem \
620.177 + -out subca/alice/alice_cert_sha1_1024_512.pem -CAcreateserial -sha1 \
620.178 + -CAserial subca/subca_cert.srl -days 7200 -passin pass:passphrase
620.179 +
620.180 + # SHA1withRSA 512 signed with RSA 1024
620.181 + ${OPENSSL} x509 -req -in subca/alice/alice_req_512.pem \
620.182 + -extfile openssl.cnf -extensions ee_of_subca \
620.183 + -CA subca/subca_cert_sha1_1024_1024.pem \
620.184 + -CAkey subca/subca_key_1024.pem \
620.185 + -out subca/alice/alice_cert_sha1_512_1024.pem -CAcreateserial -sha1 \
620.186 + -CAserial subca/subca_cert.srl -days 7200 -passin pass:passphrase
620.187 +
620.188 + # SHA1withRSA 512 signed with RSA 512
620.189 + ${OPENSSL} x509 -req -in subca/alice/alice_req_512.pem \
620.190 + -extfile openssl.cnf -extensions ee_of_subca \
620.191 + -CA subca/subca_cert_sha1_512_1024.pem \
620.192 + -CAkey subca/subca_key_512.pem \
620.193 + -out subca/alice/alice_cert_sha1_512_512.pem -CAcreateserial -sha1 \
620.194 + -CAserial subca/subca_cert.srl -days 7200 -passin pass:passphrase
620.195 +
620.196 + # MD2withRSA 1024 signed with RSA 1024
620.197 + ${OPENSSL} x509 -req -in subca/alice/alice_req_1024.pem \
620.198 + -extfile openssl.cnf -extensions ee_of_subca \
620.199 + -CA subca/subca_cert_sha1_1024_1024.pem \
620.200 + -CAkey subca/subca_key_1024.pem \
620.201 + -out subca/alice/alice_cert_md2_1024_1024.pem -CAcreateserial -md2 \
620.202 + -CAserial subca/subca_cert.srl -days 7200 -passin pass:passphrase
620.203 +
620.204 + # MD2withRSA 1024 signed with RSA 512
620.205 + ${OPENSSL} x509 -req -in subca/alice/alice_req_1024.pem \
620.206 + -extfile openssl.cnf -extensions ee_of_subca \
620.207 + -CA subca/subca_cert_sha1_512_1024.pem \
620.208 + -CAkey subca/subca_key_512.pem \
620.209 + -out subca/alice/alice_cert_md2_1024_512.pem -CAcreateserial -md2 \
620.210 + -CAserial subca/subca_cert.srl -days 7200 -passin pass:passphrase
620.211 +
620.212 + touch subca/alice/finished
620.213 +fi
620.214 +
620.215 +if [ ! -f root/revoked ]; then
620.216 + if [ ! -d root ]; then
620.217 + mkdir root
620.218 + fi
620.219 +
620.220 + if [ ! -f root/index.txt ]; then
620.221 + touch root/index.txt
620.222 + echo 00 > root/crlnumber
620.223 + fi
620.224 +
620.225 + openssl ca -gencrl -config openssl.cnf -name ca_top -crldays 7000 -md sha1 \
620.226 + -crl_reason superseded -keyfile root/root_crlissuer_key.pem \
620.227 + -cert root/root_crlissuer_cert.pem -out root/top_crl.pem \
620.228 + -passin pass:passphrase
620.229 +
620.230 + touch root/revoked
620.231 +fi
620.232 +
620.233 +if [ ! -f subca/revoked ]; then
620.234 + if [ ! -d subca ]; then
620.235 + mkdir subca
620.236 + fi
620.237 +
620.238 + if [ ! -f subca/index.txt ]; then
620.239 + touch subca/index.txt
620.240 + echo 00 > subca/crlnumber
620.241 + fi
620.242 +
620.243 + # revoke alice's SHA1withRSA 1024 signed with RSA 1024
620.244 + openssl ca -revoke subca/alice/alice_cert_sha1_1024_1024.pem \
620.245 + -config openssl.cnf \
620.246 + -name ca_subca -crl_reason superseded \
620.247 + -keyfile subca/subca_crlissuer_key.pem \
620.248 + -cert subca/subca_crlissuer_cert.pem -passin pass:passphrase
620.249 +
620.250 + openssl ca -gencrl -config openssl.cnf \
620.251 + -name ca_subca -crldays 7000 -md md2 \
620.252 + -crl_reason superseded -keyfile subca/subca_crlissuer_key.pem \
620.253 + -cert subca/subca_crlissuer_cert.pem \
620.254 + -out subca/subca_crl.pem \
620.255 + -passin pass:passphrase
620.256 +
620.257 + touch subca/revoked
620.258 +fi
621.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
621.2 +++ b/test/sun/security/provider/certpath/DisabledAlgorithms/openssl.cnf Wed Nov 25 11:08:25 2009 -0800
621.3 @@ -0,0 +1,206 @@
621.4 +#
621.5 +# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
621.6 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
621.7 +#
621.8 +# This code is free software; you can redistribute it and/or modify it
621.9 +# under the terms of the GNU General Public License version 2 only, as
621.10 +# published by the Free Software Foundation. Sun designates this
621.11 +# particular file as subject to the "Classpath" exception as provided
621.12 +# by Sun in the LICENSE file that accompanied this code.
621.13 +#
621.14 +# This code is distributed in the hope that it will be useful, but WITHOUT
621.15 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
621.16 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
621.17 +# version 2 for more details (a copy is included in the LICENSE file that
621.18 +# accompanied this code).
621.19 +#
621.20 +# You should have received a copy of the GNU General Public License version
621.21 +# 2 along with this work; if not, write to the Free Software Foundation,
621.22 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
621.23 +#
621.24 +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
621.25 +# CA 95054 USA or visit www.sun.com if you need additional information or
621.26 +# have any questions.
621.27 +#
621.28 +
621.29 +#
621.30 +# OpenSSL configuration file.
621.31 +#
621.32 +
621.33 +HOME = .
621.34 +RANDFILE = $ENV::HOME/.rnd
621.35 +
621.36 +[ ca ]
621.37 +default_ca = CA_default
621.38 +
621.39 +[ CA_default ]
621.40 +dir = ./top
621.41 +certs = $dir/certs
621.42 +crl_dir = $dir/crl
621.43 +database = $dir/index.txt
621.44 +unique_subject = no
621.45 +new_certs_dir = $dir/newcerts
621.46 +certificate = $dir/cacert.pem
621.47 +serial = $dir/serial
621.48 +crlnumber = $dir/crlnumber
621.49 +crl = $dir/crl.pem
621.50 +private_key = $dir/private/cakey.pem
621.51 +RANDFILE = $dir/private/.rand
621.52 +x509_extensions = v3_ca
621.53 +
621.54 +name_opt = ca_default
621.55 +cert_opt = ca_default
621.56 +
621.57 +default_days = 7650
621.58 +default_crl_days = 30
621.59 +default_md = sha1
621.60 +preserve = no
621.61 +
621.62 +policy = policy_anything
621.63 +
621.64 +[ ca_top ]
621.65 +dir = ./root
621.66 +certs = $dir/certs
621.67 +crl_dir = $dir/crl
621.68 +database = $dir/index.txt
621.69 +unique_subject = no
621.70 +new_certs_dir = $dir/newcerts
621.71 +certificate = $dir/cacert.pem
621.72 +serial = $dir/serial
621.73 +crlnumber = $dir/crlnumber
621.74 +crl = $dir/crl.pem
621.75 +private_key = $dir/private/cakey.pem
621.76 +RANDFILE = $dir/private/.rand
621.77 +
621.78 +x509_extensions = v3_ca
621.79 +
621.80 +name_opt = ca_default
621.81 +cert_opt = ca_default
621.82 +
621.83 +default_days = 7650
621.84 +default_crl_days = 30
621.85 +default_md = sha1
621.86 +preserve = no
621.87 +
621.88 +policy = policy_anything
621.89 +
621.90 +[ ca_subca ]
621.91 +dir = ./subca
621.92 +certs = $dir/certs
621.93 +crl_dir = $dir/crl
621.94 +database = $dir/index.txt
621.95 +unique_subject = no
621.96 +new_certs_dir = $dir/newcerts
621.97 +
621.98 +certificate = $dir/cacert.pem
621.99 +serial = $dir/serial
621.100 +crlnumber = $dir/crlnumber
621.101 +crl = $dir/crl.pem
621.102 +private_key = $dir/private/cakey.pem
621.103 +RANDFILE = $dir/private/.rand
621.104 +
621.105 +x509_extensions = usr_cert
621.106 +
621.107 +name_opt = ca_default
621.108 +cert_opt = ca_default
621.109 +
621.110 +default_days = 7650
621.111 +default_crl_days = 30
621.112 +default_md = sha1
621.113 +preserve = no
621.114 +
621.115 +policy = policy_anything
621.116 +
621.117 +[ policy_match ]
621.118 +countryName = match
621.119 +stateOrProvinceName = match
621.120 +organizationName = match
621.121 +organizationalUnitName = optional
621.122 +commonName = supplied
621.123 +emailAddress = optional
621.124 +
621.125 +[ policy_anything ]
621.126 +countryName = optional
621.127 +stateOrProvinceName = optional
621.128 +localityName = optional
621.129 +organizationName = optional
621.130 +organizationalUnitName = optional
621.131 +commonName = supplied
621.132 +emailAddress = optional
621.133 +
621.134 +[ req ]
621.135 +default_bits = 1024
621.136 +default_keyfile = privkey.pem
621.137 +distinguished_name = req_distinguished_name
621.138 +attributes = req_attributes
621.139 +x509_extensions = v3_ca
621.140 +
621.141 +string_mask = nombstr
621.142 +
621.143 +[ req_distinguished_name ]
621.144 +countryName = Country Name (2 letter code)
621.145 +countryName_default = NO
621.146 +countryName_min = 2
621.147 +countryName_max = 2
621.148 +
621.149 +stateOrProvinceName = State or Province Name (full name)
621.150 +stateOrProvinceName_default = A-State
621.151 +
621.152 +localityName = Locality Name (eg, city)
621.153 +
621.154 +0.organizationName = Organization Name (eg, company)
621.155 +0.organizationName_default = Internet Widgits Pty Ltd
621.156 +
621.157 +organizationalUnitName = Organizational Unit Name (eg, section)
621.158 +
621.159 +commonName = Common Name (eg, YOUR name)
621.160 +commonName_max = 64
621.161 +
621.162 +emailAddress = Email Address
621.163 +emailAddress_max = 64
621.164 +
621.165 +[ req_attributes ]
621.166 +challengePassword = A challenge password
621.167 +challengePassword_min = 4
621.168 +challengePassword_max = 20
621.169 +unstructuredName = An optional company name
621.170 +
621.171 +
621.172 +[ usr_cert ]
621.173 +keyUsage = nonRepudiation, digitalSignature, keyEncipherment
621.174 +
621.175 +subjectKeyIdentifier = hash
621.176 +authorityKeyIdentifier = keyid,issuer
621.177 +
621.178 +[ v3_req ]
621.179 +basicConstraints = CA:FALSE
621.180 +keyUsage = nonRepudiation, digitalSignature, keyEncipherment
621.181 +subjectAltName = email:example@openjdk.net, RID:1.2.3.4:true
621.182 +
621.183 +[ v3_ca ]
621.184 +subjectKeyIdentifier = hash
621.185 +authorityKeyIdentifier = keyid:always,issuer:always
621.186 +basicConstraints = critical,CA:true
621.187 +keyUsage = keyCertSign
621.188 +
621.189 +[ cert_issuer ]
621.190 +subjectKeyIdentifier = hash
621.191 +authorityKeyIdentifier = keyid:always,issuer:always
621.192 +basicConstraints = critical,CA:true
621.193 +keyUsage = keyCertSign
621.194 +
621.195 +
621.196 +[ crl_issuer ]
621.197 +subjectKeyIdentifier = hash
621.198 +authorityKeyIdentifier = keyid:always,issuer:always
621.199 +keyUsage = cRLSign
621.200 +
621.201 +
621.202 +[ crl_ext ]
621.203 +authorityKeyIdentifier = keyid:always,issuer:always
621.204 +
621.205 +[ ee_of_subca ]
621.206 +keyUsage = nonRepudiation, digitalSignature, keyEncipherment, keyAgreement
621.207 +
621.208 +subjectKeyIdentifier = hash
621.209 +authorityKeyIdentifier = keyid,issuer
622.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
622.2 +++ b/test/sun/security/tools/jarsigner/ec.sh Wed Nov 25 11:08:25 2009 -0800
622.3 @@ -0,0 +1,73 @@
622.4 +#
622.5 +# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
622.6 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
622.7 +#
622.8 +# This code is free software; you can redistribute it and/or modify it
622.9 +# under the terms of the GNU General Public License version 2 only, as
622.10 +# published by the Free Software Foundation.
622.11 +#
622.12 +# This code is distributed in the hope that it will be useful, but WITHOUT
622.13 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
622.14 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
622.15 +# version 2 for more details (a copy is included in the LICENSE file that
622.16 +# accompanied this code).
622.17 +#
622.18 +# You should have received a copy of the GNU General Public License version
622.19 +# 2 along with this work; if not, write to the Free Software Foundation,
622.20 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
622.21 +#
622.22 +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
622.23 +# CA 95054 USA or visit www.sun.com if you need additional information or
622.24 +# have any questions.
622.25 +#
622.26 +
622.27 +# @test
622.28 +# @bug 6870812
622.29 +# @summary enhance security tools to use ECC algorithm
622.30 +#
622.31 +
622.32 +if [ "${TESTJAVA}" = "" ] ; then
622.33 + JAVAC_CMD=`which javac`
622.34 + TESTJAVA=`dirname $JAVAC_CMD`/..
622.35 +fi
622.36 +
622.37 +# set platform-dependent variables
622.38 +OS=`uname -s`
622.39 +case "$OS" in
622.40 + Windows_* )
622.41 + FS="\\"
622.42 + ;;
622.43 + * )
622.44 + FS="/"
622.45 + ;;
622.46 +esac
622.47 +
622.48 +KS=ec.jks
622.49 +JFILE=ec.jar
622.50 +
622.51 +KT="$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS"
622.52 +JAR=$TESTJAVA${FS}bin${FS}jar
622.53 +JARSIGNER=$TESTJAVA${FS}bin${FS}jarsigner
622.54 +
622.55 +rm $KS $JFILE
622.56 +echo A > A
622.57 +$JAR cvf $JFILE A
622.58 +
622.59 +$KT -alias a -dname CN=a -keyalg ec -genkey -validity 300 || exit 11
622.60 +$KT -alias b -dname CN=b -keyalg ec -genkey -validity 300 || exit 12
622.61 +$KT -alias c -dname CN=c -keyalg ec -genkey -validity 300 || exit 13
622.62 +$KT -alias x -dname CN=x -keyalg ec -genkey -validity 300 || exit 14
622.63 +
622.64 +$JARSIGNER -keystore $KS -storepass changeit $JFILE a -debug -strict || exit 21
622.65 +$JARSIGNER -keystore $KS -storepass changeit $JFILE b -debug -strict -sigalg SHA1withECDSA || exit 22
622.66 +$JARSIGNER -keystore $KS -storepass changeit $JFILE c -debug -strict -sigalg SHA512withECDSA || exit 23
622.67 +
622.68 +$JARSIGNER -keystore $KS -storepass changeit -verify $JFILE a -debug -strict || exit 31
622.69 +$JARSIGNER -keystore $KS -storepass changeit -verify $JFILE b -debug -strict || exit 32
622.70 +$JARSIGNER -keystore $KS -storepass changeit -verify $JFILE c -debug -strict || exit 33
622.71 +
622.72 +# Not signed by x, should exit with non-zero
622.73 +$JARSIGNER -keystore $KS -storepass changeit -verify $JFILE x -debug -strict && exit 34
622.74 +
622.75 +exit 0
622.76 +
623.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
623.2 +++ b/test/sun/security/tools/keytool/readjar.sh Wed Nov 25 11:08:25 2009 -0800
623.3 @@ -0,0 +1,56 @@
623.4 +#
623.5 +# Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
623.6 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
623.7 +#
623.8 +# This code is free software; you can redistribute it and/or modify it
623.9 +# under the terms of the GNU General Public License version 2 only, as
623.10 +# published by the Free Software Foundation.
623.11 +#
623.12 +# This code is distributed in the hope that it will be useful, but WITHOUT
623.13 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
623.14 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
623.15 +# version 2 for more details (a copy is included in the LICENSE file that
623.16 +# accompanied this code).
623.17 +#
623.18 +# You should have received a copy of the GNU General Public License version
623.19 +# 2 along with this work; if not, write to the Free Software Foundation,
623.20 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
623.21 +#
623.22 +# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
623.23 +# CA 95054 USA or visit www.sun.com if you need additional information or
623.24 +# have any questions.
623.25 +#
623.26 +
623.27 +# @test
623.28 +# @bug 6890872
623.29 +# @summary keytool -printcert to recognize signed jar files
623.30 +#
623.31 +
623.32 +if [ "${TESTJAVA}" = "" ] ; then
623.33 + JAVAC_CMD=`which javac`
623.34 + TESTJAVA=`dirname $JAVAC_CMD`/..
623.35 +fi
623.36 +
623.37 +# set platform-dependent variables
623.38 +OS=`uname -s`
623.39 +case "$OS" in
623.40 + Windows_* )
623.41 + FS="\\"
623.42 + ;;
623.43 + * )
623.44 + FS="/"
623.45 + ;;
623.46 +esac
623.47 +
623.48 +KS=readjar.jks
623.49 +rm $KS
623.50 +$TESTJAVA${FS}bin${FS}keytool -storepass changeit -keypass changeit -keystore $KS \
623.51 + -alias x -dname CN=X -genkeypair
623.52 +$TESTJAVA${FS}bin${FS}jar cvf readjar.jar $KS
623.53 +$TESTJAVA${FS}bin${FS}jarsigner -storepass changeit -keystore $KS readjar.jar x
623.54 +
623.55 +$TESTJAVA${FS}bin${FS}keytool -printcert -jarfile readjar.jar || exit 1
623.56 +$TESTJAVA${FS}bin${FS}keytool -printcert -jarfile readjar.jar -rfc || exit 1
623.57 +
623.58 +exit 0
623.59 +
624.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
624.2 +++ b/test/sun/security/util/DerValue/BadValue.java Wed Nov 25 11:08:25 2009 -0800
624.3 @@ -0,0 +1,119 @@
624.4 +/*
624.5 + * Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
624.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
624.7 + *
624.8 + * This code is free software; you can redistribute it and/or modify it
624.9 + * under the terms of the GNU General Public License version 2 only, as
624.10 + * published by the Free Software Foundation.
624.11 + *
624.12 + * This code is distributed in the hope that it will be useful, but WITHOUT
624.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
624.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
624.15 + * version 2 for more details (a copy is included in the LICENSE file that
624.16 + * accompanied this code).
624.17 + *
624.18 + * You should have received a copy of the GNU General Public License version
624.19 + * 2 along with this work; if not, write to the Free Software Foundation,
624.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
624.21 + *
624.22 + * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
624.23 + * CA 95054 USA or visit www.sun.com if you need additional information or
624.24 + * have any questions.
624.25 + */
624.26 +
624.27 +/*
624.28 + * @test
624.29 + * @bug 6864911
624.30 + * @summary ASN.1/DER input stream parser needs more work
624.31 + */
624.32 +
624.33 +import java.io.*;
624.34 +import sun.security.util.*;
624.35 +import sun.misc.IOUtils;
624.36 +
624.37 +public class BadValue {
624.38 +
624.39 + public static void main(String[] args) throws Exception {
624.40 +
624.41 + // Test IOUtils.readFully
624.42 +
624.43 + // We have 4 bytes
624.44 + InputStream in = new ByteArrayInputStream(new byte[10]);
624.45 + byte[] bs = IOUtils.readFully(in, 4, true);
624.46 + if (bs.length != 4 || in.available() != 6) {
624.47 + throw new Exception("First read error");
624.48 + }
624.49 + // But only 6 left
624.50 + bs = IOUtils.readFully(in, 10, false);
624.51 + if (bs.length != 6 || in.available() != 0) {
624.52 + throw new Exception("Second read error");
624.53 + }
624.54 + // MAX read as much as it can
624.55 + in = new ByteArrayInputStream(new byte[10]);
624.56 + bs = IOUtils.readFully(in, Integer.MAX_VALUE, true);
624.57 + if (bs.length != 10 || in.available() != 0) {
624.58 + throw new Exception("Second read error");
624.59 + }
624.60 + // MAX ignore readAll
624.61 + in = new ByteArrayInputStream(new byte[10]);
624.62 + bs = IOUtils.readFully(in, Integer.MAX_VALUE, false);
624.63 + if (bs.length != 10 || in.available() != 0) {
624.64 + throw new Exception("Second read error");
624.65 + }
624.66 + // 20>10, readAll means failure
624.67 + in = new ByteArrayInputStream(new byte[10]);
624.68 + try {
624.69 + bs = IOUtils.readFully(in, 20, true);
624.70 + throw new Exception("Third read error");
624.71 + } catch (EOFException e) {
624.72 + // OK
624.73 + }
624.74 + int bignum = 10 * 1024 * 1024;
624.75 + bs = IOUtils.readFully(new SuperSlowStream(bignum), -1, true);
624.76 + if (bs.length != bignum) {
624.77 + throw new Exception("Fourth read error");
624.78 + }
624.79 +
624.80 + // Test DerValue
624.81 + byte[] input = {0x04, (byte)0x84, 0x40, 0x00, 0x42, 0x46, 0x4b};
624.82 + try {
624.83 + new DerValue(new ByteArrayInputStream(input));
624.84 + } catch (IOException ioe) {
624.85 + // This is OK
624.86 + }
624.87 + }
624.88 +}
624.89 +
624.90 +/**
624.91 + * An InputStream contains a given number of bytes, but only returns one byte
624.92 + * per read.
624.93 + */
624.94 +class SuperSlowStream extends InputStream {
624.95 + private int p;
624.96 + /**
624.97 + * @param Initial capacity
624.98 + */
624.99 + public SuperSlowStream(int capacity) {
624.100 + p = capacity;
624.101 + }
624.102 + @Override
624.103 + public int read() throws IOException {
624.104 + if (p > 0) {
624.105 + p--;
624.106 + return 0;
624.107 + } else {
624.108 + return -1;
624.109 + }
624.110 + }
624.111 + @Override
624.112 + public int read(byte b[], int off, int len) throws IOException {
624.113 + if (len == 0) return 0;
624.114 + if (p > 0) {
624.115 + p--;
624.116 + b[off] = 0;
624.117 + return 1;
624.118 + } else {
624.119 + return -1;
624.120 + }
624.121 + }
624.122 +}
625.1 --- a/test/sun/util/logging/PlatformLoggerTest.java Mon Nov 23 10:04:47 2009 +0000
625.2 +++ b/test/sun/util/logging/PlatformLoggerTest.java Wed Nov 25 11:08:25 2009 -0800
625.3 @@ -28,7 +28,7 @@
625.4 * logging is enabled. Also validate some basic PlatformLogger
625.5 * operations.
625.6 *
625.7 - * @build PlatformLoggerTest
625.8 + * @compile -XDignore.symbol.file PlatformLoggerTest.java
625.9 * @run main PlatformLoggerTest
625.10 */
625.11