This commit is contained in:
J. Duke 2017-07-05 17:03:41 +02:00
commit 62c247e129
610 changed files with 24490 additions and 61830 deletions

View File

@ -50,3 +50,4 @@ e1b972ff53cd58f825791f8ed9b2deffd16e768c jdk7-b68
3ac6dcf7823205546fbbc3d4ea59f37358d0b0d4 jdk7-b73
2c88089b6e1c053597418099a14232182c387edc jdk7-b74
d1516b9f23954b29b8e76e6f4efc467c08c78133 jdk7-b75
c8b63075403d53a208104a8a6ea5072c1cb66aab jdk7-b76

View File

@ -50,3 +50,4 @@ a94714c550658fd6741793ef036cb9625dc2ab1a jdk7-b72
faf94d94786b621f8e13cbcc941ca69c6d967c3f jdk7-b73
f4b900403d6e4b0af51447bd13bbe23fe3a1dac7 jdk7-b74
d8dd291a362acb656026a9c0a9da48501505a1e7 jdk7-b75
9174bb32e934965288121f75394874eeb1fcb649 jdk7-b76

View File

@ -50,3 +50,4 @@ b3f3240135f0c10b9f2481c174b81b7fcf0daa60 jdk7-b71
f708138c9aca4b389872838fe6773872fce3609e jdk7-b73
eacb36e30327e7ae33baa068e82ddccbd91eaae2 jdk7-b74
8885b22565077236a927e824ef450742e434a230 jdk7-b75
8fb602395be0f7d5af4e7e93b7df2d960faf9d17 jdk7-b76

View File

@ -165,6 +165,9 @@ ifeq ($(SYSTEM_UNAME), Linux)
sparc*) \
echo sparc \
;; \
arm*) \
echo arm \
;; \
*) \
echo $(mach) \
;; \

View File

@ -160,10 +160,8 @@ CORE_PKGS = \
javax.lang.model.type \
javax.lang.model.util \
javax.management \
javax.management.event \
javax.management.loading \
javax.management.monitor \
javax.management.namespace \
javax.management.relation \
javax.management.openmbean \
javax.management.timer \

View File

@ -251,6 +251,7 @@ JAVA_JAVA_java = \
java/util/IdentityHashMap.java \
java/util/EnumMap.java \
java/util/Arrays.java \
java/util/DualPivotQuicksort.java \
java/util/TimSort.java \
java/util/ComparableTimSort.java \
java/util/ConcurrentModificationException.java \

View File

@ -83,7 +83,7 @@ endif
#
# Find platform specific native code
#
vpath %.c $(PLATFORM_SRC)/native/sun/net/dns $(PLATFORM_SRC)/native/sun/net/www/protocol/http $(PLATFORM_SRC)/native/sun/net/spi
vpath %.c $(PLATFORM_SRC)/native/sun/net/dns $(PLATFORM_SRC)/native/sun/net/www/protocol/http/ntlm $(PLATFORM_SRC)/native/sun/net/spi
#
# Include rules

View File

@ -1,5 +1,5 @@
#
# Copyright 2006-2008 Sun Microsystems, Inc. All Rights Reserved.
# Copyright 2006-2009 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
@ -34,8 +34,8 @@ solaris_i586_5.10,\
solaris_x64_5.10,\
linux_i586_2.6,\
linux_x64_2.6,\
windows_i586,\
windows_x64
windows_i586_5.0,\
windows_x64_5.2
# The different build flavors we want
jprt.build.flavors=product,fastdebug
@ -51,21 +51,37 @@ jprt.run.flavor.c2.option=-server
jprt.solaris_sparcv9.build.platform.match32=solaris_sparc_5.10
jprt.solaris_x64.build.platform.match32=solaris_i586_5.10
# Standard list of jprt test targets for this workspace
# Standard test target for everybody
jprt.test.targets=*-*-*-jvm98
jprt.regression.test.targets= \
*-product-*-java/lang, \
*-product-*-java/security, \
*-product-*-java/text, \
*-product-*-java/util
#jprt.regression.test.targets= \
# *-product-*-java/awt, \
# *-product-*-java/beans, \
# *-product-*-java/io, \
# *-product-*-java/net, \
# *-product-*-java/nio, \
# *-product-*-java/rmi, \
# Test targets in test/Makefile (some longer running tests only test c2)
jprt.make.rule.test.targets= \
*-product-*-jdk_beans1, \
*-product-*-jdk_beans2, \
*-product-*-jdk_beans3, \
*-product-*-jdk_io, \
*-product-*-jdk_lang, \
*-product-*-jdk_management1, \
*-product-*-jdk_management2, \
*-product-*-jdk_math, \
*-product-*-jdk_misc, \
*-product-*-jdk_net, \
*-product-*-jdk_nio1, \
*-product-*-jdk_nio2, \
*-product-*-jdk_nio3, \
*-product-*-jdk_security1, \
*-product-*-jdk_security2, \
*-product-*-jdk_security3, \
*-product-*-jdk_text, \
*-product-*-jdk_tools1, \
*-product-*-jdk_tools2, \
*-product-*-jdk_util
# Some of these are crashing Xvfb or windows manager, need dedicated DISPLAY per test batch
jprt2.make.rule.test.targets= \
*-product-*-jdk_awt, \
*-product-*-jdk_rmi, \
*-product-*-jdk_swing, \
# Directories needed to build
jprt.bundle.exclude.src.dirs=build

View File

@ -53,7 +53,6 @@ SUNWprivate_1.1 {
Java_sun_awt_image_GifImageDecoder_initIDs;
Java_sun_awt_image_GifImageDecoder_parseImage;
Java_sun_awt_image_ImageRepresentation_initIDs;
Java_sun_awt_image_ImageRepresentation_setBytePixels;
Java_sun_awt_image_ImageRepresentation_setDiffICM;
Java_sun_awt_image_ImageRepresentation_setICMpixels;
Java_sun_awt_image_ImagingLib_convolveBI;

View File

@ -55,7 +55,6 @@ SUNWprivate_1.1 {
Java_sun_awt_image_GifImageDecoder_parseImage;
Java_sun_awt_image_Image_initIDs;
Java_sun_awt_image_ImageRepresentation_initIDs;
Java_sun_awt_image_ImageRepresentation_setBytePixels;
Java_sun_awt_image_ImageRepresentation_setDiffICM;
Java_sun_awt_image_ImageRepresentation_setICMpixels;
Java_sun_awt_image_ImagingLib_convolveBI;

View File

@ -21,4 +21,4 @@
# CA 95054 USA or visit www.sun.com if you need additional information or
# have any questions.
#
tzdata2009l
tzdata2009r

View File

@ -102,15 +102,38 @@ Rule ChileAQ 2000 max - Mar Sun>=9 3:00u 0 -
# Davis, Vestfold Hills, -6835+07759, since 1957-01-13
# (except 1964-11 - 1969-02)
# Mawson, Holme Bay, -6736+06253, since 1954-02-13
# From Steffen Thorsen (2009-03-11):
# Three Australian stations in Antarctica have changed their time zone:
# Casey moved from UTC+8 to UTC+11
# Davis moved from UTC+7 to UTC+5
# Mawson moved from UTC+6 to UTC+5
# The changes occurred on 2009-10-18 at 02:00 (local times).
#
# Government source: (Australian Antarctic Division)
# <a href="http://www.aad.gov.au/default.asp?casid=37079">
# http://www.aad.gov.au/default.asp?casid=37079
# </a>
#
# We have more background information here:
# <a href="http://www.timeanddate.com/news/time/antarctica-new-times.html">
# http://www.timeanddate.com/news/time/antarctica-new-times.html
# </a>
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Antarctica/Casey 0 - zzz 1969
8:00 - WST # Western (Aus) Standard Time
8:00 - WST 2009 Oct 18 2:00
# Western (Aus) Standard Time
11:00 - CAST # Casey Time
Zone Antarctica/Davis 0 - zzz 1957 Jan 13
7:00 - DAVT 1964 Nov # Davis Time
0 - zzz 1969 Feb
7:00 - DAVT
7:00 - DAVT 2009 Oct 18 2:0
5:00 - DAVT
Zone Antarctica/Mawson 0 - zzz 1954 Feb 13
6:00 - MAWT # Mawson Time
6:00 - MAWT 2009 Oct 18 2:00
# Mawson Time
5:00 - MAWT
# References:
# <a href="http://www.antdiv.gov.au/aad/exop/sfo/casey/casey_aws.html">
# Casey Weather (1998-02-26)

View File

@ -21,7 +21,6 @@
# CA 95054 USA or visit www.sun.com if you need additional information or
# have any questions.
#
# <pre>
# This file is in the public domain, so clarified as of
# 2009-05-17 by Arthur David Olson.
@ -194,11 +193,30 @@ Zone Asia/Bahrain 3:22:20 - LMT 1920 # Al Manamah
#
# No DST end date has been announced yet.
# From Arthur David Olson (2009-07-11):
# Arbitrarily end DST at the end of 2009 so that a POSIX-sytle time zone string
# can appear in the Dhaka binary file and for the benefit of old glibc
# reimplementations of the time zone software that mishandle permanent DST.
# A change will be required once the end date is known.
# From Alexander Krivenyshev (2009-09-25):
# Bangladesh won't go back to Standard Time from October 1, 2009,
# instead it will continue DST measure till the cabinet makes a fresh decision.
#
# Following report by same newspaper-"The Daily Star Friday":
# "DST change awaits cabinet decision-Clock won't go back by 1-hr from Oct 1"
# <a href="http://www.thedailystar.net/newDesign/news-details.php?nid=107021">
# http://www.thedailystar.net/newDesign/news-details.php?nid=107021
# </a>
# or
# <a href="http://www.worldtimezone.com/dst_news/dst_news_bangladesh04.html">
# http://www.worldtimezone.com/dst_news/dst_news_bangladesh04.html
# </a>
# From Steffen Thorsen (2009-10-13):
# IANS (Indo-Asian News Service) now reports:
# Bangladesh has decided that the clock advanced by an hour to make
# maximum use of daylight hours as an energy saving measure would
# "continue for an indefinite period."
#
# One of many places where it is published:
# <a href="http://www.thaindian.com/newsportal/business/bangladesh-to-continue-indefinitely-with-advanced-time_100259987.html">
# http://www.thaindian.com/newsportal/business/bangladesh-to-continue-indefinitely-with-advanced-time_100259987.html
# </a>
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Dhaka 6:01:40 - LMT 1890
@ -208,8 +226,7 @@ Zone Asia/Dhaka 6:01:40 - LMT 1890
6:30 - BURT 1951 Sep 30
6:00 - DACT 1971 Mar 26 # Dacca Time
6:00 - BDT 2009 Jun 19 23:00 # Bangladesh Time
6:00 1:00 BDST 2010
6:00 - BDT
6:00 1:00 BDST
# Bhutan
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
@ -373,14 +390,84 @@ Zone Asia/Kashgar 5:03:56 - LMT 1928 # or Kashi or Kaxgar
5:00 - KAST 1980 May
8:00 PRC C%sT
# From Lee Yiu Chung (2009-10-24):
# I found there are some mistakes for the historial DST rule for Hong
# Kong. Accoring to the DST record from Hong Kong Observatory (actually,
# it is not [an] observatory, but the official meteorological agency of HK,
# and also serves as the official timing agency), there are some missing
# and incorrect rules. Although the exact switch over time is missing, I
# think 3:30 is correct. The official DST record for Hong Kong can be
# obtained from
# <a href="http://www.hko.gov.hk/gts/time/Summertime.htm">
# http://www.hko.gov.hk/gts/time/Summertime.htm
# </a>.
# From Arthur David Olson (2009-10-28):
# Here are the dates given at
# <a href="http://www.hko.gov.hk/gts/time/Summertime.htm">
# http://www.hko.gov.hk/gts/time/Summertime.htm
# </a>
# as of 2009-10-28:
# Year Period
# 1941 1 Apr to 30 Sep
# 1942 Whole year
# 1943 Whole year
# 1944 Whole year
# 1945 Whole year
# 1946 20 Apr to 1 Dec
# 1947 13 Apr to 30 Dec
# 1948 2 May to 31 Oct
# 1949 3 Apr to 30 Oct
# 1950 2 Apr to 29 Oct
# 1951 1 Apr to 28 Oct
# 1952 6 Apr to 25 Oct
# 1953 5 Apr to 1 Nov
# 1954 21 Mar to 31 Oct
# 1955 20 Mar to 6 Nov
# 1956 18 Mar to 4 Nov
# 1957 24 Mar to 3 Nov
# 1958 23 Mar to 2 Nov
# 1959 22 Mar to 1 Nov
# 1960 20 Mar to 6 Nov
# 1961 19 Mar to 5 Nov
# 1962 18 Mar to 4 Nov
# 1963 24 Mar to 3 Nov
# 1964 22 Mar to 1 Nov
# 1965 18 Apr to 17 Oct
# 1966 17 Apr to 16 Oct
# 1967 16 Apr to 22 Oct
# 1968 21 Apr to 20 Oct
# 1969 20 Apr to 19 Oct
# 1970 19 Apr to 18 Oct
# 1971 18 Apr to 17 Oct
# 1972 16 Apr to 22 Oct
# 1973 22 Apr to 21 Oct
# 1973/74 30 Dec 73 to 20 Oct 74
# 1975 20 Apr to 19 Oct
# 1976 18 Apr to 17 Oct
# 1977 Nil
# 1978 Nil
# 1979 13 May to 21 Oct
# 1980 to Now Nil
# The page does not give start or end times of day.
# The page does not give a start date for 1942.
# The page does not givw an end date for 1945.
# The Japanese occupation of Hong Kong began on 1941-12-25.
# The Japanese surrender of Hong Kong was signed 1945-09-15.
# For lack of anything better, use start of those days as the transition times.
# Hong Kong (Xianggang)
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule HK 1941 only - Apr 1 3:30 1:00 S
Rule HK 1941 only - Sep 30 3:30 0 -
Rule HK 1946 only - Apr 20 3:30 1:00 S
Rule HK 1946 only - Dec 1 3:30 0 -
Rule HK 1947 only - Apr 13 3:30 1:00 S
Rule HK 1947 only - Dec 30 3:30 0 -
Rule HK 1948 only - May 2 3:30 1:00 S
Rule HK 1948 1952 - Oct lastSun 3:30 0 -
Rule HK 1948 1951 - Oct lastSun 3:30 0 -
Rule HK 1952 only - Oct 25 3:30 0 -
Rule HK 1949 1953 - Apr Sun>=1 3:30 1:00 S
Rule HK 1953 only - Nov 1 3:30 0 -
Rule HK 1954 1964 - Mar Sun>=18 3:30 1:00 S
@ -388,13 +475,15 @@ Rule HK 1954 only - Oct 31 3:30 0 -
Rule HK 1955 1964 - Nov Sun>=1 3:30 0 -
Rule HK 1965 1977 - Apr Sun>=16 3:30 1:00 S
Rule HK 1965 1977 - Oct Sun>=16 3:30 0 -
Rule HK 1979 1980 - May Sun>=8 3:30 1:00 S
Rule HK 1979 1980 - Oct Sun>=16 3:30 0 -
Rule HK 1973 only - Dec 30 3:30 1:00 S
Rule HK 1979 only - May Sun>=8 3:30 1:00 S
Rule HK 1979 only - Oct Sun>=16 3:30 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Hong_Kong 7:36:36 - LMT 1904 Oct 30
8:00 HK HK%sT 1941 Dec 25
9:00 - JST 1945 Sep 15
8:00 HK HK%sT
###############################################################################
# Taiwan
@ -1696,16 +1785,66 @@ Zone Asia/Muscat 3:54:20 - LMT 1920
# advance clocks in the country by one hour from April 15 to
# conserve energy"
# From Arthur David Olson (2009-04-10):
# Assume for now that Pakistan will end DST in 2009 as it did in 2008.
# From Steffen Thorsen (2009-09-17):
# "The News International," Pakistan reports that: "The Federal
# Government has decided to restore the previous time by moving the
# clocks backward by one hour from October 1. A formal announcement to
# this effect will be made after the Prime Minister grants approval in
# this regard."
# <a href="http://www.thenews.com.pk/updates.asp?id=87168">
# http://www.thenews.com.pk/updates.asp?id=87168
# </a>
# From Alexander Krivenyshev (2009-09-28):
# According to Associated Press Of Pakistan, it is confirmed that
# Pakistan clocks across the country would be turned back by an hour from October
# 1, 2009.
#
# "Clocks to go back one hour from 1 Oct"
# <a href="http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=86715&Itemid=2">
# http://www.app.com.pk/en_/index.php?option=com_content&task=view&id=86715&Itemid=2
# </a>
# or
# <a href="http://www.worldtimezone.com/dst_news/dst_news_pakistan07.htm">
# http://www.worldtimezone.com/dst_news/dst_news_pakistan07.htm
# </a>
# From Steffen Thorsen (2009-09-29):
# Alexander Krivenyshev wrote:
# > According to Associated Press Of Pakistan, it is confirmed that
# > Pakistan clocks across the country would be turned back by an hour from October
# > 1, 2009.
#
# Now they seem to have changed their mind, November 1 is the new date:
# <a href="http://www.thenews.com.pk/top_story_detail.asp?Id=24742">
# http://www.thenews.com.pk/top_story_detail.asp?Id=24742
# </a>
# "The country's clocks will be reversed by one hour on November 1.
# Officials of Federal Ministry for Interior told this to Geo News on
# Monday."
#
# And more importantly, it seems that these dates will be kept every year:
# "It has now been decided that clocks will be wound forward by one hour
# on April 15 and reversed by an hour on November 1 every year without
# obtaining prior approval, the officials added."
#
# We have confirmed this year's end date with both with the Ministry of
# Water and Power and the Pakistan Electric Power Company:
# <a href="http://www.timeanddate.com/news/time/pakistan-ends-dst09.html">
# http://www.timeanddate.com/news/time/pakistan-ends-dst09.html
# </a>
# From Christoph Goehre (2009-10-01):
# [T]he German Consulate General in Karachi reported me today that Pakistan
# will go back to standard time on 1st of November.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule Pakistan 2002 only - Apr Sun>=2 0:01 1:00 S
Rule Pakistan 2002 only - Oct Sun>=2 0:01 0 -
Rule Pakistan 2008 only - Jun 1 0:00 1:00 S
Rule Pakistan 2008 only - Nov 1 0:00 0 -
Rule Pakistan 2009 only - Apr 15 0:00 1:00 S
Rule Pakistan 2009 only - Nov 1 0:00 0 -
Rule Pakistan 2009 max - Apr 15 0:00 1:00 S
Rule Pakistan 2009 max - Nov 1 0:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Karachi 4:28:12 - LMT 1907
5:30 - IST 1942 Sep
@ -1858,6 +1997,42 @@ Zone Asia/Karachi 4:28:12 - LMT 1907
# http://www.worldtimezone.com/dst_news/dst_news_westbank01.html
# </a>
# From Steffen Thorsen (2009-08-31):
# Palestine's Council of Ministers announced that they will revert back to
# winter time on Friday, 2009-09-04.
#
# One news source:
# <a href="http://www.safa.ps/ara/?action=showdetail&seid=4158">
# http://www.safa.ps/ara/?action=showdetail&seid=4158
# </a>
# (Palestinian press agency, Arabic),
# Google translate: "Decided that the Palestinian government in Ramallah
# headed by Salam Fayyad, the start of work in time for the winter of
# 2009, starting on Friday approved the fourth delay Sept. clock sixty
# minutes per hour as of Friday morning."
#
# We are not sure if Gaza will do the same, last year they had a different
# end date, we will keep this page updated:
# <a href="http://www.timeanddate.com/news/time/westbank-gaza-dst-2009.html">
# http://www.timeanddate.com/news/time/westbank-gaza-dst-2009.html
# </a>
# From Alexander Krivenyshev (2009-09-02):
# Seems that Gaza Strip will go back to Winter Time same date as West Bank.
#
# According to Palestinian Ministry Of Interior, West Bank and Gaza Strip plan
# to change time back to Standard time on September 4, 2009.
#
# "Winter time unite the West Bank and Gaza"
# (from Palestinian National Authority):
# <a href="http://www.moi.gov.ps/en/?page=633167343250594025&nid=11505
# http://www.moi.gov.ps/en/?page=633167343250594025&nid=11505
# </a>
# or
# <a href="http://www.worldtimezone.com/dst_news/dst_news_gazastrip02.html>
# http://www.worldtimezone.com/dst_news/dst_news_gazastrip02.html
# </a>
# The rules for Egypt are stolen from the `africa' file.
# Rule NAME FROM TO TYPE IN ON AT SAVE LETTER/S
Rule EgyptAsia 1957 only - May 10 0:00 1:00 S
@ -1876,7 +2051,7 @@ Rule Palestine 2006 only - Sep 22 0:00 0 -
Rule Palestine 2007 only - Sep Thu>=8 2:00 0 -
Rule Palestine 2008 only - Aug lastFri 2:00 0 -
Rule Palestine 2009 max - Mar lastFri 0:00 1:00 S
Rule Palestine 2009 max - Sep lastMon 2:00 0 -
Rule Palestine 2009 max - Sep Fri>=1 2:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Gaza 2:17:52 - LMT 1900 Oct
@ -2154,9 +2329,23 @@ Rule Syria 2007 only - Nov Fri>=1 0:00 0 -
# http://www.timeanddate.com/news/time/syria-dst-starts-march-27-2009.html
# </a>
# From Steffen Thorsen (2009-10-27):
# The Syrian Arab News Network on 2009-09-29 reported that Syria will
# revert back to winter (standard) time on midnight between Thursday
# 2009-10-29 and Friday 2009-10-30:
# <a href="http://www.sana.sy/ara/2/2009/09/29/247012.htm">
# http://www.sana.sy/ara/2/2009/09/29/247012.htm (Arabic)
# </a>
# From Arthur David Olson (2009-10-28):
# We'll see if future DST switching times turn out to be end of the last
# Thursday of the month or the start of the last Friday of the month or
# something else. For now, use the start of the last Friday.
Rule Syria 2008 only - Apr Fri>=1 0:00 1:00 S
Rule Syria 2008 max - Nov 1 0:00 0 -
Rule Syria 2008 only - Nov 1 0:00 0 -
Rule Syria 2009 max - Mar lastFri 0:00 1:00 S
Rule Syria 2009 max - Oct lastFri 0:00 0 -
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
Zone Asia/Damascus 2:25:12 - LMT 1920 # Dimashq

View File

@ -465,10 +465,56 @@ Zone Pacific/Pago_Pago 12:37:12 - LMT 1879 Jul 5
# http://www.worldtimezone.com/dst_news/dst_news_samoa01.html
# </a>
# From Steffen Thorsen (2009-08-27):
# Samoa's parliament passed the Daylight Saving Bill 2009, and will start
# daylight saving time on the first Sunday of October 2009 and end on the
# last Sunday of March 2010. We hope that the full text will be published
# soon, but we believe that the bill is only valid for 2009-2010. Samoa's
# Daylight Saving Act 2009 will be enforced as soon as the Head of State
# executes a proclamation publicizing this Act.
#
# Some background information here, which will be updated once we have
# more details:
# <a href="http://www.timeanddate.com/news/time/samoa-dst-plan-2009.html">
# http://www.timeanddate.com/news/time/samoa-dst-plan-2009.html
# </a>
# From Alexander Krivenyshev (2009-10-03):
# First, my deepest condolences to people of Samoa islands and all families and
# loved ones around the world who lost their lives in the earthquake and tsunami.
#
# Considering the recent devastation on Samoa by earthquake and tsunami and that
# many government offices/ ministers are closed- not sure if "Daylight Saving
# Bill 2009" will be implemented in next few days- on October 4, 2009.
#
# Here is reply from Consulate-General of Samoa in New Zealand
# ---------------------------
# Consul General
# consulgeneral@samoaconsulate.org.nz
#
# Talofa Alexander,
#
# Thank you for your sympathy for our country but at this time we have not
# been informed about the Daylight Savings Time Change. Most Ministries in
# Apia are closed or relocating due to weather concerns.
#
# When we do find out if they are still proceeding with the time change we
# will advise you soonest.
#
# Kind Regards,
# Lana
# for: Consul General
# From Steffen Thorsen (2009-10-05):
# We have called a hotel in Samoa and asked about local time there - they
# are still on standard time.
Zone Pacific/Apia 12:33:04 - LMT 1879 Jul 5
-11:26:56 - LMT 1911
-11:30 - SAMT 1950 # Samoa Time
-11:00 - WST # Samoa Time
-11:00 - WST 2009 Oct 4
-11:00 1:00 WSDT 2010 Mar 28
-11:00 - WST
# Solomon Is
# excludes Bougainville, for which see Papua New Guinea

View File

@ -2094,9 +2094,43 @@ Zone Asia/Novosibirsk 5:31:40 - LMT 1919 Dec 14 6:00
6:00 Russia NOV%sT 1992 Jan 19 2:00s
7:00 Russia NOV%sT 1993 May 23 # say Shanks & P.
6:00 Russia NOV%sT
# From Alexander Krivenyshev (2009-10-13):
# Kemerovo oblast' (Kemerovo region) in Russia will change current time zone on
# March 28, 2010:
# from current Russia Zone 6 - Krasnoyarsk Time Zone (KRA) UTC +0700
# to Russia Zone 5 - Novosibirsk Time Zone (NOV) UTC +0600
#
# This is according to Government of Russia decree # 740, on September
# 14, 2009 "Application in the territory of the Kemerovo region the Fifth
# time zone." ("Russia Zone 5" or old "USSR Zone 5" is GMT +0600)
#
# Russian Government web site (Russian language)
# <a href="http://www.government.ru/content/governmentactivity/rfgovernmentdecisions/archiv">
# http://www.government.ru/content/governmentactivity/rfgovernmentdecisions/archive/2009/09/14/991633.htm
# </a>
# or Russian-English translation by WorldTimeZone.com with reference
# map to local region and new Russia Time Zone map after March 28, 2010
# <a href="http://www.worldtimezone.com/dst_news/dst_news_russia03.html">
# http://www.worldtimezone.com/dst_news/dst_news_russia03.html
# </a>
#
# Thus, when Russia will switch to DST on the night of March 28, 2010
# Kemerovo region (Kemerovo oblast') will not change the clock.
#
# As a result, Kemerovo oblast' will be in the same time zone as
# Novosibirsk, Omsk, Tomsk, Barnaul and Altai Republic.
Zone Asia/Novokuznetsk 5:48:48 - NMT 1920 Jan 6
6:00 - KRAT 1930 Jun 21 # Krasnoyarsk Time
7:00 Russia KRA%sT 1991 Mar 31 2:00s
6:00 Russia KRA%sT 1992 Jan 19 2:00s
7:00 Russia KRA%sT 2010 Mar 28 2:00s
6:00 Russia NOV%sT # Novosibirsk/Novokuznetsk Time
#
# From Oscar van Vlijmen (2001-08-25): [This region consists of]
# Kemerovskaya oblast', Krasnoyarskij kraj,
# Krasnoyarskij kraj,
# Tajmyrskij (Dolgano-Nenetskij) avtonomnyj okrug,
# Respublika Tuva, Respublika Khakasiya, Evenkijskij avtonomnyj okrug.
Zone Asia/Krasnoyarsk 6:11:20 - LMT 1920 Jan 6

View File

@ -237,9 +237,23 @@ Rule Arg 2000 only - Mar 3 0:00 0 -
# http://www.jujuy.gov.ar/index2/partes_prensa/18_10_08/235-181008.doc
# </a>
# From fullinet (2009-10-18):
# As announced in
# <a hef="http://www.argentina.gob.ar/argentina/portal/paginas.dhtml?pagina=356">
# http://www.argentina.gob.ar/argentina/portal/paginas.dhtml?pagina=356
# </a>
# (an official .gob.ar) under title: "Sin Cambio de Hora" (english: "No hour change")
#
# "Por el momento, el Gobierno Nacional resolvio no modificar la hora
# oficial, decision que estaba en estudio para su implementacion el
# domingo 18 de octubre. Desde el Ministerio de Planificacion se anuncio
# que la Argentina hoy, en estas condiciones meteorologicas, no necesita
# la modificacion del huso horario, ya que 2009 nos encuentra con
# crecimiento en la produccion y distribucion energetica."
Rule Arg 2007 only - Dec 30 0:00 1:00 S
Rule Arg 2008 max - Mar Sun>=15 0:00 0 -
Rule Arg 2008 max - Oct Sun>=15 0:00 1:00 S
Rule Arg 2008 2009 - Mar Sun>=15 0:00 0 -
Rule Arg 2008 only - Oct Sun>=15 0:00 1:00 S
# From Mariano Absatz (2004-05-21):
# Today it was officially published that the Province of Mendoza is changing
@ -411,15 +425,40 @@ Rule Arg 2008 max - Oct Sun>=15 0:00 1:00 S
# during 2009, this timezone change will run from 00:00 the third Sunday
# in March until 24:00 of the second Saturday in October.
# From Arthur David Olson (2009-03-16):
# The unofficial claim at
# <a href="http://www.timeanddate.com/news/time/san-luis-new-time-zone.html">
# http://www.timeanddate.com/news/time/san-luis-new-time-zone.html
# </a>
# is that "The province will most likely follow the next daylight saving schedule,
# which is planned for the second Sunday in October."
# From Mariano Absatz (2009-10-16):
# ...the Province of San Luis is a case in itself.
#
# The Law at
# <a href="http://www.diputadossanluis.gov.ar/diputadosasp/paginas/verNorma.asp?NormaID=276>"
# http://www.diputadossanluis.gov.ar/diputadosasp/paginas/verNorma.asp?NormaID=276
# </a>
# is ambiguous because establishes a calendar from the 2nd Sunday in
# October at 0:00 thru the 2nd Saturday in March at 24:00 and the
# complement of that starting on the 2nd Sunday of March at 0:00 and
# ending on the 2nd Saturday of March at 24:00.
#
# This clearly breaks every time the 1st of March or October is a Sunday.
#
# IMHO, the "spirit of the Law" is to make the changes at 0:00 on the 2nd
# Sunday of October and March.
#
# The problem is that the changes in the rest of the Provinces that did
# change in 2007/2008, were made according to the Federal Law and Decrees
# that did so on the 3rd Sunday of October and March.
#
# In fact, San Luis actually switched from UTC-4 to UTC-3 last Sunday
# (October 11th) at 0:00.
#
# So I guess a new set of rules, besides "Arg", must be made and the last
# America/Argentina/San_Luis entries should change to use these...
#
# I'm enclosing a patch that does what I say... regretfully, the San Luis
# timezone must be called "WART/WARST" even when most of the time (like,
# right now) WARST == ART... that is, since last Sunday, all the country
# is using UTC-3, but in my patch, San Luis calls it "WARST" and the rest
# of the country calls it "ART".
# ...
# Zone NAME GMTOFF RULES FORMAT [UNTIL]
#
# Buenos Aires (BA), Capital Federal (CF),
@ -552,6 +591,10 @@ Zone America/Argentina/Mendoza -4:35:16 - LMT 1894 Oct 31
-3:00 - ART
#
# San Luis (SL)
Rule SanLuis 2008 max - Mar Sun>=8 0:00 0 -
Rule SanLuis 2007 max - Oct Sun>=8 0:00 1:00 S
Zone America/Argentina/San_Luis -4:25:24 - LMT 1894 Oct 31
-4:16:48 - CMT 1920 May
-4:00 - ART 1930 Dec
@ -566,8 +609,7 @@ Zone America/Argentina/San_Luis -4:25:24 - LMT 1894 Oct 31
-3:00 - ART 2004 May 31
-4:00 - WART 2004 Jul 25
-3:00 Arg AR%sT 2008 Jan 21
-3:00 - ART 2009 Mar 15
-4:00 Arg WAR%sT
-4:00 SanLuis WAR%sT
#
# Santa Cruz (SC)
Zone America/Argentina/Rio_Gallegos -4:36:52 - LMT 1894 Oct 31

View File

@ -352,6 +352,7 @@ RU +5312+05009 Europe/Samara Moscow+01 - Samara, Udmurtia
RU +5651+06036 Asia/Yekaterinburg Moscow+02 - Urals
RU +5500+07324 Asia/Omsk Moscow+03 - west Siberia
RU +5502+08255 Asia/Novosibirsk Moscow+03 - Novosibirsk
RU +5345+08707 Asia/Novokuznetsk Moscow+03 - Novokuznetsk
RU +5601+09250 Asia/Krasnoyarsk Moscow+04 - Yenisei River
RU +5216+10420 Asia/Irkutsk Moscow+05 - Lake Baikal
RU +6200+12940 Asia/Yakutsk Moscow+06 - Lena River

View File

@ -45,8 +45,14 @@ FILES_java = \
sun/net/dns/ResolverConfiguration.java \
sun/net/dns/ResolverConfigurationImpl.java \
sun/net/ftp/FtpClient.java \
sun/net/ftp/FtpClientProvider.java \
sun/net/ftp/FtpDirEntry.java \
sun/net/ftp/FtpReplyCode.java \
sun/net/ftp/FtpDirParser.java \
sun/net/ftp/FtpLoginException.java \
sun/net/ftp/FtpProtocolException.java \
sun/net/ftp/impl/FtpClient.java \
sun/net/ftp/impl/DefaultFtpClientProvider.java \
sun/net/spi/DefaultProxySelector.java \
sun/net/spi/nameservice/NameServiceDescriptor.java \
sun/net/spi/nameservice/NameService.java \
@ -79,7 +85,6 @@ FILES_java = \
sun/net/www/http/Hurryable.java \
sun/net/www/protocol/http/Handler.java \
sun/net/www/protocol/http/HttpURLConnection.java \
sun/net/www/protocol/http/HttpLogFormatter.java \
sun/net/www/protocol/http/HttpAuthenticator.java \
sun/net/www/protocol/http/AuthenticationHeader.java \
sun/net/www/protocol/http/AuthenticationInfo.java \
@ -89,11 +94,13 @@ FILES_java = \
sun/net/www/protocol/http/AuthScheme.java \
sun/net/www/protocol/http/BasicAuthentication.java \
sun/net/www/protocol/http/DigestAuthentication.java \
sun/net/www/protocol/http/NTLMAuthentication.java \
sun/net/www/protocol/http/NTLMAuthenticationProxy.java \
sun/net/www/protocol/http/NegotiateAuthentication.java \
sun/net/www/protocol/http/NegotiatorImpl.java \
sun/net/www/protocol/http/NegotiateCallbackHandler.java \
sun/net/www/protocol/http/Negotiator.java \
sun/net/www/protocol/http/ntlm/NTLMAuthentication.java \
sun/net/www/protocol/http/spnego/NegotiatorImpl.java \
sun/net/www/protocol/http/spnego/NegotiateCallbackHandler.java \
sun/net/www/protocol/http/logging/HttpLogFormatter.java \
sun/net/www/protocol/https/AbstractDelegateHttpsURLConnection.java \
sun/net/www/protocol/https/HttpsClient.java \
sun/net/www/protocol/https/DefaultHostnameVerifier.java \
@ -128,7 +135,7 @@ FILES_java = \
sun/net/idn/StringPrep.java
ifeq ($(PLATFORM), windows)
FILES_java += sun/net/www/protocol/http/NTLMAuthSequence.java
FILES_java += sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java
endif
ifeq ($(PLATFORM), solaris)

View File

@ -39,6 +39,7 @@ AUTO_FILES_JAVA_DIRS = \
sun/security/provider \
sun/security/rsa \
sun/security/ssl \
sun/security/ssl/krb5 \
sun/security/timestamp \
sun/security/validator \
sun/security/x509 \

View File

@ -62,6 +62,8 @@ import javax.imageio.event.IIOReadWarningListener;
import java.io.*;
import java.nio.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;
@ -502,12 +504,18 @@ public class BMPImageReader extends ImageReader implements BMPConstants {
iis.reset();
try {
if (metadata.colorSpace == PROFILE_LINKED)
if (metadata.colorSpace == PROFILE_LINKED &&
isLinkedProfileAllowed() &&
!isUncOrDevicePath(profile))
{
String path = new String(profile, "windows-1252");
colorSpace =
new ICC_ColorSpace(ICC_Profile.getInstance(new String(profile)));
else
new ICC_ColorSpace(ICC_Profile.getInstance(path));
} else {
colorSpace =
new ICC_ColorSpace(ICC_Profile.getInstance(profile));
}
} catch (Exception e) {
colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
}
@ -1745,4 +1753,69 @@ public class BMPImageReader extends ImageReader implements BMPConstants {
public void sequenceStarted(ImageReader src, int minIndex) {}
public void readAborted(ImageReader src) {}
}
private static Boolean isLinkedProfileDisabled = null;
private static boolean isLinkedProfileAllowed() {
if (isLinkedProfileDisabled == null) {
PrivilegedAction<Boolean> a = new PrivilegedAction<Boolean>() {
public Boolean run() {
return Boolean.getBoolean("sun.imageio.plugins.bmp.disableLinkedProfiles");
}
};
isLinkedProfileDisabled = AccessController.doPrivileged(a);
}
return !isLinkedProfileDisabled;
}
private static Boolean isWindowsPlatform = null;
/**
* Verifies whether the byte array contans a unc path.
* Non-UNC path examples:
* c:\path\to\file - simple notation
* \\?\c:\path\to\file - long notation
*
* UNC path examples:
* \\server\share - a UNC path in simple notation
* \\?\UNC\server\share - a UNC path in long notation
* \\.\some\device - a path to device.
*/
private static boolean isUncOrDevicePath(byte[] p) {
if (isWindowsPlatform == null) {
PrivilegedAction<Boolean> a = new PrivilegedAction<Boolean>() {
public Boolean run() {
String osname = System.getProperty("os.name");
return (osname != null &&
osname.toLowerCase().startsWith("win"));
}
};
isWindowsPlatform = AccessController.doPrivileged(a);
}
if (!isWindowsPlatform) {
/* no need for the check on platforms except windows */
return false;
}
/* normalize prefix of the path */
if (p[0] == '/') p[0] = '\\';
if (p[1] == '/') p[1] = '\\';
if (p[3] == '/') p[3] = '\\';
if ((p[0] == '\\') && (p[1] == '\\')) {
if ((p[2] == '?') && (p[3] == '\\')) {
// long path: whether unc or local
return ((p[4] == 'U' || p[4] == 'u') &&
(p[5] == 'N' || p[5] == 'n') &&
(p[6] == 'C' || p[6] == 'c'));
} else {
// device path or short unc notation
return true;
}
} else {
return false;
}
}
}

View File

@ -25,6 +25,8 @@
package com.sun.java.swing.plaf.motif;
import sun.awt.AppContext;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.basic.*;
@ -46,16 +48,23 @@ import javax.swing.plaf.*;
*/
public class MotifButtonUI extends BasicButtonUI {
private final static MotifButtonUI motifButtonUI = new MotifButtonUI();
protected Color selectColor;
private boolean defaults_initialized = false;
private static final Object MOTIF_BUTTON_UI_KEY = new Object();
// ********************************
// Create PLAF
// ********************************
public static ComponentUI createUI(JComponent c){
public static ComponentUI createUI(JComponent c) {
AppContext appContext = AppContext.getAppContext();
MotifButtonUI motifButtonUI =
(MotifButtonUI) appContext.get(MOTIF_BUTTON_UI_KEY);
if (motifButtonUI == null) {
motifButtonUI = new MotifButtonUI();
appContext.put(MOTIF_BUTTON_UI_KEY, motifButtonUI);
}
return motifButtonUI;
}

View File

@ -25,6 +25,8 @@
package com.sun.java.swing.plaf.motif;
import sun.awt.AppContext;
import javax.swing.*;
import javax.swing.plaf.*;
@ -45,7 +47,7 @@ import java.awt.*;
*/
public class MotifCheckBoxUI extends MotifRadioButtonUI {
private static final MotifCheckBoxUI motifCheckBoxUI = new MotifCheckBoxUI();
private static final Object MOTIF_CHECK_BOX_UI_KEY = new Object();
private final static String propertyPrefix = "CheckBox" + ".";
@ -55,7 +57,14 @@ public class MotifCheckBoxUI extends MotifRadioButtonUI {
// ********************************
// Create PLAF
// ********************************
public static ComponentUI createUI(JComponent c){
public static ComponentUI createUI(JComponent c) {
AppContext appContext = AppContext.getAppContext();
MotifCheckBoxUI motifCheckBoxUI =
(MotifCheckBoxUI) appContext.get(MOTIF_CHECK_BOX_UI_KEY);
if (motifCheckBoxUI == null) {
motifCheckBoxUI = new MotifCheckBoxUI();
appContext.put(MOTIF_CHECK_BOX_UI_KEY, motifCheckBoxUI);
}
return motifCheckBoxUI;
}

View File

@ -25,6 +25,8 @@
package com.sun.java.swing.plaf.motif;
import sun.awt.AppContext;
import javax.swing.*;
import javax.swing.plaf.basic.BasicLabelUI;
import javax.swing.plaf.ComponentUI;
@ -44,9 +46,16 @@ import javax.swing.plaf.ComponentUI;
*/
public class MotifLabelUI extends BasicLabelUI
{
static MotifLabelUI sharedInstance = new MotifLabelUI();
private static final Object MOTIF_LABEL_UI_KEY = new Object();
public static ComponentUI createUI(JComponent c) {
return sharedInstance;
AppContext appContext = AppContext.getAppContext();
MotifLabelUI motifLabelUI =
(MotifLabelUI) appContext.get(MOTIF_LABEL_UI_KEY);
if (motifLabelUI == null) {
motifLabelUI = new MotifLabelUI();
appContext.put(MOTIF_LABEL_UI_KEY, motifLabelUI);
}
return motifLabelUI;
}
}

View File

@ -25,6 +25,8 @@
package com.sun.java.swing.plaf.motif;
import sun.awt.AppContext;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.plaf.basic.BasicRadioButtonUI;
@ -47,7 +49,7 @@ import java.awt.*;
*/
public class MotifRadioButtonUI extends BasicRadioButtonUI {
private static final MotifRadioButtonUI motifRadioButtonUI = new MotifRadioButtonUI();
private static final Object MOTIF_RADIO_BUTTON_UI_KEY = new Object();
protected Color focusColor;
@ -57,6 +59,13 @@ public class MotifRadioButtonUI extends BasicRadioButtonUI {
// Create PLAF
// ********************************
public static ComponentUI createUI(JComponent c) {
AppContext appContext = AppContext.getAppContext();
MotifRadioButtonUI motifRadioButtonUI =
(MotifRadioButtonUI) appContext.get(MOTIF_RADIO_BUTTON_UI_KEY);
if (motifRadioButtonUI == null) {
motifRadioButtonUI = new MotifRadioButtonUI();
appContext.put(MOTIF_RADIO_BUTTON_UI_KEY, motifRadioButtonUI);
}
return motifRadioButtonUI;
}

View File

@ -25,6 +25,8 @@
package com.sun.java.swing.plaf.motif;
import sun.awt.AppContext;
import java.awt.*;
import java.awt.event.*;
@ -48,7 +50,7 @@ import javax.swing.plaf.basic.*;
*/
public class MotifToggleButtonUI extends BasicToggleButtonUI
{
private final static MotifToggleButtonUI motifToggleButtonUI = new MotifToggleButtonUI();
private static final Object MOTIF_TOGGLE_BUTTON_UI_KEY = new Object();
protected Color selectColor;
@ -58,6 +60,13 @@ public class MotifToggleButtonUI extends BasicToggleButtonUI
// Create PLAF
// ********************************
public static ComponentUI createUI(JComponent b) {
AppContext appContext = AppContext.getAppContext();
MotifToggleButtonUI motifToggleButtonUI =
(MotifToggleButtonUI) appContext.get(MOTIF_TOGGLE_BUTTON_UI_KEY);
if (motifToggleButtonUI == null) {
motifToggleButtonUI = new MotifToggleButtonUI();
appContext.put(MOTIF_TOGGLE_BUTTON_UI_KEY, motifToggleButtonUI);
}
return motifToggleButtonUI;
}

View File

@ -35,6 +35,7 @@ import java.awt.*;
import static com.sun.java.swing.plaf.windows.TMSchema.*;
import static com.sun.java.swing.plaf.windows.TMSchema.Part.*;
import static com.sun.java.swing.plaf.windows.XPStyle.Skin;
import sun.awt.AppContext;
/**
@ -52,8 +53,6 @@ import static com.sun.java.swing.plaf.windows.XPStyle.Skin;
*/
public class WindowsButtonUI extends BasicButtonUI
{
private final static WindowsButtonUI windowsButtonUI = new WindowsButtonUI();
protected int dashedRectGapX;
protected int dashedRectGapY;
protected int dashedRectGapWidth;
@ -63,11 +62,19 @@ public class WindowsButtonUI extends BasicButtonUI
private boolean defaults_initialized = false;
private static final Object WINDOWS_BUTTON_UI_KEY = new Object();
// ********************************
// Create PLAF
// ********************************
public static ComponentUI createUI(JComponent c){
public static ComponentUI createUI(JComponent c) {
AppContext appContext = AppContext.getAppContext();
WindowsButtonUI windowsButtonUI =
(WindowsButtonUI) appContext.get(WINDOWS_BUTTON_UI_KEY);
if (windowsButtonUI == null) {
windowsButtonUI = new WindowsButtonUI();
appContext.put(WINDOWS_BUTTON_UI_KEY, windowsButtonUI);
}
return windowsButtonUI;
}
@ -151,7 +158,7 @@ public class WindowsButtonUI extends BasicButtonUI
* allocating them in each paint call substantially reduced the time
* it took paint to run. Obviously, this method can't be re-entered.
*/
private static Rectangle viewRect = new Rectangle();
private Rectangle viewRect = new Rectangle();
public void paint(Graphics g, JComponent c) {
if (XPStyle.getXP() != null) {

View File

@ -25,6 +25,8 @@
package com.sun.java.swing.plaf.windows;
import sun.awt.AppContext;
import javax.swing.plaf.basic.*;
import javax.swing.*;
import javax.swing.plaf.*;
@ -49,7 +51,7 @@ public class WindowsCheckBoxUI extends WindowsRadioButtonUI
// of BasicCheckBoxUI because we want to pick up all the
// painting changes made in MetalRadioButtonUI.
private static final WindowsCheckBoxUI windowsCheckBoxUI = new WindowsCheckBoxUI();
private static final Object WINDOWS_CHECK_BOX_UI_KEY = new Object();
private final static String propertyPrefix = "CheckBox" + ".";
@ -59,6 +61,13 @@ public class WindowsCheckBoxUI extends WindowsRadioButtonUI
// Create PLAF
// ********************************
public static ComponentUI createUI(JComponent c) {
AppContext appContext = AppContext.getAppContext();
WindowsCheckBoxUI windowsCheckBoxUI =
(WindowsCheckBoxUI) appContext.get(WINDOWS_CHECK_BOX_UI_KEY);
if (windowsCheckBoxUI == null) {
windowsCheckBoxUI = new WindowsCheckBoxUI();
appContext.put(WINDOWS_CHECK_BOX_UI_KEY, windowsCheckBoxUI);
}
return windowsCheckBoxUI;
}

View File

@ -26,6 +26,8 @@
package com.sun.java.swing.plaf.windows;
import sun.swing.SwingUtilities2;
import sun.awt.AppContext;
import java.awt.Color;
import java.awt.Graphics;
@ -51,12 +53,19 @@ import javax.swing.plaf.basic.BasicLabelUI;
*/
public class WindowsLabelUI extends BasicLabelUI {
private final static WindowsLabelUI windowsLabelUI = new WindowsLabelUI();
private static final Object WINDOWS_LABEL_UI_KEY = new Object();
// ********************************
// Create PLAF
// ********************************
public static ComponentUI createUI(JComponent c){
public static ComponentUI createUI(JComponent c) {
AppContext appContext = AppContext.getAppContext();
WindowsLabelUI windowsLabelUI =
(WindowsLabelUI) appContext.get(WINDOWS_LABEL_UI_KEY);
if (windowsLabelUI == null) {
windowsLabelUI = new WindowsLabelUI();
appContext.put(WINDOWS_LABEL_UI_KEY, windowsLabelUI);
}
return windowsLabelUI;
}

View File

@ -25,6 +25,8 @@
package com.sun.java.swing.plaf.windows;
import sun.awt.AppContext;
import javax.swing.plaf.basic.*;
import javax.swing.*;
import javax.swing.plaf.*;
@ -44,7 +46,7 @@ import java.awt.*;
*/
public class WindowsRadioButtonUI extends BasicRadioButtonUI
{
private static final WindowsRadioButtonUI windowsRadioButtonUI = new WindowsRadioButtonUI();
private static final Object WINDOWS_RADIO_BUTTON_UI_KEY = new Object();
protected int dashedRectGapX;
protected int dashedRectGapY;
@ -59,6 +61,13 @@ public class WindowsRadioButtonUI extends BasicRadioButtonUI
// Create PLAF
// ********************************
public static ComponentUI createUI(JComponent c) {
AppContext appContext = AppContext.getAppContext();
WindowsRadioButtonUI windowsRadioButtonUI =
(WindowsRadioButtonUI) appContext.get(WINDOWS_RADIO_BUTTON_UI_KEY);
if (windowsRadioButtonUI == null) {
windowsRadioButtonUI = new WindowsRadioButtonUI();
appContext.put(WINDOWS_RADIO_BUTTON_UI_KEY, windowsRadioButtonUI);
}
return windowsRadioButtonUI;
}

View File

@ -25,6 +25,8 @@
package com.sun.java.swing.plaf.windows;
import sun.awt.AppContext;
import javax.swing.plaf.basic.*;
import javax.swing.border.*;
import javax.swing.plaf.*;
@ -49,18 +51,25 @@ import java.beans.PropertyChangeEvent;
*/
public class WindowsToggleButtonUI extends BasicToggleButtonUI
{
protected static int dashedRectGapX;
protected static int dashedRectGapY;
protected static int dashedRectGapWidth;
protected static int dashedRectGapHeight;
protected int dashedRectGapX;
protected int dashedRectGapY;
protected int dashedRectGapWidth;
protected int dashedRectGapHeight;
protected Color focusColor;
private final static WindowsToggleButtonUI windowsToggleButtonUI = new WindowsToggleButtonUI();
private static final Object WINDOWS_TOGGLE_BUTTON_UI_KEY = new Object();
private boolean defaults_initialized = false;
public static ComponentUI createUI(JComponent b) {
AppContext appContext = AppContext.getAppContext();
WindowsToggleButtonUI windowsToggleButtonUI =
(WindowsToggleButtonUI) appContext.get(WINDOWS_TOGGLE_BUTTON_UI_KEY);
if (windowsToggleButtonUI == null) {
windowsToggleButtonUI = new WindowsToggleButtonUI();
appContext.put(WINDOWS_TOGGLE_BUTTON_UI_KEY, windowsToggleButtonUI);
}
return windowsToggleButtonUI;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1999-2007 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -176,18 +176,6 @@ public class JmxProperties {
public static final String RELATION_LOGGER_NAME =
"javax.management.relation";
/**
* Logger name for Namespaces.
*/
public static final String NAMESPACE_LOGGER_NAME =
"javax.management.namespace";
/**
* Logger name for Namespaces.
*/
public static final Logger NAMESPACE_LOGGER =
Logger.getLogger(NAMESPACE_LOGGER_NAME);
/**
* Logger for Relation Service.
*/

View File

@ -69,9 +69,9 @@ public class ServiceName {
/**
* The version of the JMX specification implemented by this product.
* <BR>
* The value is <CODE>2.0</CODE>.
* The value is <CODE>1.4</CODE>.
*/
public static final String JMX_SPEC_VERSION = "2.0";
public static final String JMX_SPEC_VERSION = "1.4";
/**
* The vendor of the JMX specification implemented by this product.

View File

@ -1,77 +0,0 @@
/*
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.event;
import com.sun.jmx.remote.util.ClassLogger;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.atomic.AtomicInteger;
public class DaemonThreadFactory implements ThreadFactory {
public DaemonThreadFactory(String nameTemplate) {
this(nameTemplate, null);
}
// nameTemplate should be a format with %d in it, which will be replaced
// by a sequence number of threads created by this factory.
public DaemonThreadFactory(String nameTemplate, ThreadGroup threadGroup) {
if (logger.debugOn()) {
logger.debug("DaemonThreadFactory",
"Construct a new daemon factory: "+nameTemplate);
}
if (threadGroup == null) {
SecurityManager s = System.getSecurityManager();
threadGroup = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
}
this.nameTemplate = nameTemplate;
this.threadGroup = threadGroup;
}
public Thread newThread(Runnable r) {
final String name =
String.format(nameTemplate, threadNumber.getAndIncrement());
Thread t = new Thread(threadGroup, r, name, 0);
t.setDaemon(true);
if (t.getPriority() != Thread.NORM_PRIORITY)
t.setPriority(Thread.NORM_PRIORITY);
if (logger.debugOn()) {
logger.debug("newThread",
"Create a new daemon thread with the name "+t.getName());
}
return t;
}
private final String nameTemplate;
private final ThreadGroup threadGroup;
private final AtomicInteger threadNumber = new AtomicInteger(1);
private static final ClassLogger logger =
new ClassLogger("com.sun.jmx.event", "DaemonThreadFactory");
}

View File

@ -1,252 +0,0 @@
/*
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.event;
import com.sun.jmx.remote.util.ClassLogger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.management.remote.NotificationResult;
import javax.management.remote.TargetedNotification;
public class EventBuffer {
public EventBuffer() {
this(Integer.MAX_VALUE, null);
}
public EventBuffer(int capacity) {
this(capacity, new ArrayList<TargetedNotification>());
}
public EventBuffer(int capacity, final List<TargetedNotification> list) {
if (logger.traceOn()) {
logger.trace("EventBuffer", "New buffer with the capacity: "
+capacity);
}
if (capacity < 1) {
throw new IllegalArgumentException(
"The capacity must be bigger than 0");
}
if (list == null) {
throw new NullPointerException("Null list.");
}
this.capacity = capacity;
this.list = list;
}
public void add(TargetedNotification tn) {
if (logger.traceOn()) {
logger.trace("add", "Add one notif.");
}
synchronized(lock) {
if (list.size() == capacity) { // have to throw one
passed++;
list.remove(0);
if (logger.traceOn()) {
logger.trace("add", "Over, remove the oldest one.");
}
}
list.add(tn);
lock.notify();
}
}
public void add(TargetedNotification[] tns) {
if (tns == null || tns.length == 0) {
return;
}
if (logger.traceOn()) {
logger.trace("add", "Add notifs: "+tns.length);
}
synchronized(lock) {
final int d = list.size() - capacity + tns.length;
if (d > 0) { // have to throw
passed += d;
if (logger.traceOn()) {
logger.trace("add",
"Over, remove the oldest: "+d);
}
if (tns.length <= capacity){
list.subList(0, d).clear();
} else {
list.clear();
TargetedNotification[] tmp =
new TargetedNotification[capacity];
System.arraycopy(tns, tns.length-capacity, tmp, 0, capacity);
tns = tmp;
}
}
Collections.addAll(list,tns);
lock.notify();
}
}
public NotificationResult fetchNotifications(long startSequenceNumber,
long timeout,
int maxNotifications) {
if (logger.traceOn()) {
logger.trace("fetchNotifications",
"Being called: "
+startSequenceNumber+" "
+timeout+" "+maxNotifications);
}
if (startSequenceNumber < 0 ||
timeout < 0 ||
maxNotifications < 0) {
throw new IllegalArgumentException("Negative value.");
}
TargetedNotification[] tns = new TargetedNotification[0];
long earliest = startSequenceNumber < passed ?
passed : startSequenceNumber;
long next = earliest;
final long startTime = System.currentTimeMillis();
long toWait = timeout;
synchronized(lock) {
int toSkip = (int)(startSequenceNumber - passed);
// skip those before startSequenceNumber.
while (!closed && toSkip > 0) {
toWait = timeout - (System.currentTimeMillis() - startTime);
if (list.size() == 0) {
if (toWait <= 0) {
// the notification of startSequenceNumber
// does not arrive yet.
return new NotificationResult(startSequenceNumber,
startSequenceNumber,
new TargetedNotification[0]);
}
waiting(toWait);
continue;
}
if (toSkip <= list.size()) {
list.subList(0, toSkip).clear();
passed += toSkip;
break;
} else {
passed += list.size();
toSkip -= list.size();
list.clear();
}
}
earliest = passed;
if (list.size() == 0) {
toWait = timeout - (System.currentTimeMillis() - startTime);
waiting(toWait);
}
if (list.size() == 0) {
tns = new TargetedNotification[0];
} else if (list.size() <= maxNotifications) {
tns = list.toArray(new TargetedNotification[0]);
} else {
tns = new TargetedNotification[maxNotifications];
for (int i=0; i<maxNotifications; i++) {
tns[i] = list.get(i);
}
}
next = earliest + tns.length;
}
if (logger.traceOn()) {
logger.trace("fetchNotifications",
"Return: "+earliest+" "+next+" "+tns.length);
}
return new NotificationResult(earliest, next, tns);
}
public int size() {
return list.size();
}
public void addLost(long nb) {
synchronized(lock) {
passed += nb;
}
}
public void close() {
if (logger.traceOn()) {
logger.trace("clear", "done");
}
synchronized(lock) {
list.clear();
closed = true;
lock.notifyAll();
}
}
// -------------------------------------------
// private classes
// -------------------------------------------
private void waiting(long timeout) {
final long startTime = System.currentTimeMillis();
long toWait = timeout;
synchronized(lock) {
while (!closed && list.size() == 0 && toWait > 0) {
try {
lock.wait(toWait);
toWait = timeout - (System.currentTimeMillis() - startTime);
} catch (InterruptedException ire) {
logger.trace("waiting", ire);
break;
}
}
}
}
private final int capacity;
private final List<TargetedNotification> list;
private boolean closed;
private long passed = 0;
private final int[] lock = new int[0];
private static final ClassLogger logger =
new ClassLogger("javax.management.event", "EventBuffer");
}

View File

@ -1,81 +0,0 @@
/*
* Copyright 2002-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.event;
import java.io.IOException;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import javax.management.MBeanServerConnection;
import javax.management.event.EventClient;
import javax.management.event.EventClientDelegate;
import javax.management.event.EventConsumer;
import javax.management.event.NotificationManager;
/**
* Override the methods related to the notification to use the
* Event service.
*/
public interface EventConnection extends MBeanServerConnection, EventConsumer {
public EventClient getEventClient();
public static class Factory {
public static EventConnection make(
final MBeanServerConnection mbsc,
final EventClient eventClient)
throws IOException {
if (!mbsc.isRegistered(EventClientDelegate.OBJECT_NAME)) {
throw new IOException(
"The server does not support the event service.");
}
InvocationHandler ih = new InvocationHandler() {
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
Class<?> intf = method.getDeclaringClass();
try {
if (intf.isInstance(eventClient))
return method.invoke(eventClient, args);
else
return method.invoke(mbsc, args);
} catch (InvocationTargetException e) {
throw e.getCause();
}
}
};
// It is important to declare NotificationManager.class first
// in the array below, so that the relevant addNL and removeNL
// methods will show up with method.getDeclaringClass() as
// being from that interface and not MBeanServerConnection.
return (EventConnection) Proxy.newProxyInstance(
NotificationManager.class.getClassLoader(),
new Class<?>[] {
NotificationManager.class, EventConnection.class,
},
ih);
}
}
}

View File

@ -1,65 +0,0 @@
/*
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.event;
import com.sun.jmx.mbeanserver.GetPropertyAction;
import com.sun.jmx.remote.util.ClassLogger;
import java.security.AccessController;
import javax.management.event.EventClient;
/**
*
* @author sjiang
*/
public class EventParams {
public static final String DEFAULT_LEASE_TIMEOUT =
"com.sun.event.lease.time";
@SuppressWarnings("cast") // cast for jdk 1.5
public static long getLeaseTimeout() {
long timeout = EventClient.DEFAULT_REQUESTED_LEASE_TIME;
try {
final GetPropertyAction act =
new GetPropertyAction(DEFAULT_LEASE_TIMEOUT);
final String s = (String)AccessController.doPrivileged(act);
if (s != null) {
timeout = Long.parseLong(s);
}
} catch (RuntimeException e) {
logger.fine("getLeaseTimeout", "exception getting property", e);
}
return timeout;
}
/** Creates a new instance of EventParams */
private EventParams() {
}
private static final ClassLogger logger =
new ClassLogger("javax.management.event", "EventParams");
}

View File

@ -1,155 +0,0 @@
/*
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.event;
import com.sun.jmx.remote.util.ClassLogger;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;
/**
* <p>Manage a renewable lease. The lease can be renewed indefinitely
* but if the lease runs to its current expiry date without being renewed
* then the expiry callback is invoked. If the lease has already expired
* when renewal is attempted then the lease method returns zero.</p>
* @author sjiang
* @author emcmanus
*/
// The synchronization logic of this class is tricky to deal correctly with the
// case where the lease expires at the same time as the |lease| or |stop| method
// is called. If the lease is active then the field |scheduled| represents
// the expiry task; otherwise |scheduled| is null. Renewing or stopping the
// lease involves canceling this task and setting |scheduled| either to a new
// task (to renew) or to null (to stop).
//
// Suppose the expiry task runs at the same time as the |lease| method is called.
// If the task enters its synchronized block before the method starts, then
// it will set |scheduled| to null and the method will return 0. If the method
// starts before the task enters its synchronized block, then the method will
// cancel the task which will see that when it later enters the block.
// Similar reasoning applies to the |stop| method. It is not expected that
// different threads will call |lease| or |stop| simultaneously, although the
// logic should be correct then too.
public class LeaseManager {
public LeaseManager(Runnable callback) {
this(callback, EventParams.getLeaseTimeout());
}
public LeaseManager(Runnable callback, long timeout) {
if (logger.traceOn()) {
logger.trace("LeaseManager", "new manager with lease: "+timeout);
}
if (callback == null) {
throw new NullPointerException("Null callback.");
}
if (timeout <= 0)
throw new IllegalArgumentException("Timeout must be positive: " + timeout);
this.callback = callback;
schedule(timeout);
}
/**
* <p>Renew the lease for the given time. The new time can be shorter
* than the previous one, in which case the lease will expire earlier
* than it would have.</p>
*
* <p>Calling this method after the lease has expired will return zero
* immediately and have no other effect.</p>
*
* @param timeout the new lifetime. If zero, the lease
* will expire immediately.
*/
public synchronized long lease(long timeout) {
if (logger.traceOn()) {
logger.trace("lease", "new lease to: "+timeout);
}
if (timeout < 0)
throw new IllegalArgumentException("Negative lease: " + timeout);
if (scheduled == null)
return 0L;
scheduled.cancel(false);
if (logger.traceOn())
logger.trace("lease", "start lease: "+timeout);
schedule(timeout);
return timeout;
}
private class Expire implements Runnable {
ScheduledFuture<?> task;
public void run() {
synchronized (LeaseManager.this) {
if (task.isCancelled())
return;
scheduled = null;
}
callback.run();
executor.shutdown();
}
}
private synchronized void schedule(long timeout) {
Expire expire = new Expire();
scheduled = executor.schedule(expire, timeout, TimeUnit.MILLISECONDS);
expire.task = scheduled;
}
/**
* <p>Cancel the lease without calling the expiry callback.</p>
*/
public synchronized void stop() {
logger.trace("stop", "canceling lease");
scheduled.cancel(false);
scheduled = null;
try {
executor.shutdown();
} catch (SecurityException e) {
// OK: caller doesn't have RuntimePermission("modifyThread")
// which is unlikely in reality but triggers a test failure otherwise
logger.trace("stop", "exception from executor.shutdown", e);
}
}
private final Runnable callback;
private ScheduledFuture<?> scheduled; // If null, the lease has expired.
private static final ThreadFactory threadFactory =
new DaemonThreadFactory("JMX LeaseManager %d");
private final ScheduledExecutorService executor
= Executors.newScheduledThreadPool(1, threadFactory);
private static final ClassLogger logger =
new ClassLogger("javax.management.event", "LeaseManager");
}

View File

@ -1,143 +0,0 @@
/*
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.event;
import com.sun.jmx.remote.util.ClassLogger;
import java.util.concurrent.Callable;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
/**
*
* @author sjiang
*/
public class LeaseRenewer {
public LeaseRenewer(ScheduledExecutorService scheduler, Callable<Long> doRenew) {
if (logger.traceOn()) {
logger.trace("LeaseRenewer", "New LeaseRenewer.");
}
if (doRenew == null) {
throw new NullPointerException("Null job to call server.");
}
this.doRenew = doRenew;
nextRenewTime = System.currentTimeMillis();
this.scheduler = scheduler;
future = this.scheduler.schedule(myRenew, 0, TimeUnit.MILLISECONDS);
}
public void close() {
if (logger.traceOn()) {
logger.trace("close", "Close the lease.");
}
synchronized(lock) {
if (closed) {
return;
} else {
closed = true;
}
}
try {
future.cancel(false); // not interrupt if running
} catch (Exception e) {
// OK
if (logger.debugOn()) {
logger.debug("close", "Failed to cancel the leasing job.", e);
}
}
}
public boolean closed() {
synchronized(lock) {
return closed;
}
}
// ------------------------------
// private
// ------------------------------
private final Runnable myRenew = new Runnable() {
public void run() {
synchronized(lock) {
if (closed()) {
return;
}
}
long next = nextRenewTime - System.currentTimeMillis();
if (next < MIN_MILLIS) {
try {
if (logger.traceOn()) {
logger.trace("myRenew-run", "");
}
next = doRenew.call().longValue();
} catch (Exception e) {
logger.fine("myRenew-run", "Failed to renew lease", e);
close();
}
if (next > 0 && next < Long.MAX_VALUE) {
next = next/2;
next = (next < MIN_MILLIS) ? MIN_MILLIS : next;
} else {
close();
}
}
nextRenewTime = System.currentTimeMillis() + next;
if (logger.traceOn()) {
logger.trace("myRenew-run", "Next leasing: "+next);
}
synchronized(lock) {
if (!closed) {
future = scheduler.schedule(this, next, TimeUnit.MILLISECONDS);
}
}
}
};
private final Callable<Long> doRenew;
private ScheduledFuture<?> future;
private boolean closed = false;
private long nextRenewTime;
private final int[] lock = new int[0];
private final ScheduledExecutorService scheduler;
private static final long MIN_MILLIS = 50;
private static final ClassLogger logger =
new ClassLogger("javax.management.event", "LeaseRenewer");
}

View File

@ -1,97 +0,0 @@
/*
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.event;
import com.sun.jmx.remote.util.ClassLogger;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.management.remote.NotificationResult;
import javax.management.remote.TargetedNotification;
public class ReceiverBuffer {
public void addNotifs(NotificationResult nr) {
if (nr == null) {
return;
}
TargetedNotification[] tns = nr.getTargetedNotifications();
if (logger.traceOn()) {
logger.trace("addNotifs", "" + tns.length);
}
long impliedStart = nr.getEarliestSequenceNumber();
final long missed = impliedStart - start;
start = nr.getNextSequenceNumber();
if (missed > 0) {
if (logger.traceOn()) {
logger.trace("addNotifs",
"lost: "+missed);
}
lost += missed;
}
Collections.addAll(notifList, nr.getTargetedNotifications());
}
public TargetedNotification[] removeNotifs() {
if (logger.traceOn()) {
logger.trace("removeNotifs", String.valueOf(notifList.size()));
}
if (notifList.size() == 0) {
return null;
}
TargetedNotification[] ret = notifList.toArray(
new TargetedNotification[]{});
notifList.clear();
return ret;
}
public int size() {
return notifList.size();
}
public int removeLost() {
int ret = lost;
lost = 0;
return ret;
}
private List<TargetedNotification> notifList
= new ArrayList<TargetedNotification>();
private long start = 0;
private int lost = 0;
private static final ClassLogger logger =
new ClassLogger("javax.management.event", "ReceiverBuffer");
}

View File

@ -1,119 +0,0 @@
/*
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.event;
import com.sun.jmx.remote.util.ClassLogger;
import java.util.concurrent.Executor;
import java.util.concurrent.RejectedExecutionException;
/**
* <p>A task that is repeatedly run by an Executor. The task will be
* repeated as long as the {@link #isSuspended()} method returns true. Once
* that method returns false, the task is no longer executed until someone
* calls {@link #resume()}.</p>
* @author sjiang
*/
public abstract class RepeatedSingletonJob implements Runnable {
public RepeatedSingletonJob(Executor executor) {
if (executor == null) {
throw new NullPointerException("Null executor!");
}
this.executor = executor;
}
public boolean isWorking() {
return working;
}
public void resume() {
synchronized(this) {
if (!working) {
if (logger.traceOn()) {
logger.trace("resume", "");
}
working = true;
execute();
}
}
}
public abstract void task();
public abstract boolean isSuspended();
public void run() {
if (logger.traceOn()) {
logger.trace("run", "execute the task");
}
try {
task();
} catch (Exception e) {
// A correct task() implementation should not throw exceptions.
// It may cause isSuspended() to start returning true, though.
logger.trace("run", "failed to execute the task", e);
}
synchronized(this) {
if (!isSuspended()) {
execute();
} else {
if (logger.traceOn()) {
logger.trace("run", "suspend the task");
}
working = false;
}
}
}
private void execute() {
try {
executor.execute(this);
} catch (RejectedExecutionException e) {
logger.warning(
"execute",
"Executor threw exception (" + this.getClass().getName() + ")",
e);
throw new RejectedExecutionException(
"Executor.execute threw exception -" +
"should not be possible", e);
// User-supplied Executor should not be configured in a way that
// might cause this exception, for example if it is shared between
// several client objects and doesn't have capacity for one job
// from each one. CR 6732037 will add text to the spec explaining
// the problem. The rethrown exception will propagate either out
// of resume() to user code, or out of run() to the Executor
// (which will probably ignore it).
}
}
private boolean working = false;
private final Executor executor;
private static final ClassLogger logger =
new ClassLogger("javax.management.event", "RepeatedSingletonJob");
}

View File

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

View File

@ -1,551 +0,0 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.interceptor;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.InvalidAttributeValueException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.QueryExp;
import javax.management.ReflectionException;
import javax.management.namespace.JMXNamespace;
/**
* A dispatcher that dispatches to MBeanServers.
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
* @since 1.7
*/
//
// This is the base class for implementing dispatchers. We have two concrete
// dispatcher implementations:
//
// * A NamespaceDispatchInterceptor, which dispatch calls to existing
// namespace interceptors
// * A DomainDispatchInterceptor, which dispatch calls to existing domain
// interceptors.
//
// With the JMX Namespaces feature, the JMX MBeanServer is now structured
// as follows:
//
// The JMX MBeanServer delegates to a NamespaceDispatchInterceptor,
// which either dispatches to a namespace, or delegates to the
// DomainDispatchInterceptor (if the object name contained no namespace).
// The DomainDispatchInterceptor in turn either dispatches to a domain (if
// there is a JMXDomain for that domain) or delegates to the
// DefaultMBeanServerInterceptor (if there is no JMXDomain for that
// domain). This makes the following picture:
//
// JMX MBeanServer (outer shell)
// |
// |
// NamespaceDispatchInterceptor
// / \
// no namespace in object name? \
// / \
// / dispatch to namespace
// DomainDispatchInterceptor
// / \
// no JMXDomain for domain? \
// / \
// / dispatch to domain
// DefaultMBeanServerInterceptor
// /
// invoke locally registered MBean
//
// The logic for maintaining a map of interceptors
// and dispatching to impacted interceptor, is implemented in this
// base class, which both NamespaceDispatchInterceptor and
// DomainDispatchInterceptor extend.
//
public abstract class DispatchInterceptor
<T extends MBeanServer, N extends JMXNamespace>
extends MBeanServerInterceptorSupport {
/**
* This is an abstraction which allows us to handle queryNames
* and queryMBeans with the same algorithm. There are some subclasses
* where we need to override both queryNames & queryMBeans to apply
* the same transformation (usually aggregation of results when
* several namespaces/domains are impacted) to both algorithms.
* Usually the only thing that varies between the algorithm of
* queryNames & the algorithm of queryMBean is the type of objects
* in the returned Set. By using a QueryInvoker we can implement the
* transformation only once and apply it to both queryNames &
* queryMBeans.
* @see QueryInterceptor below, and its subclass in
* {@link DomainDispatcher}.
**/
static abstract class QueryInvoker<T> {
abstract Set<T> query(MBeanServer mbs,
ObjectName pattern, QueryExp query);
}
/**
* Used to perform queryNames. A QueryInvoker that invokes
* queryNames on an MBeanServer.
**/
final static QueryInvoker<ObjectName> queryNamesInvoker =
new QueryInvoker<ObjectName>() {
Set<ObjectName> query(MBeanServer mbs,
ObjectName pattern, QueryExp query) {
return mbs.queryNames(pattern,query);
}
};
/**
* Used to perform queryMBeans. A QueryInvoker that invokes
* queryMBeans on an MBeanServer.
**/
final static QueryInvoker<ObjectInstance> queryMBeansInvoker =
new QueryInvoker<ObjectInstance>() {
Set<ObjectInstance> query(MBeanServer mbs,
ObjectName pattern, QueryExp query) {
return mbs.queryMBeans(pattern,query);
}
};
/**
* We use this class to intercept queries.
* There's a special case for JMXNamespace MBeans, because
* "namespace//*:*" matches both "namespace//domain:k=v" and
* "namespace//:type=JMXNamespace".
* Therefore, queries may need to be forwarded to more than
* on interceptor and the results aggregated...
*/
static class QueryInterceptor {
final MBeanServer wrapped;
QueryInterceptor(MBeanServer mbs) {
wrapped = mbs;
}
<X> Set<X> query(ObjectName pattern, QueryExp query,
QueryInvoker<X> invoker, MBeanServer server) {
return invoker.query(server, pattern, query);
}
public Set<ObjectName> queryNames(ObjectName pattern, QueryExp query) {
return query(pattern,query,queryNamesInvoker,wrapped);
}
public Set<ObjectInstance> queryMBeans(ObjectName pattern,
QueryExp query) {
return query(pattern,query,queryMBeansInvoker,wrapped);
}
}
// We don't need a ConcurrentHashMap here because getkeys() returns
// an array of keys. Therefore there's no risk to have a
// ConcurrentModificationException. We must however take into
// account the fact that there can be no interceptor for
// some of the returned keys if the map is being modified by
// another thread, or by a callback within the same thread...
// See getKeys() in this class and query() in DomainDispatcher.
//
private final Map<String,T> handlerMap =
Collections.synchronizedMap(
new HashMap<String,T>());
// The key at which an interceptor for accessing the named MBean can be
// found in the handlerMap. Note: there doesn't need to be an interceptor
// for that key in the Map.
//
abstract String getHandlerKey(ObjectName name);
// Returns an interceptor for that name, or null if there's no interceptor
// for that name.
abstract MBeanServer getInterceptorOrNullFor(ObjectName name);
// Returns a QueryInterceptor for that pattern.
abstract QueryInterceptor getInterceptorForQuery(ObjectName pattern);
// Returns the ObjectName of the JMXNamespace (or JMXDomain) for that
// key (a namespace or a domain name).
abstract ObjectName getHandlerNameFor(String key);
// Creates an interceptor for the given key, name, JMXNamespace (or
// JMXDomain). Note: this will be either a NamespaceInterceptor
// wrapping a JMXNamespace, if this object is an instance of
// NamespaceDispatchInterceptor, or a DomainInterceptor wrapping a
// JMXDomain, if this object is an instance of DomainDispatchInterceptor.
abstract T createInterceptorFor(String key, ObjectName name,
N jmxNamespace, Queue<Runnable> postRegisterQueue);
//
// The next interceptor in the chain.
//
// For the NamespaceDispatchInterceptor, this the DomainDispatchInterceptor.
// For the DomainDispatchInterceptor, this is the
// DefaultMBeanServerInterceptor.
//
// The logic of when to invoke the next interceptor in the chain depends
// on the logic of the concrete dispatcher class.
//
// For instance, the NamespaceDispatchInterceptor invokes the next
// interceptor when the object name doesn't contain any namespace.
//
// On the other hand, the DomainDispatchInterceptor invokes the
// next interceptor when there's no interceptor for the accessed domain.
//
abstract MBeanServer getNextInterceptor();
// hook for cleanup in subclasses.
void interceptorReleased(T interceptor,
Queue<Runnable> postDeregisterQueue) {
// hook
}
// Hook for subclasses.
MBeanServer getInterceptorForCreate(ObjectName name)
throws MBeanRegistrationException {
final MBeanServer ns = getInterceptorOrNullFor(name);
if (ns == null) // name cannot be null here.
throw new MBeanRegistrationException(
new IllegalArgumentException("No such MBean handler: " +
getHandlerKey(name) + " for " +name));
return ns;
}
// Hook for subclasses.
MBeanServer getInterceptorForInstance(ObjectName name)
throws InstanceNotFoundException {
final MBeanServer ns = getInterceptorOrNullFor(name);
if (ns == null) // name cannot be null here.
throw new InstanceNotFoundException(String.valueOf(name));
return ns;
}
// sanity checks
void validateHandlerNameFor(String key, ObjectName name) {
if (key == null || key.equals(""))
throw new IllegalArgumentException("invalid key for "+name+": "+key);
final ObjectName handlerName = getHandlerNameFor(key);
if (!name.equals(handlerName))
throw new IllegalArgumentException("bad handler name: "+name+
". Should be: "+handlerName);
}
// Called by the DefaultMBeanServerInterceptor when an instance
// of JMXNamespace (or a subclass of it) is registered as an MBean.
// This method is usually invoked from within the repository lock,
// hence the necessity of the postRegisterQueue.
public void addInterceptorFor(ObjectName name, N jmxNamespace,
Queue<Runnable> postRegisterQueue) {
final String key = getHandlerKey(name);
validateHandlerNameFor(key,name);
synchronized (handlerMap) {
final T exists =
handlerMap.get(key);
if (exists != null)
throw new IllegalArgumentException(key+
": handler already exists");
final T ns = createInterceptorFor(key,name,jmxNamespace,
postRegisterQueue);
handlerMap.put(key,ns);
}
}
// Called by the DefaultMBeanServerInterceptor when an instance
// of JMXNamespace (or a subclass of it) is deregistered.
// This method is usually invoked from within the repository lock,
// hence the necessity of the postDeregisterQueue.
public void removeInterceptorFor(ObjectName name, N jmxNamespace,
Queue<Runnable> postDeregisterQueue) {
final String key = getHandlerKey(name);
final T ns;
synchronized(handlerMap) {
ns = handlerMap.remove(key);
}
interceptorReleased(ns,postDeregisterQueue);
}
// Get the interceptor for that key.
T getInterceptor(String key) {
synchronized (handlerMap) {
return handlerMap.get(key);
}
}
// We return an array of keys, which makes it possible to make
// concurrent modifications of the handlerMap, provided that
// the code which loops over the keys is prepared to handle null
// interceptors.
// See declaration of handlerMap above, and see also query() in
// DomainDispatcher
//
public String[] getKeys() {
synchronized (handlerMap) {
final int size = handlerMap.size();
return handlerMap.keySet().toArray(new String[size]);
}
}
// From MBeanServer
public final ObjectInstance createMBean(String className, ObjectName name)
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException {
return getInterceptorForCreate(name).createMBean(className,name);
}
// From MBeanServer
public final ObjectInstance createMBean(String className, ObjectName name,
ObjectName loaderName)
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, InstanceNotFoundException{
return getInterceptorForCreate(name).createMBean(className,name,loaderName);
}
// From MBeanServer
public final ObjectInstance createMBean(String className, ObjectName name,
Object params[], String signature[])
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException{
return getInterceptorForCreate(name).
createMBean(className,name,params,signature);
}
// From MBeanServer
public final ObjectInstance createMBean(String className, ObjectName name,
ObjectName loaderName, Object params[],
String signature[])
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, InstanceNotFoundException{
return getInterceptorForCreate(name).createMBean(className,name,loaderName,
params,signature);
}
// From MBeanServer
public final ObjectInstance registerMBean(Object object, ObjectName name)
throws InstanceAlreadyExistsException, MBeanRegistrationException,
NotCompliantMBeanException {
return getInterceptorForCreate(name).registerMBean(object,name);
}
// From MBeanServer
public final void unregisterMBean(ObjectName name)
throws InstanceNotFoundException, MBeanRegistrationException {
getInterceptorForInstance(name).unregisterMBean(name);
}
// From MBeanServer
public final ObjectInstance getObjectInstance(ObjectName name)
throws InstanceNotFoundException {
return getInterceptorForInstance(name).getObjectInstance(name);
}
// From MBeanServer
public final Set<ObjectInstance> queryMBeans(ObjectName name,
QueryExp query) {
final QueryInterceptor queryInvoker =
getInterceptorForQuery(name);
if (queryInvoker == null) return Collections.emptySet();
else return queryInvoker.queryMBeans(name,query);
}
// From MBeanServer
public final Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
final QueryInterceptor queryInvoker =
getInterceptorForQuery(name);
if (queryInvoker == null) return Collections.emptySet();
else return queryInvoker.queryNames(name,query);
}
// From MBeanServer
public final boolean isRegistered(ObjectName name) {
final MBeanServer mbs = getInterceptorOrNullFor(name);
if (mbs == null) return false;
else return mbs.isRegistered(name);
}
// From MBeanServer
public Integer getMBeanCount() {
return getNextInterceptor().getMBeanCount();
}
// From MBeanServer
public final Object getAttribute(ObjectName name, String attribute)
throws MBeanException, AttributeNotFoundException,
InstanceNotFoundException, ReflectionException {
return getInterceptorForInstance(name).getAttribute(name,attribute);
}
// From MBeanServer
public final AttributeList getAttributes(ObjectName name,
String[] attributes)
throws InstanceNotFoundException, ReflectionException {
return getInterceptorForInstance(name).getAttributes(name,attributes);
}
// From MBeanServer
public final void setAttribute(ObjectName name, Attribute attribute)
throws InstanceNotFoundException, AttributeNotFoundException,
InvalidAttributeValueException, MBeanException,
ReflectionException {
getInterceptorForInstance(name).setAttribute(name,attribute);
}
// From MBeanServer
public final AttributeList setAttributes(ObjectName name,
AttributeList attributes)
throws InstanceNotFoundException, ReflectionException {
return getInterceptorForInstance(name).setAttributes(name,attributes);
}
// From MBeanServer
public final Object invoke(ObjectName name, String operationName,
Object params[], String signature[])
throws InstanceNotFoundException, MBeanException,
ReflectionException {
return getInterceptorForInstance(name).invoke(name,operationName,params,
signature);
}
// From MBeanServer
public String getDefaultDomain() {
return getNextInterceptor().getDefaultDomain();
}
/**
* Returns the list of domains in which any MBean is currently
* registered.
*/
public abstract String[] getDomains();
// From MBeanServer
public final void addNotificationListener(ObjectName name,
NotificationListener listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException {
getInterceptorForInstance(name).
addNotificationListener(name,listener,filter,
handback);
}
// From MBeanServer
public final void addNotificationListener(ObjectName name,
ObjectName listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException {
getInterceptorForInstance(name).
addNotificationListener(name,listener,filter,
handback);
}
// From MBeanServer
public final void removeNotificationListener(ObjectName name,
ObjectName listener)
throws InstanceNotFoundException, ListenerNotFoundException {
getInterceptorForInstance(name).
removeNotificationListener(name,listener);
}
// From MBeanServer
public final void removeNotificationListener(ObjectName name,
ObjectName listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException, ListenerNotFoundException {
getInterceptorForInstance(name).
removeNotificationListener(name,listener,filter,
handback);
}
// From MBeanServer
public final void removeNotificationListener(ObjectName name,
NotificationListener listener)
throws InstanceNotFoundException, ListenerNotFoundException {
getInterceptorForInstance(name).
removeNotificationListener(name,listener);
}
// From MBeanServer
public final void removeNotificationListener(ObjectName name,
NotificationListener listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException, ListenerNotFoundException {
getInterceptorForInstance(name).
removeNotificationListener(name,listener,filter,
handback);
}
// From MBeanServer
public final MBeanInfo getMBeanInfo(ObjectName name)
throws InstanceNotFoundException, IntrospectionException,
ReflectionException {
return getInterceptorForInstance(name).getMBeanInfo(name);
}
// From MBeanServer
public final boolean isInstanceOf(ObjectName name, String className)
throws InstanceNotFoundException {
return getInterceptorForInstance(name).isInstanceOf(name,className);
}
// From MBeanServer
public final ClassLoader getClassLoaderFor(ObjectName mbeanName)
throws InstanceNotFoundException {
return getInterceptorForInstance(mbeanName).
getClassLoaderFor(mbeanName);
}
// From MBeanServer
public final ClassLoader getClassLoader(ObjectName loaderName)
throws InstanceNotFoundException {
return getInterceptorForInstance(loaderName).
getClassLoader(loaderName);
}
}

View File

@ -1,350 +0,0 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.interceptor;
import com.sun.jmx.defaults.JmxProperties;
import com.sun.jmx.mbeanserver.MBeanInstantiator;
import com.sun.jmx.mbeanserver.Repository;
import com.sun.jmx.mbeanserver.Util;
import com.sun.jmx.namespace.DomainInterceptor;
import java.util.Queue;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.MBeanServer;
import javax.management.MBeanServerDelegate;
import javax.management.ObjectName;
import javax.management.QueryExp;
import javax.management.namespace.JMXDomain;
import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR;
/**
* A dispatcher that dispatch incoming MBeanServer requests to
* DomainInterceptors.
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
* @since 1.7
*/
//
// See comments in DispatchInterceptor.
//
class DomainDispatchInterceptor
extends DispatchInterceptor<DomainInterceptor, JMXDomain> {
/**
* A logger for this class.
**/
private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
private static final ObjectName ALL_DOMAINS =
JMXDomain.getDomainObjectName("*");
/**
* A QueryInterceptor that perform & aggregates queries spanning several
* domains.
*/
final static class AggregatingQueryInterceptor extends QueryInterceptor {
private final DomainDispatchInterceptor parent;
AggregatingQueryInterceptor(DomainDispatchInterceptor dispatcher) {
super(dispatcher.nextInterceptor);
parent = dispatcher;
}
/**
* Perform queryNames or queryMBeans, depending on which QueryInvoker
* is passed as argument. This is closures without closures.
**/
@Override
<T> Set<T> query(ObjectName pattern, QueryExp query,
QueryInvoker<T> invoker, MBeanServer localNamespace) {
final Set<T> local = invoker.query(localNamespace, pattern, query);
// Add all matching MBeans from local namespace.
final Set<T> res = Util.cloneSet(local);
if (pattern == null) pattern = ObjectName.WILDCARD;
final boolean all = pattern.getDomain().equals("*");
final String domain = pattern.getDomain();
// If there's no domain pattern, just include the pattern's domain.
// Otherwiae, loop over all virtual domains (parent.getKeys()).
final String[] keys =
(pattern.isDomainPattern() ?
parent.getKeys() : new String[]{domain});
// Add all matching MBeans from each virtual domain
//
for (String key : keys) {
// Only invoke those virtual domain which are selected
// by the domain pattern
//
if (!all && !Util.isDomainSelected(key, domain))
continue;
try {
final MBeanServer mbs = parent.getInterceptor(key);
// mbs can be null if the interceptor was removed
// concurrently...
// See handlerMap and getKeys() in DispatchInterceptor
//
if (mbs == null) continue;
// If the domain is selected, we can replace the pattern
// by the actual domain. This is safer if we want to avoid
// a domain (which could be backed up by an MBeanServer) to
// return names from outside the domain.
// So instead of asking the domain handler for "foo" to
// return all names which match "?o*:type=Bla,*" we're
// going to ask it to return all names which match
// "foo:type=Bla,*"
//
final ObjectName subPattern = pattern.withDomain(key);
res.addAll(invoker.query(mbs, subPattern, query));
} catch (Exception x) {
LOG.finest("Ignoring exception " +
"when attempting to query namespace "+key+": "+x);
continue;
}
}
return res;
}
}
private final DefaultMBeanServerInterceptor nextInterceptor;
private final String mbeanServerName;
private final MBeanServerDelegate delegate;
/**
* Creates a DomainDispatchInterceptor with the specified
* repository instance.
*
* @param outer A pointer to the MBeanServer object that must be
* passed to the MBeans when invoking their
* {@link javax.management.MBeanRegistration} interface.
* @param delegate A pointer to the MBeanServerDelegate associated
* with the new MBeanServer. The new MBeanServer must register
* this MBean in its MBean repository.
* @param instantiator The MBeanInstantiator that will be used to
* instantiate MBeans and take care of class loading issues.
* @param repository The repository to use for this MBeanServer
*/
public DomainDispatchInterceptor(MBeanServer outer,
MBeanServerDelegate delegate,
MBeanInstantiator instantiator,
Repository repository,
NamespaceDispatchInterceptor namespaces) {
nextInterceptor = new DefaultMBeanServerInterceptor(outer,
delegate, instantiator,repository,namespaces);
mbeanServerName = Util.getMBeanServerSecurityName(delegate);
this.delegate = delegate;
}
final boolean isLocalHandlerNameFor(String domain,
ObjectName handlerName) {
if (domain == null) return true;
return handlerName.getDomain().equals(domain) &&
JMXDomain.TYPE_ASSIGNMENT.equals(
handlerName.getKeyPropertyListString());
}
@Override
void validateHandlerNameFor(String key, ObjectName name) {
super.validateHandlerNameFor(key,name);
final String[] domains = nextInterceptor.getDomains();
for (int i=0;i<domains.length;i++) {
if (domains[i].equals(key))
throw new IllegalArgumentException("domain "+key+
" is not empty");
}
}
@Override
final MBeanServer getInterceptorOrNullFor(ObjectName name) {
if (name == null) return nextInterceptor;
final String domain = name.getDomain();
if (domain.endsWith(NAMESPACE_SEPARATOR))
return nextInterceptor; // This can be a namespace handler.
if (domain.contains(NAMESPACE_SEPARATOR))
return null; // shouldn't reach here.
if (isLocalHandlerNameFor(domain,name)) {
// This is the name of a JMXDomain MBean. Return nextInterceptor.
LOG.finer("dispatching to local namespace");
return nextInterceptor;
}
final DomainInterceptor ns = getInterceptor(domain);
if (ns == null) {
// no JMXDomain found for that domain - return nextInterceptor.
if (LOG.isLoggable(Level.FINER)) {
LOG.finer("dispatching to local namespace: " + domain);
}
return getNextInterceptor();
}
if (LOG.isLoggable(Level.FINER)) {
LOG.finer("dispatching to domain: " + domain);
}
return ns;
}
// This method returns true if the given pattern must be evaluated against
// several interceptors. This happens when either:
//
// a) the pattern can select several domains (it's null, or it's a
// domain pattern)
// or b) it's not a domain pattern, but it might select the name of a
// JMXDomain MBean in charge of that domain. Since the JMXDomain
// MBean is located in the nextInterceptor, the pattern might need
// to be evaluated on two interceptors.
//
// 1. When this method returns false, the query is evaluated on a single
// interceptor:
// The interceptor for pattern.getDomain(), if there is one,
// or the next interceptor, if there is none.
//
// 2. When this method returns true, we loop over all the domain
// interceptors:
// in the list, and if the domain pattern matches the interceptor domain
// we evaluate the query on that interceptor and aggregate the results.
// Eventually we also evaluate the pattern against the next interceptor.
//
// See getInterceptorForQuery below.
//
private boolean multipleQuery(ObjectName pattern) {
// case a) above
if (pattern == null) return true;
if (pattern.isDomainPattern()) return true;
// case b) above.
//
// This is a bit of a hack. If there's any chance that a JMXDomain
// MBean name is selected by the given pattern then we must include
// the local namespace in our search.
//
// Returning true will have this effect. see 2. above.
//
if (pattern.apply(ALL_DOMAINS.withDomain(pattern.getDomain())))
return true;
return false;
}
@Override
final QueryInterceptor getInterceptorForQuery(ObjectName pattern) {
// Check if we need to aggregate.
if (multipleQuery(pattern))
return new AggregatingQueryInterceptor(this);
// We don't need to aggregate: do the "simple" thing...
final String domain = pattern.getDomain();
// Do we have a virtual domain?
final DomainInterceptor ns = getInterceptor(domain);
if (ns != null) {
if (LOG.isLoggable(Level.FINER))
LOG.finer("dispatching to domain: " + domain);
return new QueryInterceptor(ns);
}
// We don't have a virtual domain. Send to local domains.
if (LOG.isLoggable(Level.FINER))
LOG.finer("dispatching to local namespace: " + domain);
return new QueryInterceptor(nextInterceptor);
}
@Override
final ObjectName getHandlerNameFor(String key) {
return JMXDomain.getDomainObjectName(key);
}
@Override
final public String getHandlerKey(ObjectName name) {
return name.getDomain();
}
@Override
final DomainInterceptor createInterceptorFor(String key,
ObjectName name, JMXDomain handler,
Queue<Runnable> postRegisterQueue) {
final DomainInterceptor ns =
new DomainInterceptor(mbeanServerName,handler,key);
ns.addPostRegisterTask(postRegisterQueue, delegate);
if (LOG.isLoggable(Level.FINER)) {
LOG.finer("DomainInterceptor created: "+ns);
}
return ns;
}
@Override
final void interceptorReleased(DomainInterceptor interceptor,
Queue<Runnable> postDeregisterQueue) {
interceptor.addPostDeregisterTask(postDeregisterQueue, delegate);
}
@Override
final DefaultMBeanServerInterceptor getNextInterceptor() {
return nextInterceptor;
}
/**
* Returns the list of domains in which any MBean is currently
* registered.
*/
@Override
public String[] getDomains() {
// A JMXDomain is registered in its own domain.
// Therefore, nextInterceptor.getDomains() contains all domains.
// In addition, nextInterceptor will perform the necessary
// MBeanPermission checks for getDomains().
//
return nextInterceptor.getDomains();
}
/**
* Returns the number of MBeans registered in the MBean server.
*/
@Override
public Integer getMBeanCount() {
int count = getNextInterceptor().getMBeanCount();
final String[] keys = getKeys();
for (String key:keys) {
final MBeanServer mbs = getInterceptor(key);
if (mbs == null) continue;
count += mbs.getMBeanCount();
}
return count;
}
}

View File

@ -1,127 +0,0 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.interceptor;
import java.io.ObjectInputStream;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.ObjectName;
import javax.management.OperationsException;
import javax.management.ReflectionException;
import javax.management.loading.ClassLoaderRepository;
/**
* An abstract class for MBeanServerInterceptorSupport.
* Some methods in MBeanServerInterceptor should never be called.
* This base class provides an implementation of these methods that simply
* throw an {@link UnsupportedOperationException}.
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
* @since 1.7
*/
public abstract class MBeanServerInterceptorSupport
implements MBeanServerInterceptor {
/**
* This method should never be called.
* Throws UnsupportedOperationException.
*/
public Object instantiate(String className)
throws ReflectionException, MBeanException {
throw new UnsupportedOperationException("Not applicable.");
}
/**
* This method should never be called.
* Throws UnsupportedOperationException.
*/
public Object instantiate(String className, ObjectName loaderName)
throws ReflectionException, MBeanException,
InstanceNotFoundException {
throw new UnsupportedOperationException("Not applicable.");
}
/**
* This method should never be called.
* Throws UnsupportedOperationException.
*/
public Object instantiate(String className, Object[] params,
String[] signature) throws ReflectionException, MBeanException {
throw new UnsupportedOperationException("Not applicable.");
}
/**
* This method should never be called.
* Throws UnsupportedOperationException.
*/
public Object instantiate(String className, ObjectName loaderName,
Object[] params, String[] signature)
throws ReflectionException, MBeanException,
InstanceNotFoundException {
throw new UnsupportedOperationException("Not applicable.");
}
/**
* This method should never be called.
* Throws UnsupportedOperationException.
*/
@Deprecated
public ObjectInputStream deserialize(ObjectName name, byte[] data)
throws InstanceNotFoundException, OperationsException {
throw new UnsupportedOperationException("Not applicable.");
}
/**
* This method should never be called.
* Throws UnsupportedOperationException.
*/
@Deprecated
public ObjectInputStream deserialize(String className, byte[] data)
throws OperationsException, ReflectionException {
throw new UnsupportedOperationException("Not applicable.");
}
/**
* This method should never be called.
* Throws UnsupportedOperationException.
*/
@Deprecated
public ObjectInputStream deserialize(String className,
ObjectName loaderName, byte[] data)
throws InstanceNotFoundException, OperationsException,
ReflectionException {
throw new UnsupportedOperationException("Not applicable.");
}
/**
* This method should never be called.
* Throws UnsupportedOperationException.
*/
public ClassLoaderRepository getClassLoaderRepository() {
throw new UnsupportedOperationException("Not applicable.");
}
}

View File

@ -1,297 +0,0 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.interceptor;
import com.sun.jmx.defaults.JmxProperties;
import com.sun.jmx.mbeanserver.MBeanInstantiator;
import com.sun.jmx.mbeanserver.Repository;
import com.sun.jmx.mbeanserver.Util;
import com.sun.jmx.namespace.NamespaceInterceptor;
import java.util.Queue;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.MBeanServer;
import javax.management.MBeanServerDelegate;
import javax.management.ObjectName;
import javax.management.RuntimeOperationsException;
import javax.management.namespace.JMXDomain;
import javax.management.namespace.JMXNamespace;
import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR;
/**
* A dispatcher that dispatches to NamespaceInterceptors.
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
* @since 1.7
*/
public class NamespaceDispatchInterceptor
extends DispatchInterceptor<NamespaceInterceptor, JMXNamespace> {
/**
* A logger for this class.
**/
private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
private static final int NAMESPACE_SEPARATOR_LENGTH =
NAMESPACE_SEPARATOR.length();
private static final ObjectName X3 = ObjectName.valueOf("x:x=x");
private final DomainDispatchInterceptor nextInterceptor;
private final String serverName;
/**
* Creates a NamespaceDispatchInterceptor with the specified
* repository instance.
* <p>Do not forget to call <code>initialize(outer,delegate)</code>
* before using this object.
*
* @param outer A pointer to the MBeanServer object that must be
* passed to the MBeans when invoking their
* {@link javax.management.MBeanRegistration} interface.
* @param delegate A pointer to the MBeanServerDelegate associated
* with the new MBeanServer. The new MBeanServer must register
* this MBean in its MBean repository.
* @param instantiator The MBeanInstantiator that will be used to
* instantiate MBeans and take care of class loading issues.
* @param repository The repository to use for this MBeanServer
*/
public NamespaceDispatchInterceptor(MBeanServer outer,
MBeanServerDelegate delegate,
MBeanInstantiator instantiator,
Repository repository) {
nextInterceptor = new DomainDispatchInterceptor(outer,delegate,
instantiator,repository,this);
serverName = Util.getMBeanServerSecurityName(delegate);
}
/**
* Get first name space in ObjectName path. Ignore leading namespace
* separators. Includes the trailing //.
*
* Examples:
* <pre>
* For ObjectName: Returns:
* foo//bar//baz:x=x -> "foo//"
* foo//:type=JMXNamespace -> "foo//"
* foo//:x=x -> "foo//"
* foo////:x=x -> "foo//"
* //foo//bar//baz:x=x -> "//"
* ////foo//bar//baz:x=x -> "//"
* //:x=x -> "//"
* foo:x=x -> ""
* (null) -> ""
* :x=x -> ""
*
* </pre>
**/
static String getFirstNamespaceWithSlash(ObjectName name) {
if (name == null) return "";
final String domain = name.getDomain();
if (domain.equals("")) return "";
// go to next separator
final int end = domain.indexOf(NAMESPACE_SEPARATOR);
if (end == -1) return ""; // no namespace
// This is the first element in the namespace path.
final String namespace =
domain.substring(0,end+NAMESPACE_SEPARATOR_LENGTH);
return namespace;
}
/**
* Called by the DefaultMBeanServerInterceptor, just before adding an
* MBean to the repository.
*
* @param resource the MBean to be registered.
* @param logicalName the name of the MBean to be registered.
*/
final void checkLocallyRegistrable(Object resource,
ObjectName logicalName) {
if (!(resource instanceof JMXNamespace) &&
logicalName.getDomain().contains(NAMESPACE_SEPARATOR))
throw new IllegalArgumentException(String.valueOf(logicalName)+
": Invalid ObjectName for an instance of " +
resource.getClass().getName());
}
// Removes the trailing //. namespaceWithSlash should be either
// "" or a namespace path ending with //.
//
private final String getKeyFor(String namespaceWithSlash) {
final int end = namespaceWithSlash.length() -
NAMESPACE_SEPARATOR_LENGTH;
if (end <= 0) return "";
final String key = namespaceWithSlash.substring(0,end);
return key;
}
@Override
final MBeanServer getInterceptorOrNullFor(ObjectName name) {
final String namespace = getFirstNamespaceWithSlash(name);
// Leading separators should trigger instance not found exception.
// returning null here has this effect.
//
if (namespace.equals(NAMESPACE_SEPARATOR)) {
LOG.finer("ObjectName starts with: "+namespace);
return null;
}
// namespace="" means that there was no namespace path in the
// ObjectName. => delegate to the next interceptor (local MBS)
// name.getDomain()=namespace means that we have an ObjectName of
// the form blah//:x=x. This is either a JMXNamespace or a non
// existent MBean. => delegate to the next interceptor (local MBS)
if (namespace.equals("") || name.getDomain().equals(namespace)) {
LOG.finer("dispatching to local name space");
return nextInterceptor;
}
// There was a namespace path in the ObjectName. Returns the
// interceptor that handles it, or null if there is no such
// interceptor.
final String key = getKeyFor(namespace);
final NamespaceInterceptor ns = getInterceptor(key);
if (LOG.isLoggable(Level.FINER)) {
if (ns != null) {
LOG.finer("dispatching to name space: " + key);
} else {
LOG.finer("no handler for: " + key);
}
}
return ns;
}
@Override
final QueryInterceptor getInterceptorForQuery(ObjectName pattern) {
final String namespace = getFirstNamespaceWithSlash(pattern);
// Leading separators should trigger instance not found exception.
// returning null here has this effect.
//
if (namespace.equals(NAMESPACE_SEPARATOR)) {
LOG.finer("ObjectName starts with: "+namespace);
return null;
}
// namespace="" means that there was no namespace path in the
// ObjectName. => delegate to the next interceptor (local MBS)
// name.getDomain()=namespace means that we have an ObjectName of
// the form blah//:x=x. This is either a JMXNamespace or a non
// existent MBean. => delegate to the next interceptor (local MBS)
if (namespace.equals("") || pattern.getDomain().equals(namespace)) {
LOG.finer("dispatching to local name space");
return new QueryInterceptor(nextInterceptor);
}
// This is a 'hack' to check whether the first namespace is a pattern.
// We wan to throw RTOE wrapping IAE in that case
if (X3.withDomain(namespace).isDomainPattern()) {
throw new RuntimeOperationsException(
new IllegalArgumentException("Pattern not allowed in namespace path"));
}
// There was a namespace path in the ObjectName. Returns the
// interceptor that handles it, or null if there is no such
// interceptor.
//
final String key = getKeyFor(namespace);
final NamespaceInterceptor ns = getInterceptor(key);
if (LOG.isLoggable(Level.FINER)) {
if (ns != null) {
LOG.finer("dispatching to name space: " + key);
} else {
LOG.finer("no handler for: " + key);
}
}
if (ns == null) return null;
return new QueryInterceptor(ns);
}
@Override
final ObjectName getHandlerNameFor(String key) {
return ObjectName.valueOf(key+NAMESPACE_SEPARATOR,
"type", JMXNamespace.TYPE);
}
@Override
final public String getHandlerKey(ObjectName name) {
final String namespace = getFirstNamespaceWithSlash(name);
// namespace is either "" or a namespace ending with //
return getKeyFor(namespace);
}
@Override
final NamespaceInterceptor createInterceptorFor(String key,
ObjectName name, JMXNamespace handler,
Queue<Runnable> postRegisterQueue) {
final NamespaceInterceptor ns =
new NamespaceInterceptor(serverName,handler,key);
if (LOG.isLoggable(Level.FINER)) {
LOG.finer("NamespaceInterceptor created: "+ns);
}
return ns;
}
@Override
final DomainDispatchInterceptor getNextInterceptor() {
return nextInterceptor;
}
/**
* Returns the list of domains in which any MBean is currently
* registered.
*/
@Override
public String[] getDomains() {
return nextInterceptor.getDomains();
}
@Override
public void addInterceptorFor(ObjectName name, JMXNamespace handler,
Queue<Runnable> postRegisterQueue) {
if (handler instanceof JMXDomain)
nextInterceptor.addInterceptorFor(name,
(JMXDomain)handler,postRegisterQueue);
else super.addInterceptorFor(name,handler,postRegisterQueue);
}
@Override
public void removeInterceptorFor(ObjectName name, JMXNamespace handler,
Queue<Runnable> postDeregisterQueue) {
if (handler instanceof JMXDomain)
nextInterceptor.removeInterceptorFor(name,(JMXDomain)handler,
postDeregisterQueue);
else super.removeInterceptorFor(name,handler,postDeregisterQueue);
}
}

View File

@ -1,442 +0,0 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.interceptor;
import com.sun.jmx.mbeanserver.Util;
import java.util.Arrays;
import java.util.Collections;
import java.util.Set;
import java.util.TreeSet;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.DynamicMBean;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.InvalidAttributeValueException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
import javax.management.NotificationEmitter;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.QueryExp;
import javax.management.ReflectionException;
import javax.management.namespace.JMXNamespaces;
import javax.management.namespace.MBeanServerSupport;
import javax.management.remote.IdentityMBeanServerForwarder;
/**
* <p>An {@link MBeanServerForwarder} that simulates the existence of a
* given MBean. Requests for that MBean, call it X, are intercepted by the
* forwarder, and requests for any other MBean are forwarded to the next
* forwarder in the chain. Requests such as queryNames which can span both the
* X and other MBeans are handled by merging the results for X with the results
* from the next forwarder, unless the "visible" parameter is false, in which
* case X is invisible to such requests.</p>
*/
public class SingleMBeanForwarder extends IdentityMBeanServerForwarder {
private final ObjectName mbeanName;
private final boolean visible;
private DynamicMBean mbean;
private MBeanServer mbeanMBS = new MBeanServerSupport() {
@Override
public DynamicMBean getDynamicMBeanFor(ObjectName name)
throws InstanceNotFoundException {
if (mbeanName.equals(name)) {
return mbean;
} else {
throw new InstanceNotFoundException(name.toString());
}
}
@Override
protected Set<ObjectName> getNames() {
return Collections.singleton(mbeanName);
}
@Override
public NotificationEmitter getNotificationEmitterFor(
ObjectName name) {
if (mbean instanceof NotificationEmitter)
return (NotificationEmitter) mbean;
return null;
}
// This will only be called if mbeanName has an empty domain.
// In that case a getAttribute (e.g.) of that name will have the
// domain replaced by MBeanServerSupport with the default domain,
// so we must be sure that the default domain is empty too.
@Override
public String getDefaultDomain() {
return mbeanName.getDomain();
}
};
public SingleMBeanForwarder(
ObjectName mbeanName, DynamicMBean mbean, boolean visible) {
this.mbeanName = mbeanName;
this.visible = visible;
setSingleMBean(mbean);
}
protected void setSingleMBean(DynamicMBean mbean) {
this.mbean = mbean;
}
@Override
public void addNotificationListener(ObjectName name, ObjectName listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException {
if (mbeanName.equals(name))
mbeanMBS.addNotificationListener(name, listener, filter, handback);
else
super.addNotificationListener(name, listener, filter, handback);
}
@Override
public void addNotificationListener(ObjectName name,
NotificationListener listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException {
if (mbeanName.equals(name))
mbeanMBS.addNotificationListener(name, listener, filter, handback);
else
super.addNotificationListener(name, listener, filter, handback);
}
@Override
public ObjectInstance createMBean(String className, ObjectName name,
ObjectName loaderName, Object[] params,
String[] signature)
throws ReflectionException,
InstanceAlreadyExistsException,
MBeanRegistrationException,
MBeanException,
NotCompliantMBeanException,
InstanceNotFoundException {
if (mbeanName.equals(name))
throw new InstanceAlreadyExistsException(mbeanName.toString());
else
return super.createMBean(className, name, loaderName, params, signature);
}
@Override
public ObjectInstance createMBean(String className, ObjectName name,
Object[] params, String[] signature)
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException {
if (mbeanName.equals(name))
throw new InstanceAlreadyExistsException(mbeanName.toString());
return super.createMBean(className, name, params, signature);
}
@Override
public ObjectInstance createMBean(String className, ObjectName name,
ObjectName loaderName)
throws ReflectionException,
InstanceAlreadyExistsException,
MBeanRegistrationException,
MBeanException,
NotCompliantMBeanException,
InstanceNotFoundException {
if (mbeanName.equals(name))
throw new InstanceAlreadyExistsException(mbeanName.toString());
return super.createMBean(className, name, loaderName);
}
@Override
public ObjectInstance createMBean(String className, ObjectName name)
throws ReflectionException,
InstanceAlreadyExistsException,
MBeanRegistrationException,
MBeanException,
NotCompliantMBeanException {
if (mbeanName.equals(name))
throw new InstanceAlreadyExistsException(mbeanName.toString());
return super.createMBean(className, name);
}
@Override
public Object getAttribute(ObjectName name, String attribute)
throws MBeanException,
AttributeNotFoundException,
InstanceNotFoundException,
ReflectionException {
if (mbeanName.equals(name))
return mbeanMBS.getAttribute(name, attribute);
else
return super.getAttribute(name, attribute);
}
@Override
public AttributeList getAttributes(ObjectName name, String[] attributes)
throws InstanceNotFoundException, ReflectionException {
if (mbeanName.equals(name))
return mbeanMBS.getAttributes(name, attributes);
else
return super.getAttributes(name, attributes);
}
@Override
public ClassLoader getClassLoader(ObjectName loaderName)
throws InstanceNotFoundException {
if (mbeanName.equals(loaderName))
return mbeanMBS.getClassLoader(loaderName);
else
return super.getClassLoader(loaderName);
}
@Override
public ClassLoader getClassLoaderFor(ObjectName name)
throws InstanceNotFoundException {
if (mbeanName.equals(name))
return mbeanMBS.getClassLoaderFor(name);
else
return super.getClassLoaderFor(name);
}
@Override
public String[] getDomains() {
String[] domains = super.getDomains();
if (!visible)
return domains;
TreeSet<String> domainSet = new TreeSet<String>(Arrays.asList(domains));
domainSet.add(mbeanName.getDomain());
return domainSet.toArray(new String[domainSet.size()]);
}
@Override
public Integer getMBeanCount() {
Integer count = super.getMBeanCount();
if (visible && !super.isRegistered(mbeanName))
count++;
return count;
}
@Override
public MBeanInfo getMBeanInfo(ObjectName name)
throws InstanceNotFoundException,
IntrospectionException,
ReflectionException {
if (mbeanName.equals(name))
return mbeanMBS.getMBeanInfo(name);
else
return super.getMBeanInfo(name);
}
@Override
public ObjectInstance getObjectInstance(ObjectName name)
throws InstanceNotFoundException {
if (mbeanName.equals(name))
return mbeanMBS.getObjectInstance(name);
else
return super.getObjectInstance(name);
}
@Override
public Object invoke(ObjectName name, String operationName, Object[] params,
String[] signature)
throws InstanceNotFoundException,
MBeanException,
ReflectionException {
if (mbeanName.equals(name))
return mbeanMBS.invoke(name, operationName, params, signature);
else
return super.invoke(name, operationName, params, signature);
}
@Override
public boolean isInstanceOf(ObjectName name, String className)
throws InstanceNotFoundException {
if (mbeanName.equals(name))
return mbeanMBS.isInstanceOf(name, className);
else
return super.isInstanceOf(name, className);
}
@Override
public boolean isRegistered(ObjectName name) {
if (mbeanName.equals(name))
return true;
else
return super.isRegistered(name);
}
/**
* This is a ugly hack. Although jmx.context//*:* matches jmx.context//:*
* queryNames(jmx.context//*:*,null) must not return jmx.context//:*
* @param pattern the pattern to match against. must not be null.
* @return true if mbeanName can be included, false if it must not.
*/
private boolean applies(ObjectName pattern) {
// we know pattern is not null.
if (!visible || !pattern.apply(mbeanName))
return false;
final String dompat = pattern.getDomain();
if (!dompat.contains(JMXNamespaces.NAMESPACE_SEPARATOR))
return true; // We already checked that patterns apply.
if (mbeanName.getDomain().endsWith(JMXNamespaces.NAMESPACE_SEPARATOR)) {
// only matches if pattern ends with //
return dompat.endsWith(JMXNamespaces.NAMESPACE_SEPARATOR);
}
// should not come here, unless mbeanName contains a // in the
// middle of its domain, which would be weird.
// let query on mbeanMBS proceed and take care of that.
//
return true;
}
@Override
public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
Set<ObjectInstance> names = super.queryMBeans(name, query);
if (visible) {
if (name == null || applies(name) ) {
// Don't assume mbs.queryNames returns a writable set.
names = Util.cloneSet(names);
names.addAll(mbeanMBS.queryMBeans(name, query));
}
}
return names;
}
@Override
public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
Set<ObjectName> names = super.queryNames(name, query);
if (visible) {
if (name == null || applies(name)) {
// Don't assume mbs.queryNames returns a writable set.
names = Util.cloneSet(names);
names.addAll(mbeanMBS.queryNames(name, query));
}
}
return names;
}
@Override
public ObjectInstance registerMBean(Object object, ObjectName name)
throws InstanceAlreadyExistsException,
MBeanRegistrationException,
NotCompliantMBeanException {
if (mbeanName.equals(name))
throw new InstanceAlreadyExistsException(mbeanName.toString());
else
return super.registerMBean(object, name);
}
@Override
public void removeNotificationListener(ObjectName name,
NotificationListener listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException,
ListenerNotFoundException {
if (mbeanName.equals(name))
mbeanMBS.removeNotificationListener(name, listener, filter, handback);
else
super.removeNotificationListener(name, listener, filter, handback);
}
@Override
public void removeNotificationListener(ObjectName name,
NotificationListener listener)
throws InstanceNotFoundException, ListenerNotFoundException {
if (mbeanName.equals(name))
mbeanMBS.removeNotificationListener(name, listener);
else
super.removeNotificationListener(name, listener);
}
@Override
public void removeNotificationListener(ObjectName name, ObjectName listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException,
ListenerNotFoundException {
if (mbeanName.equals(name))
mbeanMBS.removeNotificationListener(name, listener, filter, handback);
else
super.removeNotificationListener(name, listener, filter, handback);
}
@Override
public void removeNotificationListener(ObjectName name, ObjectName listener)
throws InstanceNotFoundException, ListenerNotFoundException {
if (mbeanName.equals(name))
mbeanMBS.removeNotificationListener(name, listener);
else
super.removeNotificationListener(name, listener);
}
@Override
public void setAttribute(ObjectName name, Attribute attribute)
throws InstanceNotFoundException,
AttributeNotFoundException,
InvalidAttributeValueException,
MBeanException,
ReflectionException {
if (mbeanName.equals(name))
mbeanMBS.setAttribute(name, attribute);
else
super.setAttribute(name, attribute);
}
@Override
public AttributeList setAttributes(ObjectName name,
AttributeList attributes)
throws InstanceNotFoundException, ReflectionException {
if (mbeanName.equals(name))
return mbeanMBS.setAttributes(name, attributes);
else
return super.setAttributes(name, attributes);
}
@Override
public void unregisterMBean(ObjectName name)
throws InstanceNotFoundException,
MBeanRegistrationException {
if (mbeanName.equals(name))
mbeanMBS.unregisterMBean(name);
else
super.unregisterMBean(name);
}
}

View File

@ -31,15 +31,13 @@ import java.lang.reflect.Type;
import javax.management.Descriptor;
import javax.management.MBeanException;
import javax.management.openmbean.MXBeanMapping;
import javax.management.openmbean.MXBeanMappingFactory;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
final class ConvertingMethod {
static ConvertingMethod from(Method m, MXBeanMappingFactory mappingFactory) {
static ConvertingMethod from(Method m) {
try {
return new ConvertingMethod(m, mappingFactory);
return new ConvertingMethod(m);
} catch (OpenDataException ode) {
final String msg = "Method " + m.getDeclaringClass().getName() +
"." + m.getName() + " has parameter or return type that " +
@ -53,7 +51,7 @@ final class ConvertingMethod {
}
Descriptor getDescriptor() {
return Introspector.descriptorForElement(method, false);
return Introspector.descriptorForElement(method);
}
Type getGenericReturnType() {
@ -206,9 +204,9 @@ final class ConvertingMethod {
return method.getDeclaringClass() + "." + method.getName();
}
private ConvertingMethod(Method m, MXBeanMappingFactory mappingFactory)
throws OpenDataException {
private ConvertingMethod(Method m) throws OpenDataException {
this.method = m;
MXBeanMappingFactory mappingFactory = MXBeanMappingFactory.DEFAULT;
returnMapping =
mappingFactory.mappingForType(m.getGenericReturnType(), mappingFactory);
Type[] params = m.getGenericParameterTypes();

View File

@ -28,8 +28,6 @@ package com.sun.jmx.mbeanserver;
import static com.sun.jmx.mbeanserver.Util.*;
import static com.sun.jmx.mbeanserver.MXBeanIntrospector.typeName;
import javax.management.openmbean.MXBeanMappingClass;
import static javax.management.openmbean.SimpleType.*;
import com.sun.jmx.remote.util.EnvHelp;
@ -69,8 +67,6 @@ import javax.management.openmbean.CompositeDataInvocationHandler;
import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeDataView;
import javax.management.openmbean.CompositeType;
import javax.management.openmbean.MXBeanMapping;
import javax.management.openmbean.MXBeanMappingFactory;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType;
@ -165,34 +161,29 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
private static final class Mappings
extends WeakHashMap<Type, WeakReference<MXBeanMapping>> {}
private static final Map<MXBeanMappingFactory, Mappings> factoryMappings =
new WeakHashMap<MXBeanMappingFactory, Mappings>();
private static final Mappings mappings = new Mappings();
private static final Map<Type, MXBeanMapping> permanentMappings = newMap();
/** Following List simply serves to keep a reference to predefined
MXBeanMappings so they don't get garbage collected. */
private static final List<MXBeanMapping> permanentMappings = newList();
private static synchronized MXBeanMapping getMapping(
Type type, MXBeanMappingFactory factory) {
Mappings mappings = factoryMappings.get(factory);
if (mappings == null) {
mappings = new Mappings();
factoryMappings.put(factory, mappings);
}
private static synchronized MXBeanMapping getMapping(Type type) {
WeakReference<MXBeanMapping> wr = mappings.get(type);
return (wr == null) ? null : wr.get();
}
private static synchronized void putMapping(
Type type, MXBeanMapping mapping, MXBeanMappingFactory factory) {
Mappings mappings = factoryMappings.get(factory);
if (mappings == null) {
mappings = new Mappings();
factoryMappings.put(factory, mappings);
}
private static synchronized void putMapping(Type type, MXBeanMapping mapping) {
WeakReference<MXBeanMapping> wr =
new WeakReference<MXBeanMapping>(mapping);
mappings.put(type, wr);
}
private static synchronized void putPermanentMapping(
Type type, MXBeanMapping mapping) {
putMapping(type, mapping);
permanentMappings.add(mapping);
}
static {
/* Set up the mappings for Java types that map to SimpleType. */
@ -213,7 +204,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
throw new Error(e);
}
final MXBeanMapping mapping = new IdentityMapping(c, t);
permanentMappings.put(c, mapping);
putPermanentMapping(c, mapping);
if (c.getName().startsWith("java.lang.")) {
try {
@ -221,7 +212,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
final Class<?> primitiveType = (Class<?>) typeField.get(null);
final MXBeanMapping primitiveMapping =
new IdentityMapping(primitiveType, t);
permanentMappings.put(primitiveType, primitiveMapping);
putPermanentMapping(primitiveType, primitiveMapping);
if (primitiveType != void.class) {
final Class<?> primitiveArrayType =
Array.newInstance(primitiveType, 0).getClass();
@ -230,8 +221,8 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
final MXBeanMapping primitiveArrayMapping =
new IdentityMapping(primitiveArrayType,
primitiveArrayOpenType);
permanentMappings.put(primitiveArrayType,
primitiveArrayMapping);
putPermanentMapping(primitiveArrayType,
primitiveArrayMapping);
}
} catch (NoSuchFieldException e) {
// OK: must not be a primitive wrapper
@ -255,7 +246,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
MXBeanMapping mapping;
mapping = getMapping(objType, null);
mapping = getMapping(objType);
if (mapping != null)
return mapping;
@ -268,7 +259,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
inProgress.remove(objType);
}
putMapping(objType, mapping, factory);
putMapping(objType, mapping);
return mapping;
}
@ -278,14 +269,6 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
/* It's not yet worth formalizing these tests by having for example
an array of factory classes, each of which says whether it
recognizes the Type (Chain of Responsibility pattern). */
MXBeanMapping mapping = permanentMappings.get(objType);
if (mapping != null)
return mapping;
Class<?> erasure = erasure(objType);
MXBeanMappingClass mappingClass =
erasure.getAnnotation(MXBeanMappingClass.class);
if (mappingClass != null)
return makeAnnotationMapping(mappingClass, objType, factory);
if (objType instanceof GenericArrayType) {
Type componentType =
((GenericArrayType) objType).getGenericComponentType();
@ -313,51 +296,6 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
throw new OpenDataException("Cannot map type: " + objType);
}
private static MXBeanMapping
makeAnnotationMapping(MXBeanMappingClass mappingClass,
Type objType,
MXBeanMappingFactory factory)
throws OpenDataException {
Class<? extends MXBeanMapping> c = mappingClass.value();
Constructor<? extends MXBeanMapping> cons;
try {
cons = c.getConstructor(Type.class);
} catch (NoSuchMethodException e) {
final String msg =
"Annotation @" + MXBeanMappingClass.class.getName() +
" must name a class with a public constructor that has a " +
"single " + Type.class.getName() + " argument";
OpenDataException ode = new OpenDataException(msg);
ode.initCause(e);
throw ode;
}
try {
return cons.newInstance(objType);
} catch (Exception e) {
final String msg =
"Could not construct a " + c.getName() + " for @" +
MXBeanMappingClass.class.getName();
OpenDataException ode = new OpenDataException(msg);
ode.initCause(e);
throw ode;
}
}
private static Class<?> erasure(Type t) {
if (t instanceof Class<?>)
return (Class<?>) t;
if (t instanceof ParameterizedType)
return erasure(((ParameterizedType) t).getRawType());
/* Other cases: GenericArrayType, TypeVariable, WildcardType.
* Returning the erasure of GenericArrayType is not necessary because
* anyway we will be recursing on the element type, and we'll erase
* then. Returning the erasure of the other two would mean returning
* the type bound (e.g. Foo in <T extends Foo> or <? extends Foo>)
* and since we don't treat this as Foo elsewhere we shouldn't here.
*/
return Object.class;
}
private static <T extends Enum<T>> MXBeanMapping
makeEnumMapping(Class<?> enumClass, Class<T> fake) {
return new EnumMapping<T>(Util.<Class<T>>cast(enumClass));

View File

@ -1,5 +1,5 @@
/*
* Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -25,7 +25,7 @@
package com.sun.jmx.mbeanserver;
import javax.management.DynamicWrapperMBean;
import javax.management.DynamicMBean;
import javax.management.MBeanServer;
import javax.management.ObjectName;
@ -35,7 +35,17 @@ import javax.management.ObjectName;
*
* @since 1.6
*/
public interface DynamicMBean2 extends DynamicWrapperMBean {
public interface DynamicMBean2 extends DynamicMBean {
/**
* The resource corresponding to this MBean. This is the object whose
* class name should be reflected by the MBean's
* getMBeanInfo().getClassName() for example. For a "plain"
* DynamicMBean it will be "this". For an MBean that wraps another
* object, like javax.management.StandardMBean, it will be the wrapped
* object.
*/
public Object getResource();
/**
* The name of this MBean's class, as used by permission checks.
* This is typically equal to getResource().getClass().getName().

View File

@ -25,14 +25,9 @@
package com.sun.jmx.mbeanserver;
import com.sun.jmx.remote.util.EnvHelp;
import java.beans.BeanInfo;
import java.beans.PropertyDescriptor;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy;
@ -40,39 +35,21 @@ import java.lang.reflect.UndeclaredThrowableException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.Level;
import javax.management.AttributeNotFoundException;
import javax.management.Description;
import javax.management.Descriptor;
import javax.management.DescriptorFields;
import javax.management.DescriptorKey;
import javax.management.DynamicMBean;
import javax.management.ImmutableDescriptor;
import javax.management.MBean;
import javax.management.MBeanInfo;
import javax.management.MXBean;
import javax.management.NotCompliantMBeanException;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.MXBeanMappingFactory;
import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
import com.sun.jmx.mbeanserver.Util;
import com.sun.jmx.remote.util.EnvHelp;
import java.beans.BeanInfo;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException;
import java.util.LinkedHashSet;
import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.management.AttributeNotFoundException;
import javax.management.JMX;
import javax.management.ObjectName;
import javax.management.ObjectNameTemplate;
import javax.management.openmbean.CompositeData;
import javax.management.openmbean.MXBeanMappingFactory;
/**
* This class contains the methods for performing all the tests needed to verify
@ -82,13 +59,7 @@ import javax.management.openmbean.MXBeanMappingFactory;
*/
public class Introspector {
/**
* Pattern used to extract Attribute Names from ObjectNameTemplate Annotation
* For example, in the following example, the Name attribute value is
* retrieved : ":type=MyType, name={Name}"
*/
private static Pattern OBJECT_NAME_PATTERN_TEMPLATE =
Pattern.compile("(\\{[^\\}]+\\})|(=\"\\{[^\\}]+\\}\")");
/*
* ------------------------------------------
* PRIVATE CONSTRUCTORS
@ -164,10 +135,6 @@ public class Introspector {
public static void checkCompliance(Class<?> mbeanClass)
throws NotCompliantMBeanException {
// Check that @Resource is used correctly (if it used).
MBeanInjector.validate(mbeanClass);
// Is DynamicMBean?
//
if (DynamicMBean.class.isAssignableFrom(mbeanClass))
@ -190,36 +157,16 @@ public class Introspector {
} catch (NotCompliantMBeanException e) {
mxbeanException = e;
}
// Is @MBean or @MXBean class?
// In fact we find @MBean or @MXBean as a hacky variant of
// getStandardMBeanInterface or getMXBeanInterface. If we get here
// then nothing worked.
final String msg =
"MBean class " + mbeanClass.getName() + " does not implement " +
"DynamicMBean; does not follow the Standard MBean conventions (" +
mbeanException.toString() + "); does not follow the MXBean conventions (" +
mxbeanException.toString() + "); and does not have or inherit the @" +
MBean.class.getSimpleName() + " or @" + MXBean.class.getSimpleName() +
" annotation";
"DynamicMBean, and neither follows the Standard MBean conventions (" +
mbeanException.toString() + ") nor the MXBean conventions (" +
mxbeanException.toString() + ")";
throw new NotCompliantMBeanException(msg);
}
/**
* <p>Make a DynamicMBean out of the existing MBean object. The object
* may already be a DynamicMBean, or it may be a Standard MBean or
* MXBean, possibly defined using {@code @MBean} or {@code @MXBean}.</p>
* @param mbean the object to convert to a DynamicMBean.
* @param <T> a type parameter defined for implementation convenience
* (which would have to be removed if this method were part of the public
* API).
* @return the converted DynamicMBean.
* @throws NotCompliantMBeanException if {@code mbean} is not a compliant
* MBean object, including the case where it is null.
*/
public static <T> DynamicMBean makeDynamicMBean(T mbean)
throws NotCompliantMBeanException {
if (mbean == null)
throw new NotCompliantMBeanException("Null MBean object");
throws NotCompliantMBeanException {
if (mbean instanceof DynamicMBean)
return (DynamicMBean) mbean;
final Class<?> mbeanClass = mbean.getClass();
@ -240,18 +187,8 @@ public class Introspector {
// to be an MBean or an MXBean. We will call checkCompliance()
// to generate the appropriate exception.
}
if (c != null) {
MXBeanMappingFactory factory;
try {
factory = MXBeanMappingFactory.forInterface(c);
} catch (IllegalArgumentException e) {
NotCompliantMBeanException ncmbe =
new NotCompliantMBeanException(e.getMessage());
ncmbe.initCause(e);
throw ncmbe;
}
return new MXBeanSupport(mbean, c, factory);
}
if (c != null)
return new MXBeanSupport(mbean, c);
checkCompliance(mbeanClass);
throw new NotCompliantMBeanException("Not compliant"); // not reached
}
@ -280,10 +217,9 @@ public class Introspector {
return testCompliance(baseClass, null);
}
public static void testComplianceMXBeanInterface(Class<?> interfaceClass,
MXBeanMappingFactory factory)
public static void testComplianceMXBeanInterface(Class<?> interfaceClass)
throws NotCompliantMBeanException {
MXBeanIntrospector.getInstance(factory).getAnalyzer(interfaceClass);
MXBeanIntrospector.getInstance().getAnalyzer(interfaceClass);
}
/**
@ -352,8 +288,6 @@ public class Introspector {
*/
public static <T> Class<? super T> getStandardMBeanInterface(Class<T> baseClass)
throws NotCompliantMBeanException {
if (baseClass.isAnnotationPresent(MBean.class))
return baseClass;
Class<? super T> current = baseClass;
Class<? super T> mbeanInterface = null;
while (current != null) {
@ -384,8 +318,6 @@ public class Introspector {
*/
public static <T> Class<? super T> getMXBeanInterface(Class<T> baseClass)
throws NotCompliantMBeanException {
if (hasMXBeanAnnotation(baseClass))
return baseClass;
try {
return MXBeanSupport.findMXBeanInterface(baseClass);
} catch (Exception e) {
@ -393,61 +325,12 @@ public class Introspector {
}
}
public static <T> Class<? super T> getStandardOrMXBeanInterface(
Class<T> baseClass, boolean mxbean)
throws NotCompliantMBeanException {
if (mxbean)
return getMXBeanInterface(baseClass);
else
return getStandardMBeanInterface(baseClass);
}
public static ObjectName templateToObjectName(Descriptor descriptor,
DynamicMBean mbean)
throws NotCompliantMBeanException {
String template = (String)
descriptor.getFieldValue(JMX.OBJECT_NAME_TEMPLATE);
if(template == null) return null;
try {
Matcher m = OBJECT_NAME_PATTERN_TEMPLATE.matcher(template);
while (m.find()){
String grp = m.group();
System.out.println("GROUP " + grp);
String attributeName = null;
boolean quote = false;
if(grp.startsWith("=\"{")) {
attributeName = grp.substring(3, grp.length() - 2);
quote = true;
} else
attributeName = grp.substring(1, grp.length() - 1);
Object attributeValue = mbean.getAttribute(attributeName);
String validValue = quote ?
"=" + ObjectName.quote(attributeValue.toString()) :
attributeValue.toString();
template = template.replace(grp, validValue);
}
return new ObjectName(template);
}catch(Exception ex) {
NotCompliantMBeanException ncex = new
NotCompliantMBeanException(ObjectNameTemplate.class.
getSimpleName() + " annotation value [" + template + "] " +
"is invalid. " + ex);
ncex.initCause(ex);
throw ncex;
}
}
/*
* ------------------------------------------
* PRIVATE METHODS
* ------------------------------------------
*/
static boolean hasMXBeanAnnotation(Class<?> c) {
MXBean m = c.getAnnotation(MXBean.class);
return (m != null && m.value());
}
/**
* Try to find the MBean interface corresponding to the class aName
@ -469,77 +352,11 @@ public class Introspector {
return null;
}
public static String descriptionForElement(AnnotatedElement elmt) {
if (elmt == null)
return null;
Description d = elmt.getAnnotation(Description.class);
if (d == null)
return null;
return d.value();
}
public static String descriptionForParameter(
Annotation[] parameterAnnotations) {
for (Annotation a : parameterAnnotations) {
if (a instanceof Description)
return ((Description) a).value();
}
return null;
}
public static String nameForParameter(
Annotation[] parameterAnnotations) {
for (Annotation a : parameterAnnotations) {
Class<? extends Annotation> ac = a.annotationType();
// You'd really have to go out of your way to have more than
// one @Name annotation, so we don't check for that.
if (ac.getSimpleName().equals("Name")) {
try {
Method value = ac.getMethod("value");
if (value.getReturnType() == String.class &&
value.getParameterTypes().length == 0) {
return (String) value.invoke(a);
}
} catch (Exception e) {
MBEANSERVER_LOGGER.log(
Level.WARNING,
"Unexpected exception getting @" + ac.getName(),
e);
}
}
}
return null;
}
public static Descriptor descriptorForElement(final AnnotatedElement elmt,
boolean isSetter) {
public static Descriptor descriptorForElement(final AnnotatedElement elmt) {
if (elmt == null)
return ImmutableDescriptor.EMPTY_DESCRIPTOR;
final Annotation[] annots = elmt.getAnnotations();
Descriptor descr = descriptorForAnnotations(annots);
String[] exceptions = {};
if(elmt instanceof Method)
exceptions = getAllExceptions(((Method) elmt).getExceptionTypes());
else
if(elmt instanceof Constructor<?>)
exceptions = getAllExceptions(((Constructor<?>) elmt).
getExceptionTypes());
if(exceptions.length > 0 ) {
String fieldName = isSetter ? JMX.SET_EXCEPTIONS_FIELD :
JMX.EXCEPTIONS_FIELD;
String[] fieldNames = {fieldName};
Object[] fieldValues = {exceptions};
descr = ImmutableDescriptor.union(descr,
new ImmutableDescriptor(fieldNames, fieldValues));
}
return descr;
}
public static Descriptor descriptorForAnnotation(Annotation annot) {
return descriptorForAnnotations(new Annotation[] {annot});
return descriptorForAnnotations(annots);
}
public static Descriptor descriptorForAnnotations(Annotation[] annots) {
@ -547,9 +364,36 @@ public class Introspector {
return ImmutableDescriptor.EMPTY_DESCRIPTOR;
Map<String, Object> descriptorMap = new HashMap<String, Object>();
for (Annotation a : annots) {
if (a instanceof DescriptorFields)
addDescriptorFieldsToMap(descriptorMap, (DescriptorFields) a);
addAnnotationFieldsToMap(descriptorMap, a);
Class<? extends Annotation> c = a.annotationType();
Method[] elements = c.getMethods();
for (Method element : elements) {
DescriptorKey key = element.getAnnotation(DescriptorKey.class);
if (key != null) {
String name = key.value();
Object value;
try {
value = element.invoke(a);
} catch (RuntimeException e) {
// we don't expect this - except for possibly
// security exceptions?
// RuntimeExceptions shouldn't be "UndeclaredThrowable".
// anyway...
//
throw e;
} catch (Exception e) {
// we don't expect this
throw new UndeclaredThrowableException(e);
}
value = annotationToField(value);
Object oldValue = descriptorMap.put(name, value);
if (oldValue != null && !equals(oldValue, value)) {
final String msg =
"Inconsistent values for descriptor field " + name +
" from annotations: " + value + " :: " + oldValue;
throw new IllegalArgumentException(msg);
}
}
}
}
if (descriptorMap.isEmpty())
@ -558,76 +402,6 @@ public class Introspector {
return new ImmutableDescriptor(descriptorMap);
}
/**
* Array of thrown excepions.
* @param exceptions can be null;
* @return An Array of Exception class names. Size is 0 if method is null.
*/
private static String[] getAllExceptions(Class<?>[] exceptions) {
Set<String> set = new LinkedHashSet<String>();
for(Class<?>ex : exceptions)
set.add(ex.getName());
String[] arr = new String[set.size()];
return set.toArray(arr);
}
private static void addDescriptorFieldsToMap(
Map<String, Object> descriptorMap, DescriptorFields df) {
for (String field : df.value()) {
int eq = field.indexOf('=');
if (eq < 0) {
throw new IllegalArgumentException(
"@DescriptorFields string must contain '=': " +
field);
}
String name = field.substring(0, eq);
String value = field.substring(eq + 1);
addToMap(descriptorMap, name, value);
}
}
private static void addAnnotationFieldsToMap(
Map<String, Object> descriptorMap, Annotation a) {
Class<? extends Annotation> c = a.annotationType();
Method[] elements = c.getMethods();
for (Method element : elements) {
DescriptorKey key = element.getAnnotation(DescriptorKey.class);
if (key != null) {
String name = key.value();
Object value;
try {
value = element.invoke(a);
} catch (RuntimeException e) {
// we don't expect this - except for possibly
// security exceptions?
// RuntimeExceptions shouldn't be "UndeclaredThrowable".
// anyway...
throw e;
} catch (Exception e) {
// we don't expect this
throw new UndeclaredThrowableException(e);
}
if (!key.omitIfDefault() ||
!equals(value, element.getDefaultValue())) {
value = annotationToField(value);
addToMap(descriptorMap, name, value);
}
}
}
}
private static void addToMap(
Map<String, Object> descriptorMap, String name, Object value) {
Object oldValue = descriptorMap.put(name, value);
if (oldValue != null && !equals(oldValue, value)) {
final String msg =
"Inconsistent values for descriptor field " + name +
" from annotations: " + value + " :: " + oldValue;
throw new IllegalArgumentException(msg);
}
}
/**
* Throws a NotCompliantMBeanException or a SecurityException.
* @param notCompliant the class which was under examination

View File

@ -25,14 +25,14 @@
package com.sun.jmx.mbeanserver;
import com.sun.jmx.interceptor.DefaultMBeanServerInterceptor;
import com.sun.jmx.interceptor.MBeanServerInterceptor;
import static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
import com.sun.jmx.interceptor.NamespaceDispatchInterceptor;
import java.io.ObjectInputStream;
import java.security.AccessController;
import java.security.Permission;
import java.security.PrivilegedExceptionAction;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
import java.util.logging.Level;
@ -108,8 +108,6 @@ public final class JmxMBeanServer
/** The MBeanServerDelegate object representing the MBean Server */
private final MBeanServerDelegate mBeanServerDelegateObject;
private final String mbeanServerName;
/**
* <b>Package:</b> Creates an MBeanServer with the
* specified default domain name, outer interface, and delegate.
@ -241,10 +239,9 @@ public final class JmxMBeanServer
final Repository repository = new Repository(domain);
this.mbsInterceptor =
new NamespaceDispatchInterceptor(outer, delegate, instantiator,
new DefaultMBeanServerInterceptor(outer, delegate, instantiator,
repository);
this.interceptorsEnabled = interceptors;
this.mbeanServerName = Util.getMBeanServerSecurityName(delegate);
initialize();
}
@ -940,8 +937,7 @@ public final class JmxMBeanServer
throws ReflectionException, MBeanException {
/* Permission check */
checkMBeanPermission(mbeanServerName, className, null, null,
"instantiate");
checkMBeanPermission(className, null, null, "instantiate");
return instantiator.instantiate(className);
}
@ -978,8 +974,7 @@ public final class JmxMBeanServer
InstanceNotFoundException {
/* Permission check */
checkMBeanPermission(mbeanServerName, className, null,
null, "instantiate");
checkMBeanPermission(className, null, null, "instantiate");
ClassLoader myLoader = outerShell.getClass().getClassLoader();
return instantiator.instantiate(className, loaderName, myLoader);
@ -1017,8 +1012,7 @@ public final class JmxMBeanServer
throws ReflectionException, MBeanException {
/* Permission check */
checkMBeanPermission(mbeanServerName, className, null, null,
"instantiate");
checkMBeanPermission(className, null, null, "instantiate");
ClassLoader myLoader = outerShell.getClass().getClassLoader();
return instantiator.instantiate(className, params, signature,
@ -1061,8 +1055,7 @@ public final class JmxMBeanServer
InstanceNotFoundException {
/* Permission check */
checkMBeanPermission(mbeanServerName, className, null,
null, "instantiate");
checkMBeanPermission(className, null, null, "instantiate");
ClassLoader myLoader = outerShell.getClass().getClassLoader();
return instantiator.instantiate(className,loaderName,params,signature,
@ -1333,8 +1326,7 @@ public final class JmxMBeanServer
**/
public ClassLoaderRepository getClassLoaderRepository() {
/* Permission check */
checkMBeanPermission(mbeanServerName, null, null,
null, "getClassLoaderRepository");
checkMBeanPermission(null, null, null, "getClassLoaderRepository");
return secureClr;
}
@ -1487,16 +1479,14 @@ public final class JmxMBeanServer
// SECURITY CHECKS
//----------------
private static void checkMBeanPermission(String serverName,
String classname,
private static void checkMBeanPermission(String classname,
String member,
ObjectName objectName,
String actions)
throws SecurityException {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
Permission perm = new MBeanPermission(serverName,
classname,
Permission perm = new MBeanPermission(classname,
member,
objectName,
actions);

View File

@ -33,10 +33,6 @@ import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javax.management.MBean;
import javax.management.MXBean;
import javax.management.ManagedAttribute;
import javax.management.ManagedOperation;
import javax.management.NotCompliantMBeanException;
/**
@ -55,15 +51,15 @@ import javax.management.NotCompliantMBeanException;
*/
class MBeanAnalyzer<M> {
static interface MBeanVisitor<M, X extends Exception> {
static interface MBeanVisitor<M> {
public void visitAttribute(String attributeName,
M getter,
M setter) throws X;
M setter);
public void visitOperation(String operationName,
M operation) throws X;
M operation);
}
<X extends Exception> void visit(MBeanVisitor<M, X> visitor) throws X {
void visit(MBeanVisitor<M> visitor) {
// visit attributes
for (Map.Entry<String, AttrMethods<M>> entry : attrMap.entrySet()) {
String name = entry.getKey();
@ -108,7 +104,10 @@ class MBeanAnalyzer<M> {
private MBeanAnalyzer(Class<?> mbeanType,
MBeanIntrospector<M> introspector)
throws NotCompliantMBeanException {
introspector.checkCompliance(mbeanType);
if (!mbeanType.isInterface()) {
throw new NotCompliantMBeanException("Not an interface: " +
mbeanType.getName());
}
try {
initMaps(mbeanType, introspector);
@ -129,26 +128,18 @@ class MBeanAnalyzer<M> {
for (Method m : methods) {
final String name = m.getName();
final int nParams = m.getParameterTypes().length;
final boolean managedOp = m.isAnnotationPresent(ManagedOperation.class);
final boolean managedAttr = m.isAnnotationPresent(ManagedAttribute.class);
if (managedOp && managedAttr) {
throw new NotCompliantMBeanException("Method " + name +
" has both @ManagedOperation and @ManagedAttribute");
}
final M cm = introspector.mFrom(m);
String attrName = "";
if (!managedOp) {
if (name.startsWith("get"))
attrName = name.substring(3);
else if (name.startsWith("is")
&& m.getReturnType() == boolean.class)
attrName = name.substring(2);
}
if (name.startsWith("get"))
attrName = name.substring(3);
else if (name.startsWith("is")
&& m.getReturnType() == boolean.class)
attrName = name.substring(2);
if (attrName.length() != 0 && nParams == 0
&& m.getReturnType() != void.class && !managedOp) {
&& m.getReturnType() != void.class) {
// It's a getter
// Check we don't have both isX and getX
AttrMethods<M> am = attrMap.get(attrName);
@ -165,7 +156,7 @@ class MBeanAnalyzer<M> {
attrMap.put(attrName, am);
} else if (name.startsWith("set") && name.length() > 3
&& nParams == 1 &&
m.getReturnType() == void.class && !managedOp) {
m.getReturnType() == void.class) {
// It's a setter
attrName = name.substring(3);
AttrMethods<M> am = attrMap.get(attrName);
@ -178,9 +169,6 @@ class MBeanAnalyzer<M> {
}
am.setter = cm;
attrMap.put(attrName, am);
} else if (managedAttr) {
throw new NotCompliantMBeanException("Method " + name +
" has @ManagedAttribute but is not a valid getter or setter");
} else {
// It's an operation
List<M> cms = opMap.get(name);

View File

@ -1,295 +0,0 @@
/*
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.mbeanserver;
import java.lang.ref.WeakReference;
import java.security.PrivilegedAction;
import java.util.Map;
import java.util.WeakHashMap;
import javax.annotation.Resource;
import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import static com.sun.jmx.mbeanserver.Util.newMap;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.security.AccessController;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.management.SendNotification;
public class MBeanInjector {
// There are no instances of this class
private MBeanInjector() {
}
private static Class<?>[] injectedClasses = {
MBeanServer.class, ObjectName.class, SendNotification.class,
};
public static void inject(Object mbean, MBeanServer mbs, ObjectName name)
throws Exception {
ClassInjector injector = injectorForClass(mbean.getClass());
injector.inject(mbean, MBeanServer.class, mbs);
injector.inject(mbean, ObjectName.class, name);
}
public static boolean injectsSendNotification(Object mbean)
throws NotCompliantMBeanException {
ClassInjector injector = injectorForClass(mbean.getClass());
return injector.injects(SendNotification.class);
}
public static void injectSendNotification(Object mbean, SendNotification sn)
throws Exception {
ClassInjector injector = injectorForClass(mbean.getClass());
injector.inject(mbean, SendNotification.class, sn);
}
public static void validate(Class<?> c) throws NotCompliantMBeanException {
injectorForClass(c);
}
private static class ClassInjector {
private Map<Class<?>, List<Field>> fields;
private Map<Class<?>, List<Method>> methods;
ClassInjector(Class<?> c) throws NotCompliantMBeanException {
fields = newMap();
methods = newMap();
Class<?> sup = c.getSuperclass();
ClassInjector supInjector;
if (sup == null) {
supInjector = null;
} else {
supInjector = injectorForClass(sup);
fields.putAll(supInjector.fields);
methods.putAll(supInjector.methods);
}
addMembers(c);
eliminateOverriddenMethods();
// If we haven't added any new fields or methods to what we
// inherited, then we can share the parent's maps.
if (supInjector != null) {
if (fields.equals(supInjector.fields))
fields = supInjector.fields;
if (methods.equals(supInjector.methods))
methods = supInjector.methods;
}
}
boolean injects(Class<?> c) {
return (fields.get(c) != null || methods.get(c) != null);
}
<T> void inject(Object instance, Class<T> type, T resource)
throws Exception {
List<Field> fs = fields.get(type);
if (fs != null) {
for (Field f : fs)
f.set(instance, resource);
}
List<Method> ms = methods.get(type);
if (ms != null) {
for (Method m : ms) {
try {
m.invoke(instance, resource);
} catch (InvocationTargetException e) {
Throwable cause = e.getCause();
if (cause instanceof Error)
throw (Error) cause;
else
throw (Exception) cause;
}
}
}
}
private void eliminateOverriddenMethods() {
/* Covariant overriding is unlikely, but it is possible that the
* parent has a @Resource method that we override with another
* @Resource method. We don't want to invoke both methods,
* because polymorphism means we would actually invoke the same
* method twice.
*/
for (Map.Entry<Class<?>, List<Method>> entry : methods.entrySet()) {
List<Method> list = entry.getValue();
list = MBeanAnalyzer.eliminateCovariantMethods(list);
entry.setValue(list);
}
}
/*
* Find Fields or Methods within the given Class that we can inject
* resource references into. Suppose we want to know if a Field can get
* a reference to an ObjectName. We'll accept fields like this:
*
* @Resource
* private transient ObjectName name;
*
* or like this:
*
* @Resource(type = ObjectName.class)
* private transient Object name;
*
* but not like this:
*
* @Resource
* private transient Object name;
*
* (Plain @Resource is equivalent to @Resource(type = Object.class).)
*
* We don't want to inject into everything that might possibly accept
* an ObjectName reference, because examples like the last one above
* could also accept an MBeanServer reference or any other sort of
* reference.
*
* So we accept a Field if it has a @Resource annotation and either
* (a) its type is exactly ObjectName and its @Resource type is
* compatible with ObjectName (e.g. it is Object); or
* (b) its type is compatible with ObjectName and its @Resource type
* is exactly ObjectName. Fields that meet these criteria will not
* meet the same criteria with respect to other types such as MBeanServer.
*
* The same logic applies mutatis mutandis to Methods such as this:
*
* @Resource
* private void setObjectName1(ObjectName name)
* @Resource(type = Object.class)
* private void setObjectName2(Object name)
*/
private void addMembers(final Class<?> c)
throws NotCompliantMBeanException {
AccessibleObject[][] memberArrays =
AccessController.doPrivileged(
new PrivilegedAction<AccessibleObject[][]>() {
public AccessibleObject[][] run() {
return new AccessibleObject[][] {
c.getDeclaredFields(), c.getDeclaredMethods()
};
}
});
for (AccessibleObject[] members : memberArrays) {
for (final AccessibleObject member : members) {
Resource res = member.getAnnotation(Resource.class);
if (res == null)
continue;
final Field field;
final Method method;
final Class<?> memberType;
final int modifiers;
if (member instanceof Field) {
field = (Field) member;
memberType = field.getType();
modifiers = field.getModifiers();
method = null;
} else {
field = null;
method = (Method) member;
Class<?>[] paramTypes = method.getParameterTypes();
if (paramTypes.length != 1) {
throw new NotCompliantMBeanException(
"@Resource method must have exactly 1 " +
"parameter: " + method);
}
if (method.getReturnType() != void.class) {
throw new NotCompliantMBeanException(
"@Resource method must return void: " +
method);
}
memberType = paramTypes[0];
modifiers = method.getModifiers();
}
if (Modifier.isStatic(modifiers)) {
throw new NotCompliantMBeanException(
"@Resource method or field cannot be static: " +
member);
}
for (Class<?> injectedClass : injectedClasses) {
Class<?>[] types = {memberType, res.type()};
boolean accept = false;
for (int i = 0; i < 2; i++) {
if (types[i] == injectedClass &&
types[1 - i].isAssignableFrom(injectedClass)) {
accept = true;
break;
}
}
if (accept) {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
member.setAccessible(true);
return null;
}
});
addToMap(fields, injectedClass, field);
addToMap(methods, injectedClass, method);
}
}
}
}
}
private static <K, V> void addToMap(Map<K, List<V>> map, K key, V value) {
if (value == null)
return;
List<V> list = map.get(key);
if (list == null)
list = Collections.singletonList(value);
else {
if (list.size() == 1)
list = new ArrayList<V>(list);
list.add(value);
}
map.put(key, list);
}
}
private static synchronized ClassInjector injectorForClass(Class<?> c)
throws NotCompliantMBeanException {
WeakReference<ClassInjector> wr = injectorMap.get(c);
ClassInjector ci = (wr == null) ? null : wr.get();
if (ci == null) {
ci = new ClassInjector(c);
injectorMap.put(c, new WeakReference<ClassInjector>(ci));
}
return ci;
}
private static Map<Class<?>, WeakReference<ClassInjector>> injectorMap =
new WeakHashMap<Class<?>, WeakReference<ClassInjector>>();
}

View File

@ -613,15 +613,6 @@ public class MBeanInstantiator {
return clr;
}
/**
* Returns the class of a primitive type.
* @param name The type for which we the associated class.
* @return the class, or null if name is not primitive.
*/
public static Class<?> primitiveType(String name) {
return primitiveClasses.get(name);
}
/**
* Load a class with the specified loader, or with this object
* class loader if the specified loader is null.

View File

@ -36,28 +36,20 @@ import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.WeakHashMap;
import javax.management.Description;
import javax.management.Descriptor;
import javax.management.ImmutableDescriptor;
import javax.management.IntrospectionException;
import javax.management.InvalidAttributeValueException;
import javax.management.MBean;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanConstructorInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MXBean;
import javax.management.ManagedAttribute;
import javax.management.ManagedOperation;
import javax.management.NotCompliantMBeanException;
import javax.management.NotificationBroadcaster;
import javax.management.NotificationInfo;
import javax.management.NotificationInfos;
import javax.management.ReflectionException;
/**
@ -79,7 +71,7 @@ import javax.management.ReflectionException;
* ancestor with ConvertingMethod. But that would mean an extra object
* for every Method in every Standard MBean interface.
*/
public abstract class MBeanIntrospector<M> {
abstract class MBeanIntrospector<M> {
static final class PerInterfaceMap<M>
extends WeakHashMap<Class<?>, WeakReference<PerInterface<M>>> {}
@ -159,27 +151,7 @@ public abstract class MBeanIntrospector<M> {
* may be null.
*/
abstract MBeanAttributeInfo getMBeanAttributeInfo(String attributeName,
M getter, M setter) throws IntrospectionException;
final String getAttributeDescription(
String attributeName, String defaultDescription,
Method getter, Method setter) throws IntrospectionException {
String g = Introspector.descriptionForElement(getter);
String s = Introspector.descriptionForElement(setter);
if (g == null) {
if (s == null)
return defaultDescription;
else
return s;
} else if (s == null || g.equals(s)) {
return g;
} else {
throw new IntrospectionException(
"Inconsistent @Description on getter and setter for " +
"attribute " + attributeName);
}
}
M getter, M setter);
/**
* Construct an MBeanOperationInfo for the given operation based on
* the M it was derived from.
@ -200,37 +172,11 @@ public abstract class MBeanIntrospector<M> {
*/
abstract Descriptor getMBeanDescriptor(Class<?> resourceClass);
/**
* Get any additional Descriptor entries for this introspector instance.
* If there is a non-default MXBeanMappingFactory, it will appear in
* this Descriptor.
* @return Additional Descriptor entries, or an empty Descriptor if none.
*/
Descriptor getSpecificMBeanDescriptor() {
return ImmutableDescriptor.EMPTY_DESCRIPTOR;
}
void checkCompliance(Class<?> mbeanType) throws NotCompliantMBeanException {
if (!mbeanType.isInterface() &&
!mbeanType.isAnnotationPresent(MBean.class) &&
!Introspector.hasMXBeanAnnotation(mbeanType)) {
throw new NotCompliantMBeanException("Not an interface and " +
"does not have @" + MBean.class.getSimpleName() +
" or @" + MXBean.class.getSimpleName() + " annotation: " +
mbeanType.getName());
}
}
/**
* Get the methods to be analyzed to build the MBean interface.
*/
List<Method> getMethods(final Class<?> mbeanType) throws Exception {
if (mbeanType.isInterface())
return Arrays.asList(mbeanType.getMethods());
final List<Method> methods = newList();
getAnnotatedMethods(mbeanType, methods);
return methods;
return Arrays.asList(mbeanType.getMethods());
}
final PerInterface<M> getPerInterface(Class<?> mbeanInterface)
@ -265,14 +211,11 @@ public abstract class MBeanIntrospector<M> {
* the MBeanInfo's Descriptor.
*/
private MBeanInfo makeInterfaceMBeanInfo(Class<?> mbeanInterface,
MBeanAnalyzer<M> analyzer) throws IntrospectionException {
MBeanAnalyzer<M> analyzer) {
final MBeanInfoMaker maker = new MBeanInfoMaker();
analyzer.visit(maker);
final String defaultDescription =
final String description =
"Information on the management interface of the MBean";
String description = Introspector.descriptionForElement(mbeanInterface);
if (description == null)
description = defaultDescription;
return maker.makeMBeanInfo(mbeanInterface, description);
}
@ -370,11 +313,11 @@ public abstract class MBeanIntrospector<M> {
/** A visitor that constructs the per-interface MBeanInfo. */
private class MBeanInfoMaker
implements MBeanAnalyzer.MBeanVisitor<M, IntrospectionException> {
implements MBeanAnalyzer.MBeanVisitor<M> {
public void visitAttribute(String attributeName,
M getter,
M setter) throws IntrospectionException {
M setter) {
MBeanAttributeInfo mbai =
getMBeanAttributeInfo(attributeName, getter, setter);
@ -403,7 +346,7 @@ public abstract class MBeanIntrospector<M> {
new ImmutableDescriptor(interfaceClassName);
final Descriptor mbeanDescriptor = getBasicMBeanDescriptor();
final Descriptor annotatedDescriptor =
Introspector.descriptorForElement(mbeanInterface, false);
Introspector.descriptorForElement(mbeanInterface);
final Descriptor descriptor =
DescriptorCache.getInstance().union(
classNameDescriptor,
@ -442,32 +385,20 @@ public abstract class MBeanIntrospector<M> {
* Return the MBeanInfo for the given resource, based on the given
* per-interface data.
*/
final MBeanInfo getMBeanInfo(Object resource, PerInterface<M> perInterface)
throws NotCompliantMBeanException {
final MBeanInfo getMBeanInfo(Object resource, PerInterface<M> perInterface) {
MBeanInfo mbi =
getClassMBeanInfo(resource.getClass(), perInterface);
MBeanNotificationInfo[] notifs;
try {
notifs = findNotifications(resource);
} catch (RuntimeException e) {
NotCompliantMBeanException x =
new NotCompliantMBeanException(e.getMessage());
x.initCause(e);
throw x;
}
Descriptor d = getSpecificMBeanDescriptor();
boolean anyNotifs = (notifs != null && notifs.length > 0);
if (!anyNotifs && ImmutableDescriptor.EMPTY_DESCRIPTOR.equals(d))
MBeanNotificationInfo[] notifs = findNotifications(resource);
if (notifs == null || notifs.length == 0)
return mbi;
else {
d = ImmutableDescriptor.union(d, mbi.getDescriptor());
return new MBeanInfo(mbi.getClassName(),
mbi.getDescription(),
mbi.getAttributes(),
mbi.getConstructors(),
mbi.getOperations(),
notifs,
d);
mbi.getDescriptor());
}
}
@ -507,145 +438,29 @@ public abstract class MBeanIntrospector<M> {
}
}
/*
* Add to "methods" every public method that has the @ManagedAttribute
* or @ManagedOperation annotation, in the given class or any of
* its superclasses or superinterfaces.
*
* We always add superclass or superinterface methods first, so that
* the stable sort used by eliminateCovariantMethods will put the
* method from the most-derived class last. This means that we will
* see the version of the @ManagedAttribute (or ...Operation) annotation
* from that method, which might have a different description or whatever.
*/
public static void getAnnotatedMethods(Class<?> c, List<Method> methods)
throws Exception {
Class<?> sup = c.getSuperclass();
if (sup != null)
getAnnotatedMethods(sup, methods);
Class<?>[] intfs = c.getInterfaces();
for (Class<?> intf : intfs)
getAnnotatedMethods(intf, methods);
for (Method m : c.getMethods()) {
// We are careful not to add m if it is inherited from a parent
// class or interface, because duplicate methods lead to nasty
// behaviour in eliminateCovariantMethods.
if (m.getDeclaringClass() == c &&
(m.isAnnotationPresent(ManagedAttribute.class) ||
m.isAnnotationPresent(ManagedOperation.class)))
methods.add(m);
}
}
/*
* Return the array of MBeanNotificationInfo for the given MBean object.
* If the object implements NotificationBroadcaster and its
* getNotificationInfo() method returns a non-empty array, then that
* is the result. Otherwise, if the object has a @NotificationInfo
* or @NotificationInfos annotation, then its contents form the result.
* Otherwise, the result is null.
*/
static MBeanNotificationInfo[] findNotifications(Object moi) {
if (moi instanceof NotificationBroadcaster) {
MBeanNotificationInfo[] mbn =
((NotificationBroadcaster) moi).getNotificationInfo();
if (mbn != null && mbn.length > 0) {
MBeanNotificationInfo[] result =
new MBeanNotificationInfo[mbn.length];
for (int i = 0; i < mbn.length; i++) {
MBeanNotificationInfo ni = mbn[i];
if (ni.getClass() != MBeanNotificationInfo.class)
ni = (MBeanNotificationInfo) ni.clone();
result[i] = ni;
}
return result;
}
} else {
try {
if (!MBeanInjector.injectsSendNotification(moi))
return null;
} catch (NotCompliantMBeanException e) {
throw new RuntimeException(e);
}
}
return findNotificationsFromAnnotations(moi.getClass());
}
public static MBeanNotificationInfo[] findNotificationsFromAnnotations(
Class<?> mbeanClass) {
Class<?> c = getAnnotatedNotificationInfoClass(mbeanClass);
if (c == null)
if (!(moi instanceof NotificationBroadcaster))
return null;
NotificationInfo ni = c.getAnnotation(NotificationInfo.class);
NotificationInfos nis = c.getAnnotation(NotificationInfos.class);
List<NotificationInfo> list = newList();
if (ni != null)
list.add(ni);
if (nis != null)
list.addAll(Arrays.asList(nis.value()));
if (list.isEmpty())
MBeanNotificationInfo[] mbn =
((NotificationBroadcaster) moi).getNotificationInfo();
if (mbn == null)
return null;
List<MBeanNotificationInfo> mbnis = newList();
for (NotificationInfo x : list) {
// The Descriptor includes any fields explicitly specified by
// x.descriptorFields(), plus any fields from the contained
// @Description annotation.
Descriptor d = new ImmutableDescriptor(x.descriptorFields());
d = ImmutableDescriptor.union(
d, Introspector.descriptorForAnnotation(x.description()));
MBeanNotificationInfo mbni = new MBeanNotificationInfo(
x.types(), x.notificationClass().getName(),
x.description().value(), d);
mbnis.add(mbni);
}
return mbnis.toArray(new MBeanNotificationInfo[mbnis.size()]);
}
private static final Map<Class<?>, WeakReference<Class<?>>>
annotatedNotificationInfoClasses = newWeakHashMap();
private static Class<?> getAnnotatedNotificationInfoClass(Class<?> baseClass) {
synchronized (annotatedNotificationInfoClasses) {
WeakReference<Class<?>> wr =
annotatedNotificationInfoClasses.get(baseClass);
if (wr != null)
return wr.get();
Class<?> c = null;
if (baseClass.isAnnotationPresent(NotificationInfo.class) ||
baseClass.isAnnotationPresent(NotificationInfos.class)) {
c = baseClass;
} else {
Class<?>[] intfs = baseClass.getInterfaces();
for (Class<?> intf : intfs) {
Class<?> c1 = getAnnotatedNotificationInfoClass(intf);
if (c1 != null) {
if (c != null) {
throw new IllegalArgumentException(
"Class " + baseClass.getName() + " inherits " +
"@NotificationInfo(s) from both " +
c.getName() + " and " + c1.getName());
}
c = c1;
}
}
}
// Record the result of the search. If no @NotificationInfo(s)
// were found, c is null, and we store a WeakReference(null).
// This prevents us from having to search again and fail again.
annotatedNotificationInfoClasses.put(baseClass,
new WeakReference<Class<?>>(c));
return c;
MBeanNotificationInfo[] result =
new MBeanNotificationInfo[mbn.length];
for (int i = 0; i < mbn.length; i++) {
MBeanNotificationInfo ni = mbn[i];
if (ni.getClass() != MBeanNotificationInfo.class)
ni = (MBeanNotificationInfo) ni.clone();
result[i] = ni;
}
return result;
}
private static MBeanConstructorInfo[] findConstructors(Class<?> c) {
Constructor<?>[] cons = c.getConstructors();
MBeanConstructorInfo[] mbc = new MBeanConstructorInfo[cons.length];
for (int i = 0; i < cons.length; i++) {
String descr = "Public constructor of the MBean";
Description d = cons[i].getAnnotation(Description.class);
if (d != null)
descr = d.value();
final String descr = "Public constructor of the MBean";
mbc[i] = new MBeanConstructorInfo(descr, cons[i]);
}
return mbc;

View File

@ -37,7 +37,7 @@ import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.openmbean.MXBeanMappingFactory;
import com.sun.jmx.mbeanserver.MXBeanMappingFactory;
/**
* Base class for MBeans. There is one instance of this class for
@ -121,8 +121,7 @@ import javax.management.openmbean.MXBeanMappingFactory;
public abstract class MBeanSupport<M>
implements DynamicMBean2, MBeanRegistration {
<T> MBeanSupport(T resource, Class<T> mbeanInterfaceType,
MXBeanMappingFactory mappingFactory)
<T> MBeanSupport(T resource, Class<T> mbeanInterfaceType)
throws NotCompliantMBeanException {
if (mbeanInterfaceType == null)
throw new NotCompliantMBeanException("Null MBean interface");
@ -133,14 +132,13 @@ public abstract class MBeanSupport<M>
throw new NotCompliantMBeanException(msg);
}
this.resource = resource;
MBeanIntrospector<M> introspector = getMBeanIntrospector(mappingFactory);
MBeanIntrospector<M> introspector = getMBeanIntrospector();
this.perInterface = introspector.getPerInterface(mbeanInterfaceType);
this.mbeanInfo = introspector.getMBeanInfo(resource, perInterface);
}
/** Return the appropriate introspector for this type of MBean. */
abstract MBeanIntrospector<M>
getMBeanIntrospector(MXBeanMappingFactory mappingFactory);
abstract MBeanIntrospector<M> getMBeanIntrospector();
/**
* Return a cookie for this MBean. This cookie will be passed to
@ -262,14 +260,10 @@ public abstract class MBeanSupport<M>
return resource.getClass().getName();
}
public final Object getWrappedObject() {
public final Object getResource() {
return resource;
}
public final ClassLoader getWrappedClassLoader() {
return resource.getClass().getClassLoader();
}
public final Class<?> getMBeanInterface() {
return perInterface.getMBeanInterface();
}

View File

@ -28,26 +28,18 @@ package com.sun.jmx.mbeanserver;
import com.sun.jmx.mbeanserver.MBeanIntrospector.MBeanInfoMap;
import com.sun.jmx.mbeanserver.MBeanIntrospector.PerInterfaceMap;
import java.lang.annotation.Annotation;
import java.lang.ref.WeakReference;
import java.lang.reflect.GenericArrayType;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Map;
import java.util.WeakHashMap;
import javax.management.Description;
import javax.management.Descriptor;
import javax.management.ImmutableDescriptor;
import javax.management.IntrospectionException;
import javax.management.JMX;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo;
import javax.management.ManagedOperation;
import javax.management.NotCompliantMBeanException;
import javax.management.openmbean.MXBeanMappingFactory;
import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
import javax.management.openmbean.OpenMBeanOperationInfoSupport;
import javax.management.openmbean.OpenMBeanParameterInfo;
@ -60,36 +52,10 @@ import javax.management.openmbean.OpenType;
* @since 1.6
*/
class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
/* We keep one MXBeanIntrospector per MXBeanMappingFactory, since the results
* of the introspection depend on the factory. The MXBeanIntrospector
* has a reference back to the factory, so we wrap it in a WeakReference.
* It will be strongly referenced by any MXBeanSupport instances using it;
* if there are none then it is OK to gc it.
*/
private static final
Map<MXBeanMappingFactory, WeakReference<MXBeanIntrospector>> map =
new WeakHashMap<MXBeanMappingFactory, WeakReference<MXBeanIntrospector>>();
private static final MXBeanIntrospector instance = new MXBeanIntrospector();
static MXBeanIntrospector getInstance(MXBeanMappingFactory factory) {
if (factory == null)
factory = MXBeanMappingFactory.DEFAULT;
synchronized (map) {
MXBeanIntrospector intro;
WeakReference<MXBeanIntrospector> wr = map.get(factory);
if (wr != null) {
intro = wr.get();
if (intro != null)
return intro;
}
intro = new MXBeanIntrospector(factory);
wr = new WeakReference<MXBeanIntrospector>(intro);
map.put(factory, wr);
return intro;
}
}
private MXBeanIntrospector(MXBeanMappingFactory factory) {
this.mappingFactory = factory;
static MXBeanIntrospector getInstance() {
return instance;
}
@Override
@ -115,7 +81,7 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
@Override
ConvertingMethod mFrom(Method m) {
return ConvertingMethod.from(m, mappingFactory);
return ConvertingMethod.from(m);
}
@Override
@ -176,17 +142,13 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
@Override
MBeanAttributeInfo getMBeanAttributeInfo(String attributeName,
ConvertingMethod getter, ConvertingMethod setter)
throws IntrospectionException {
ConvertingMethod getter, ConvertingMethod setter) {
final boolean isReadable = (getter != null);
final boolean isWritable = (setter != null);
final boolean isIs = isReadable && getName(getter).startsWith("is");
final String description = getAttributeDescription(
attributeName, attributeName,
getter == null ? null : getter.getMethod(),
setter == null ? null : setter.getMethod());
final String description = attributeName;
final OpenType<?> openType;
final Type originalType;
@ -235,17 +197,13 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
MBeanOperationInfo getMBeanOperationInfo(String operationName,
ConvertingMethod operation) {
final Method method = operation.getMethod();
String description = operationName;
final String description = operationName;
/* Ideally this would be an empty string, but
OMBOperationInfo constructor forbids that. */
Description d = method.getAnnotation(Description.class);
if (d != null)
description = d.value();
OMBOperationInfo constructor forbids that. Also, we
could consult an annotation to get a useful
description. */
int impact = MBeanOperationInfo.UNKNOWN;
ManagedOperation annot = method.getAnnotation(ManagedOperation.class);
if (annot != null)
impact = annot.impact().getCode();
final int impact = MBeanOperationInfo.UNKNOWN;
final OpenType<?> returnType = operation.getOpenReturnType();
final Type originalReturnType = operation.getGenericReturnType();
@ -257,15 +215,8 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
boolean openParameterTypes = true;
Annotation[][] annots = method.getParameterAnnotations();
for (int i = 0; i < paramTypes.length; i++) {
String paramName = Introspector.nameForParameter(annots[i]);
if (paramName == null)
paramName = "p" + i;
String paramDescription =
Introspector.descriptionForParameter(annots[i]);
if (paramDescription == null)
paramDescription = paramName;
final String paramName = "p" + i;
final String paramDescription = paramName;
final OpenType<?> openType = paramTypes[i];
final Type originalType = originalParamTypes[i];
Descriptor descriptor =
@ -292,7 +243,7 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
Descriptor descriptor =
typeDescriptor(returnType, originalReturnType);
descriptor = ImmutableDescriptor.union(descriptor,
Introspector.descriptorForElement(method, false));
Introspector.descriptorForElement(method));
final MBeanOperationInfo oi;
if (openReturnType && openParameterTypes) {
/* If the return value and all the parameters can be faithfully
@ -343,17 +294,6 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
return ImmutableDescriptor.EMPTY_DESCRIPTOR;
}
@Override
Descriptor getSpecificMBeanDescriptor() {
if (mappingFactory == MXBeanMappingFactory.DEFAULT)
return ImmutableDescriptor.EMPTY_DESCRIPTOR;
else {
return new ImmutableDescriptor(
JMX.MXBEAN_MAPPING_FACTORY_CLASS_FIELD + "=" +
mappingFactory.getClass().getName());
}
}
private static Descriptor typeDescriptor(OpenType<?> openType,
Type originalType) {
return new ImmutableDescriptor(
@ -421,7 +361,5 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
private final PerInterfaceMap<ConvertingMethod>
perInterfaceMap = new PerInterfaceMap<ConvertingMethod>();
private final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap();
private final MXBeanMappingFactory mappingFactory;
private static final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap();
}

View File

@ -25,8 +25,6 @@
package com.sun.jmx.mbeanserver;
import com.sun.jmx.remote.util.EnvHelp;
import java.io.InvalidObjectException;
import static com.sun.jmx.mbeanserver.Util.*;
import java.util.Map;
import java.lang.ref.WeakReference;
@ -85,181 +83,87 @@ import javax.management.openmbean.OpenDataException;
*
* From the above, it is clear that the logic for getX on an MXBean is
* the same as for setX on a proxy, and vice versa.
*
* The above describes the logic for "plain" MXBeanLookup, represented
* by MXBeanLookup.Plain. When namespaces enter the picture, we see
* MXBeanLookup.Prefix. Here, the idea is that the name of the ModuleMXBean
* might be a//m:m=m. In this case, we don't accept a reference to
* an MXBean object, since that would require different namespaces to know
* each others' objects. We only accept proxies. Suppose you have a proxy
* for a//m:m=m, call it moduleProxy, and you call
* moduleProxy.setProduct(productProxy). Then if productProxy is for
* a//p:p=p we should convert this to just p:p=p. If productProxy is for
* a//b//p:p=p we should convert it to b//p:p=p. Conversely, if getProduct
* returns an ObjectName like b//p:p=p then we should convert it into a proxy
* for a//b//p:p=p.
*/
public abstract class MXBeanLookup {
public class MXBeanLookup {
private MXBeanLookup(MBeanServerConnection mbsc) {
this.mbsc = mbsc;
}
static MXBeanLookup lookupFor(MBeanServerConnection mbsc, String prefix) {
if (prefix == null)
return Plain.lookupFor(mbsc);
else
return new Prefix(mbsc, prefix);
static MXBeanLookup lookupFor(MBeanServerConnection mbsc) {
synchronized (mbscToLookup) {
WeakReference<MXBeanLookup> weakLookup = mbscToLookup.get(mbsc);
MXBeanLookup lookup = (weakLookup == null) ? null : weakLookup.get();
if (lookup == null) {
lookup = new MXBeanLookup(mbsc);
mbscToLookup.put(mbsc, new WeakReference<MXBeanLookup>(lookup));
}
return lookup;
}
}
abstract <T> T objectNameToMXBean(ObjectName name, Class<T> type)
throws InvalidObjectException;
abstract ObjectName mxbeanToObjectName(Object mxbean)
throws OpenDataException;
static class Plain extends MXBeanLookup {
Plain(MBeanServerConnection mbsc) {
super(mbsc);
synchronized <T> T objectNameToMXBean(ObjectName name, Class<T> type) {
WeakReference<Object> wr = objectNameToProxy.get(name);
if (wr != null) {
Object proxy = wr.get();
if (type.isInstance(proxy))
return type.cast(proxy);
}
T proxy = JMX.newMXBeanProxy(mbsc, name, type);
objectNameToProxy.put(name, new WeakReference<Object>(proxy));
return proxy;
}
static Plain lookupFor(MBeanServerConnection mbsc) {
synchronized (mbscToLookup) {
WeakReference<Plain> weakLookup = mbscToLookup.get(mbsc);
Plain lookup = (weakLookup == null) ? null : weakLookup.get();
if (lookup == null) {
lookup = new Plain(mbsc);
mbscToLookup.put(mbsc, new WeakReference<Plain>(lookup));
}
return lookup;
}
}
@Override
synchronized <T> T objectNameToMXBean(ObjectName name, Class<T> type) {
WeakReference<Object> wr = objectNameToProxy.get(name);
if (wr != null) {
Object proxy = wr.get();
if (type.isInstance(proxy))
return type.cast(proxy);
}
T proxy = JMX.newMXBeanProxy(mbsc, name, type);
objectNameToProxy.put(name, new WeakReference<Object>(proxy));
return proxy;
}
@Override
synchronized ObjectName mxbeanToObjectName(Object mxbean)
throws OpenDataException {
String wrong;
if (mxbean instanceof Proxy) {
InvocationHandler ih = Proxy.getInvocationHandler(mxbean);
if (ih instanceof MBeanServerInvocationHandler) {
MBeanServerInvocationHandler mbsih =
(MBeanServerInvocationHandler) ih;
if (mbsih.getMBeanServerConnection().equals(mbsc))
return mbsih.getObjectName();
else
wrong = "proxy for a different MBeanServer";
} else
wrong = "not a JMX proxy";
} else {
ObjectName name = mxbeanToObjectName.get(mxbean);
if (name != null)
return name;
wrong = "not an MXBean registered in this MBeanServer";
}
String s = (mxbean == null) ?
"null" : "object of type " + mxbean.getClass().getName();
throw new OpenDataException(
"Could not convert " + s + " to an ObjectName: " + wrong);
// Message will be strange if mxbean is null but it is not
// supposed to be.
}
synchronized void addReference(ObjectName name, Object mxbean)
throws InstanceAlreadyExistsException {
ObjectName existing = mxbeanToObjectName.get(mxbean);
if (existing != null) {
String multiname = AccessController.doPrivileged(
new GetPropertyAction("jmx.mxbean.multiname"));
if (!"true".equalsIgnoreCase(multiname)) {
throw new InstanceAlreadyExistsException(
"MXBean already registered with name " + existing);
}
}
mxbeanToObjectName.put(mxbean, name);
}
synchronized boolean removeReference(ObjectName name, Object mxbean) {
if (name.equals(mxbeanToObjectName.get(mxbean))) {
mxbeanToObjectName.remove(mxbean);
return true;
synchronized ObjectName mxbeanToObjectName(Object mxbean)
throws OpenDataException {
String wrong;
if (mxbean instanceof Proxy) {
InvocationHandler ih = Proxy.getInvocationHandler(mxbean);
if (ih instanceof MBeanServerInvocationHandler) {
MBeanServerInvocationHandler mbsih =
(MBeanServerInvocationHandler) ih;
if (mbsih.getMBeanServerConnection().equals(mbsc))
return mbsih.getObjectName();
else
wrong = "proxy for a different MBeanServer";
} else
return false;
/* removeReference can be called when the above condition fails,
* notably if you try to register the same MXBean twice.
*/
wrong = "not a JMX proxy";
} else {
ObjectName name = mxbeanToObjectName.get(mxbean);
if (name != null)
return name;
wrong = "not an MXBean registered in this MBeanServer";
}
private final WeakIdentityHashMap<Object, ObjectName>
mxbeanToObjectName = WeakIdentityHashMap.make();
private final Map<ObjectName, WeakReference<Object>>
objectNameToProxy = newMap();
private static WeakIdentityHashMap<MBeanServerConnection,
WeakReference<Plain>>
mbscToLookup = WeakIdentityHashMap.make();
String s = (mxbean == null) ?
"null" : "object of type " + mxbean.getClass().getName();
throw new OpenDataException(
"Could not convert " + s + " to an ObjectName: " + wrong);
// Message will be strange if mxbean is null but it is not
// supposed to be.
}
private static class Prefix extends MXBeanLookup {
private final String prefix;
Prefix(MBeanServerConnection mbsc, String prefix) {
super(mbsc);
this.prefix = prefix;
}
@Override
<T> T objectNameToMXBean(ObjectName name, Class<T> type)
throws InvalidObjectException {
String domain = prefix + name.getDomain();
try {
name = name.withDomain(domain);
} catch (IllegalArgumentException e) {
throw EnvHelp.initCause(
new InvalidObjectException(e.getMessage()), e);
synchronized void addReference(ObjectName name, Object mxbean)
throws InstanceAlreadyExistsException {
ObjectName existing = mxbeanToObjectName.get(mxbean);
if (existing != null) {
String multiname = AccessController.doPrivileged(
new GetPropertyAction("jmx.mxbean.multiname"));
if (!"true".equalsIgnoreCase(multiname)) {
throw new InstanceAlreadyExistsException(
"MXBean already registered with name " + existing);
}
return JMX.newMXBeanProxy(mbsc, name, type);
}
@Override
ObjectName mxbeanToObjectName(Object mxbean)
throws OpenDataException {
ObjectName name = proxyToObjectName(mxbean);
String domain = name.getDomain();
if (!domain.startsWith(prefix)) {
throw new OpenDataException(
"Proxy's name does not start with " +
prefix + ": " + name);
}
try {
name = name.withDomain(domain.substring(prefix.length()));
} catch (IllegalArgumentException e) {
throw EnvHelp.initCause(
new OpenDataException(e.getMessage()), e);
}
return name;
}
mxbeanToObjectName.put(mxbean, name);
}
ObjectName proxyToObjectName(Object proxy) {
InvocationHandler ih = Proxy.getInvocationHandler(proxy);
if (ih instanceof MBeanServerInvocationHandler) {
MBeanServerInvocationHandler mbsih =
(MBeanServerInvocationHandler) ih;
if (mbsih.getMBeanServerConnection().equals(mbsc))
return mbsih.getObjectName();
}
return null;
synchronized boolean removeReference(ObjectName name, Object mxbean) {
if (name.equals(mxbeanToObjectName.get(mxbean))) {
mxbeanToObjectName.remove(mxbean);
return true;
} else
return false;
/* removeReference can be called when the above condition fails,
* notably if you try to register the same MXBean twice.
*/
}
static MXBeanLookup getLookup() {
@ -273,5 +177,12 @@ public abstract class MXBeanLookup {
private static final ThreadLocal<MXBeanLookup> currentLookup =
new ThreadLocal<MXBeanLookup>();
final MBeanServerConnection mbsc;
private final MBeanServerConnection mbsc;
private final WeakIdentityHashMap<Object, ObjectName>
mxbeanToObjectName = WeakIdentityHashMap.make();
private final Map<ObjectName, WeakReference<Object>>
objectNameToProxy = newMap();
private static final WeakIdentityHashMap<MBeanServerConnection,
WeakReference<MXBeanLookup>>
mbscToLookup = WeakIdentityHashMap.make();
}

View File

@ -23,10 +23,12 @@
* have any questions.
*/
package javax.management.openmbean;
package com.sun.jmx.mbeanserver;
import java.io.InvalidObjectException;
import java.lang.reflect.Type;
import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType;
/**
* <p>A custom mapping between Java types and Open types for use in MXBeans.
@ -166,12 +168,10 @@ public abstract class MXBeanMapping {
if (javaType instanceof Class<?> && ((Class<?>) javaType).isPrimitive())
return (Class<?>) javaType;
try {
String className = OpenType.validClassName(openType.getClassName());
String className = openType.getClassName();
return Class.forName(className, false, null);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e); // should not happen
} catch (OpenDataException e) {
throw new IllegalArgumentException("Bad OpenType: " + openType, e);
}
}

View File

@ -23,8 +23,10 @@
* have any questions.
*/
package javax.management.openmbean;
package com.sun.jmx.mbeanserver;
import javax.management.openmbean.*;
import com.sun.jmx.mbeanserver.MXBeanMapping;
import com.sun.jmx.mbeanserver.DefaultMXBeanMappingFactory;
import java.lang.reflect.Type;
@ -100,49 +102,6 @@ public abstract class MXBeanMappingFactory {
public static final MXBeanMappingFactory DEFAULT =
new DefaultMXBeanMappingFactory();
/**
* <p>Determine the appropriate MXBeanMappingFactory to use for the given
* MXBean interface, based on its annotations. If the interface has an
* {@link MXBeanMappingFactoryClass @MXBeanMappingFactoryClass} annotation,
* that is used to determine the MXBeanMappingFactory. Otherwise, if the
* package containing the interface has such an annotation, that is used.
* Otherwise the MXBeanMappingFactory is the {@linkplain #DEFAULT default}
* one.</p>
*
* @param intf the MXBean interface for which to determine the
* MXBeanMappingFactory.
*
* @return the MXBeanMappingFactory for the given MXBean interface.
*
* @throws IllegalArgumentException if {@code intf} is null, or if an
* exception occurs while trying constructing an MXBeanMappingFactory
* based on an annotation. In the second case, the exception will appear
* in the {@linkplain Throwable#getCause() cause chain} of the
* {@code IllegalArgumentException}.
*/
public static MXBeanMappingFactory forInterface(Class<?> intf) {
if (intf == null)
throw new IllegalArgumentException("Null interface");
MXBeanMappingFactoryClass annot =
intf.getAnnotation(MXBeanMappingFactoryClass.class);
if (annot == null) {
Package p = intf.getPackage();
if (p != null)
annot = p.getAnnotation(MXBeanMappingFactoryClass.class);
}
if (annot == null)
return MXBeanMappingFactory.DEFAULT;
Class<? extends MXBeanMappingFactory> factoryClass = annot.value();
try {
return annot.value().newInstance();
} catch (Exception e) {
throw new IllegalArgumentException(
"Could not instantiate MXBeanMappingFactory " +
factoryClass.getName() +
" from @MXBeanMappingFactoryClass", e);
}
}
/**
* <p>Return the mapping for the given Java type. Typically, a
* mapping factory will return mappings for types it handles, and

View File

@ -32,10 +32,8 @@ import java.util.Map;
import javax.management.Attribute;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.openmbean.MXBeanMappingFactory;
/**
<p>Helper class for an {@link InvocationHandler} that forwards methods from an
@ -47,7 +45,7 @@ import javax.management.openmbean.MXBeanMappingFactory;
@since 1.6
*/
public class MXBeanProxy {
public MXBeanProxy(Class<?> mxbeanInterface, MXBeanMappingFactory factory) {
public MXBeanProxy(Class<?> mxbeanInterface) {
if (mxbeanInterface == null)
throw new IllegalArgumentException("Null parameter");
@ -55,7 +53,7 @@ public class MXBeanProxy {
final MBeanAnalyzer<ConvertingMethod> analyzer;
try {
analyzer =
MXBeanIntrospector.getInstance(factory).getAnalyzer(mxbeanInterface);
MXBeanIntrospector.getInstance().getAnalyzer(mxbeanInterface);
} catch (NotCompliantMBeanException e) {
throw new IllegalArgumentException(e);
}
@ -63,7 +61,7 @@ public class MXBeanProxy {
}
private class Visitor
implements MBeanAnalyzer.MBeanVisitor<ConvertingMethod, RuntimeException> {
implements MBeanAnalyzer.MBeanVisitor<ConvertingMethod> {
public void visitAttribute(String attributeName,
ConvertingMethod getter,
ConvertingMethod setter) {
@ -161,8 +159,7 @@ public class MXBeanProxy {
Handler handler = handlerMap.get(method);
ConvertingMethod cm = handler.getConvertingMethod();
String prefix = extractPrefix(name);
MXBeanLookup lookup = MXBeanLookup.lookupFor(mbsc, prefix);
MXBeanLookup lookup = MXBeanLookup.lookupFor(mbsc);
MXBeanLookup oldLookup = MXBeanLookup.getLookup();
try {
MXBeanLookup.setLookup(lookup);
@ -174,17 +171,5 @@ public class MXBeanProxy {
}
}
private static String extractPrefix(ObjectName name)
throws MalformedObjectNameException {
String domain = name.getDomain();
int slashslash = domain.lastIndexOf("//");
if (slashslash > 0 && domain.charAt(slashslash - 1) == '/')
slashslash--;
if (slashslash >= 0)
return domain.substring(0, slashslash + 2);
else
return null;
}
private final Map<Method, Handler> handlerMap = newMap();
}

View File

@ -35,7 +35,6 @@ import javax.management.JMX;
import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.openmbean.MXBeanMappingFactory;
/**
* Base class for MXBeans.
@ -62,16 +61,14 @@ public class MXBeanSupport extends MBeanSupport<ConvertingMethod> {
if it does not implement the class {@code mxbeanInterface} or if
that class is not a valid MXBean interface.
*/
public <T> MXBeanSupport(T resource, Class<T> mxbeanInterface,
MXBeanMappingFactory mappingFactory)
public <T> MXBeanSupport(T resource, Class<T> mxbeanInterface)
throws NotCompliantMBeanException {
super(resource, mxbeanInterface, mappingFactory);
super(resource, mxbeanInterface);
}
@Override
MBeanIntrospector<ConvertingMethod>
getMBeanIntrospector(MXBeanMappingFactory mappingFactory) {
return MXBeanIntrospector.getInstance(mappingFactory);
MBeanIntrospector<ConvertingMethod> getMBeanIntrospector() {
return MXBeanIntrospector.getInstance();
}
@Override
@ -159,8 +156,8 @@ public class MXBeanSupport extends MBeanSupport<ConvertingMethod> {
// eventually we could have some logic to supply a default name
synchronized (lock) {
this.mxbeanLookup = MXBeanLookup.Plain.lookupFor(server);
this.mxbeanLookup.addReference(name, getWrappedObject());
this.mxbeanLookup = MXBeanLookup.lookupFor(server);
this.mxbeanLookup.addReference(name, getResource());
this.objectName = name;
}
}
@ -169,19 +166,13 @@ public class MXBeanSupport extends MBeanSupport<ConvertingMethod> {
public void unregister() {
synchronized (lock) {
if (mxbeanLookup != null) {
if (mxbeanLookup.removeReference(objectName, getWrappedObject()))
if (mxbeanLookup.removeReference(objectName, getResource()))
objectName = null;
}
// XXX: need to revisit the whole register/unregister logic in
// the face of wrapping. The mxbeanLookup!=null test is a hack.
// If you wrap an MXBean in a MyWrapperMBean and register it,
// the lookup table should contain the wrapped object. But that
// implies that MyWrapperMBean calls register, which today it
// can't within the public API.
}
}
private final Object lock = new Object(); // for mxbeanLookup and objectName
private MXBeanLookup.Plain mxbeanLookup;
private MXBeanLookup mxbeanLookup;
private ObjectName objectName;
}

View File

@ -1,82 +0,0 @@
/*
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.mbeanserver;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import javax.management.NotCompliantMBeanException;
import javax.management.Notification;
import javax.management.openmbean.MXBeanMappingFactory;
/**
* <p>A variant of {@code StandardMBeanSupport} where the only
* methods included are public getters. This is used by
* {@code QueryNotificationFilter} to pretend that a Notification is
* an MBean so it can have a query evaluated on it. Standard queries
* never set attributes or invoke methods but custom queries could and
* we don't want to allow that. Also we don't want to fail if a
* Notification happens to have inconsistent types in a pair of getX and
* setX methods, and we want to include the Object.getClass() method.
*/
public class NotificationMBeanSupport extends StandardMBeanSupport {
public <T extends Notification> NotificationMBeanSupport(T n)
throws NotCompliantMBeanException {
super(n, Util.<Class<T>>cast(n.getClass()));
}
@Override
MBeanIntrospector<Method> getMBeanIntrospector(MXBeanMappingFactory ignored) {
return introspector;
}
private static class Introspector extends StandardMBeanIntrospector {
@Override
void checkCompliance(Class<?> mbeanType) {}
@Override
List<Method> getMethods(final Class<?> mbeanType)
throws Exception {
List<Method> methods = new ArrayList<Method>();
for (Method m : mbeanType.getMethods()) {
String name = m.getName();
Class<?> ret = m.getReturnType();
if (m.getParameterTypes().length == 0) {
if ((name.startsWith("is") && name.length() > 2 &&
ret == boolean.class) ||
(name.startsWith("get") && name.length() > 3 &&
ret != void.class)) {
methods.add(m);
}
}
}
return methods;
}
}
private static final MBeanIntrospector<Method> introspector =
new Introspector();
}

View File

@ -1,186 +0,0 @@
/*
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.mbeanserver;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.DynamicMBean;
import javax.management.DynamicWrapperMBean;
import javax.management.InvalidAttributeValueException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanRegistration;
import javax.management.MBeanServer;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationEmitter;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.ReflectionException;
/**
* Create wrappers for DynamicMBean that implement NotificationEmitter
* and SendNotification.
*/
public class NotifySupport
implements DynamicMBean2, NotificationEmitter, MBeanRegistration {
private final DynamicMBean mbean;
private final NotificationBroadcasterSupport nbs;
public static DynamicMBean wrap(
DynamicMBean mbean, NotificationBroadcasterSupport nbs) {
return new NotifySupport(mbean, nbs);
}
private NotifySupport(DynamicMBean mbean, NotificationBroadcasterSupport nbs) {
this.mbean = mbean;
this.nbs = nbs;
}
public static NotificationBroadcasterSupport getNB(DynamicMBean mbean) {
if (mbean instanceof NotifySupport)
return ((NotifySupport) mbean).nbs;
else
return null;
}
public String getClassName() {
if (mbean instanceof DynamicMBean2)
return ((DynamicMBean2) mbean).getClassName();
Object w = mbean;
if (w instanceof DynamicWrapperMBean)
w = ((DynamicWrapperMBean) w).getWrappedObject();
return w.getClass().getName();
}
public void preRegister2(MBeanServer mbs, ObjectName name) throws Exception {
if (mbean instanceof DynamicMBean2)
((DynamicMBean2) mbean).preRegister2(mbs, name);
}
public void registerFailed() {
if (mbean instanceof DynamicMBean2)
((DynamicMBean2) mbean).registerFailed();
}
public Object getWrappedObject() {
if (mbean instanceof DynamicWrapperMBean)
return ((DynamicWrapperMBean) mbean).getWrappedObject();
else
return mbean;
}
public ClassLoader getWrappedClassLoader() {
if (mbean instanceof DynamicWrapperMBean)
return ((DynamicWrapperMBean) mbean).getWrappedClassLoader();
else
return mbean.getClass().getClassLoader();
}
public Object getAttribute(String attribute) throws AttributeNotFoundException,
MBeanException,
ReflectionException {
return mbean.getAttribute(attribute);
}
public void setAttribute(Attribute attribute) throws AttributeNotFoundException,
InvalidAttributeValueException,
MBeanException,
ReflectionException {
mbean.setAttribute(attribute);
}
public AttributeList setAttributes(AttributeList attributes) {
return mbean.setAttributes(attributes);
}
public Object invoke(String actionName, Object[] params, String[] signature)
throws MBeanException, ReflectionException {
return mbean.invoke(actionName, params, signature);
}
public MBeanInfo getMBeanInfo() {
return mbean.getMBeanInfo();
}
public AttributeList getAttributes(String[] attributes) {
return mbean.getAttributes(attributes);
}
public void removeNotificationListener(NotificationListener listener,
NotificationFilter filter,
Object handback) throws ListenerNotFoundException {
nbs.removeNotificationListener(listener, filter, handback);
}
public void removeNotificationListener(NotificationListener listener)
throws ListenerNotFoundException {
nbs.removeNotificationListener(listener);
}
public MBeanNotificationInfo[] getNotificationInfo() {
return nbs.getNotificationInfo();
}
public void addNotificationListener(NotificationListener listener,
NotificationFilter filter,
Object handback) {
nbs.addNotificationListener(listener, filter, handback);
}
public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception {
if (mbr() != null)
return mbr().preRegister(server, name);
else
return name;
}
public void postRegister(Boolean registrationDone) {
if (mbr() != null)
mbr().postRegister(registrationDone);
}
public void preDeregister() throws Exception {
if (mbr() != null)
mbr().preDeregister();
}
public void postDeregister() {
if (mbr() != null)
mbr().postDeregister();
}
private MBeanRegistration mbr() {
if (mbean instanceof MBeanRegistration)
return (MBeanRegistration) mbean;
else
return null;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2005-2006 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -231,7 +231,7 @@ final class PerInterface<M> {
/**
* Visitor that sets up the method maps (operations, getters, setters).
*/
private class InitMaps implements MBeanAnalyzer.MBeanVisitor<M, RuntimeException> {
private class InitMaps implements MBeanAnalyzer.MBeanVisitor<M> {
public void visitAttribute(String attributeName,
M getter,
M setter) {

View File

@ -1,71 +0,0 @@
/*
* Copyright 1999-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.mbeanserver;
import java.lang.ref.WeakReference;
import java.util.concurrent.ThreadPoolExecutor;
/**
* <p>A factory for ThreadPoolExecutor objects that allows the same object to
* be shared by all users of the factory that are in the same ThreadGroup.</p>
*/
// We return a ThreadPoolExecutor rather than the more general ExecutorService
// because we need to be able to call allowCoreThreadTimeout so that threads in
// the pool will eventually be destroyed when the pool is no longer in use.
// Otherwise these threads would keep the ThreadGroup alive forever.
public class PerThreadGroupPool<T extends ThreadPoolExecutor> {
private final WeakIdentityHashMap<ThreadGroup, WeakReference<T>> map =
WeakIdentityHashMap.make();
public static interface Create<T extends ThreadPoolExecutor> {
public T createThreadPool(ThreadGroup group);
}
private PerThreadGroupPool() {}
public static <T extends ThreadPoolExecutor> PerThreadGroupPool<T> make() {
return new PerThreadGroupPool<T>();
}
public synchronized T getThreadPoolExecutor(Create<T> create) {
// Find out if there's already an existing executor for the calling
// thread and reuse it. Otherwise, create a new one and store it in
// the executors map. If there is a SecurityManager, the group of
// System.getSecurityManager() is used, else the group of the calling
// thread.
SecurityManager s = System.getSecurityManager();
ThreadGroup group = (s != null) ? s.getThreadGroup() :
Thread.currentThread().getThreadGroup();
WeakReference<T> wr = map.get(group);
T executor = (wr == null) ? null : wr.get();
if (executor == null) {
executor = create.createThreadPool(group);
executor.allowCoreThreadTimeOut(true);
map.put(group, new WeakReference<T>(executor));
}
return executor;
}
}

View File

@ -396,7 +396,7 @@ public class Repository {
// Set domain to default if domain is empty and not already set
if (dom.length() == 0)
name = ObjectName.valueOf(domain + name.toString());
name = Util.newObjectName(domain + name.toString());
// Do we have default domain ?
if (dom == domain) { // ES: OK (dom & domain are interned)
@ -573,7 +573,7 @@ public class Repository {
// Pattern matching in the domain name (*, ?)
final String dom2Match = name.getDomain();
for (String dom : domainTb.keySet()) {
if (Util.wildpathmatch(dom, dom2Match)) {
if (Util.wildmatch(dom, dom2Match)) {
final Map<String,NamedObject> moiTb = domainTb.get(dom);
if (allNames)
result.addAll(moiTb.values());

View File

@ -1,5 +1,5 @@
/*
* Copyright 2005-2008 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 2005 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -35,7 +35,6 @@ import javax.management.IntrospectionException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException;
import javax.management.MBeanOperationInfo;
import javax.management.ManagedOperation;
import javax.management.NotCompliantMBeanException;
import javax.management.NotificationBroadcaster;
import javax.management.NotificationBroadcasterSupport;
@ -119,32 +118,22 @@ class StandardMBeanIntrospector extends MBeanIntrospector<Method> {
@Override
MBeanAttributeInfo getMBeanAttributeInfo(String attributeName,
Method getter, Method setter) throws IntrospectionException {
Method getter, Method setter) {
String description = getAttributeDescription(
attributeName, "Attribute exposed for management",
getter, setter);
return new MBeanAttributeInfo(attributeName, description,
getter, setter);
final String description = "Attribute exposed for management";
try {
return new MBeanAttributeInfo(attributeName, description,
getter, setter);
} catch (IntrospectionException e) {
throw new RuntimeException(e); // should not happen
}
}
@Override
MBeanOperationInfo getMBeanOperationInfo(String operationName,
Method operation) {
final String defaultDescription = "Operation exposed for management";
String description = Introspector.descriptionForElement(operation);
if (description == null)
description = defaultDescription;
int impact = MBeanOperationInfo.UNKNOWN;
ManagedOperation annot = operation.getAnnotation(ManagedOperation.class);
if (annot != null)
impact = annot.impact().getCode();
MBeanOperationInfo mboi = new MBeanOperationInfo(description, operation);
return new MBeanOperationInfo(
mboi.getName(), mboi.getDescription(), mboi.getSignature(),
mboi.getReturnType(), impact, mboi.getDescriptor());
final String description = "Operation exposed for management";
return new MBeanOperationInfo(description, operation);
}
@Override

View File

@ -31,7 +31,6 @@ import javax.management.MBeanInfo;
import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName;
import javax.management.openmbean.MXBeanMappingFactory;
/**
* Base class for Standard MBeans.
@ -58,11 +57,11 @@ public class StandardMBeanSupport extends MBeanSupport<Method> {
*/
public <T> StandardMBeanSupport(T resource, Class<T> mbeanInterfaceType)
throws NotCompliantMBeanException {
super(resource, mbeanInterfaceType, (MXBeanMappingFactory) null);
super(resource, mbeanInterfaceType);
}
@Override
MBeanIntrospector<Method> getMBeanIntrospector(MXBeanMappingFactory ignored) {
MBeanIntrospector<Method> getMBeanIntrospector() {
return StandardMBeanIntrospector.getInstance();
}
@ -84,14 +83,13 @@ public class StandardMBeanSupport extends MBeanSupport<Method> {
@Override
public MBeanInfo getMBeanInfo() {
MBeanInfo mbi = super.getMBeanInfo();
Class<?> resourceClass = getWrappedObject().getClass();
if (!getMBeanInterface().isInterface() ||
StandardMBeanIntrospector.isDefinitelyImmutableInfo(resourceClass))
Class<?> resourceClass = getResource().getClass();
if (StandardMBeanIntrospector.isDefinitelyImmutableInfo(resourceClass))
return mbi;
return new MBeanInfo(mbi.getClassName(), mbi.getDescription(),
mbi.getAttributes(), mbi.getConstructors(),
mbi.getOperations(),
MBeanIntrospector.findNotifications(getWrappedObject()),
MBeanIntrospector.findNotifications(getResource()),
mbi.getDescriptor());
}
}

View File

@ -25,8 +25,6 @@
package com.sun.jmx.mbeanserver;
import com.sun.jmx.defaults.JmxProperties;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -40,25 +38,18 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.SortedMap;
import java.util.SortedSet;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.WeakHashMap;
import java.util.logging.Level;
import javax.management.MBeanServer;
import javax.management.MBeanServerDelegate;
import javax.management.MBeanServerFactory;
import javax.management.ObjectInstance;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.loading.ClassLoaderRepository;
import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR;
public class Util {
private final static int NAMESPACE_SEPARATOR_LENGTH =
NAMESPACE_SEPARATOR.length();
public final static char[] ILLEGAL_MBEANSERVER_NAME_CHARS=";:*?".
toCharArray();
public static ObjectName newObjectName(String string) {
try {
return new ObjectName(string);
} catch (MalformedObjectNameException e) {
throw new IllegalArgumentException(e);
}
}
static <K, V> Map<K, V> newMap() {
return new HashMap<K, V>();
@ -89,10 +80,6 @@ public class Util {
return new LinkedHashMap<K, V>();
}
static <K, V> WeakHashMap<K, V> newWeakHashMap() {
return new WeakHashMap<K, V>();
}
static <E> Set<E> newSet() {
return new HashSet<E>();
}
@ -251,451 +238,4 @@ public class Util {
public static boolean wildmatch(String str, String pat) {
return wildmatch(str,pat,0,str.length(),0,pat.length());
}
/**
* Matches a string against a pattern, as a name space path.
* This is a special matching where * and ?? don't match //.
* The string is split in sub-strings separated by //, and the
* pattern is split in sub-patterns separated by //. Each sub-string
* is matched against its corresponding sub-pattern.
* so <elt-1>//<elt2>//...//<elt-n> matches <pat-1>//<pat-2>//...//<pat-q>
* only if n==q and for ( i = 1 => n) elt-i matches pat-i.
*
* In addition, if we encounter a pattern element which is exactly
* **, it can match any number of path-elements - but it must match at
* least one element.
* When we encounter such a meta-wildcard, we remember its position
* and the position in the string path, and we advance both the pattern
* and the string. Later, if we encounter a mismatch in pattern & string,
* we rewind the position in pattern to just after the meta-wildcard,
* and we backtrack the string to i+1 element after the position
* we had when we first encountered the meta-wildcard, i being the
* position when we last backtracked the string.
*
* The backtracking logic is an adaptation of the logic in wildmatch
* above.
* See test/javax/mangement/ObjectName/ApplyWildcardTest.java
*
* Note: this thing is called 'wild' - and that's for a reason ;-)
**/
public static boolean wildpathmatch(String str, String pat) {
final int strlen = str.length();
final int patlen = pat.length();
int stri = 0;
int pati = 0;
int starstri; // index for backtrack if "**" attempt fails
int starpati; // index for backtrack if "**" attempt fails
starstri = starpati = -1;
while (true) {
// System.out.println("pati="+pati+", stri="+stri);
final int strend = str.indexOf(NAMESPACE_SEPARATOR, stri);
final int patend = pat.indexOf(NAMESPACE_SEPARATOR, pati);
// no // remaining in either string or pattern: simple wildmatch
// until end of string.
if (strend == -1 && patend == -1) {
// System.out.println("last sub pattern, last sub element...");
// System.out.println("wildmatch("+str.substring(stri,strlen)+
// ","+pat.substring(pati,patlen)+")");
return wildmatch(str,pat,stri,strlen,pati,patlen);
}
// no // remaining in string, but at least one remaining in
// pattern
// => no match
if (strend == -1) {
// System.out.println("pattern has more // than string...");
return false;
}
// strend is != -1, but patend might.
// detect wildcard **
if (patend == pati+2 && pat.charAt(pati)=='*' &&
pat.charAt(pati+1)=='*') {
// if we reach here we know that neither strend nor patend are
// equals to -1.
stri = strend + NAMESPACE_SEPARATOR_LENGTH;
pati = patend + NAMESPACE_SEPARATOR_LENGTH;
starpati = pati; // position just after **// in pattern
starstri = stri; // we eat 1 element in string, and remember
// the position for backtracking and eating
// one more element if needed.
// System.out.println("starpati="+pati);
continue;
}
// This is a bit hacky: * can match // when // is at the end
// of the string, so we include the // delimiter in the pattern
// matching. Either we're in the middle of the path, so including
// // both at the end of the pattern and at the end of the string
// has no effect - match(*//,dfsd//) is equivalent to match(*,dfsd)
// or we're at the end of the pattern path, in which case
// including // at the end of the string will have the desired
// effect (provided that we detect the end of matching correctly,
// see further on).
//
final int endpat =
((patend > -1)?patend+NAMESPACE_SEPARATOR_LENGTH:patlen);
final int endstr =
((strend > -1)?strend+NAMESPACE_SEPARATOR_LENGTH:strlen);
// if we reach the end of the pattern, or if elt-i & pat-i
// don't match, we have a mismatch.
// Note: we know that strend != -1, therefore patend==-1
// indicates a mismatch unless pattern can match
// a // at the end, and strend+2=strlen.
// System.out.println("wildmatch("+str.substring(stri,endstr)+","+
// pat.substring(pati,endpat)+")");
if (!wildmatch(str,pat,stri,endstr,pati,endpat)) {
// System.out.println("nomatch");
// if we have a mismatch and didn't encounter any meta-wildcard,
// we return false. String & pattern don't match.
if (starpati < 0) return false;
// If we reach here, we had a meta-wildcard.
// We need to backtrack to the wildcard, and make it eat an
// additional string element.
//
stri = str.indexOf(NAMESPACE_SEPARATOR, starstri);
// System.out.println("eating one additional element? "+stri);
// If there's no more elements to eat, string and pattern
// don't match => return false.
if (stri == -1) return false;
// Backtrack to where we were when we last matched against
// the meta-wildcard, make it eat an additional path element,
// remember the new positions, and continue from there...
//
stri = stri + NAMESPACE_SEPARATOR_LENGTH;
starstri = stri;
pati = starpati;
// System.out.println("skiping to stri="+stri);
continue;
}
// Here we know that strend > -1 but we can have patend == -1.
//
// So if we reach here, we know pat-i+//? has matched
// elt-i+//
//
// If patend==-1, we know that there was no delimiter
// at the end of the pattern, that we are at the last pattern,
// and therefore that pat-i has matched elt-i+//
//
// In that case we can consider that we have a match only if
// elt-i is also the last path element in the string, which is
// equivalent to saying that strend+2==strlen.
//
if (patend == -1 && starpati == -1)
return (strend+NAMESPACE_SEPARATOR_LENGTH==strlen);
// patend != -1, or starpati > -1 so there remains something
// to match.
// go to next pair: elt-(i+1) pat-(i+1);
stri = strend + NAMESPACE_SEPARATOR_LENGTH;
pati = (patend==-1)?pati:(patend + NAMESPACE_SEPARATOR_LENGTH);
}
}
/**
* Returns true if the ObjectName's {@code domain} is selected by the
* given {@code pattern}.
*/
public static boolean isDomainSelected(String domain, String pattern) {
if (domain == null || pattern == null)
throw new IllegalArgumentException("null");
return Util.wildpathmatch(domain,pattern);
}
/**
* Filters a set of ObjectName according to a given pattern.
*
* @param pattern the pattern that the returned names must match.
* @param all the set of names to filter.
* @return a set of ObjectName from which non matching names
* have been removed.
*/
public static Set<ObjectName> filterMatchingNames(ObjectName pattern,
Set<ObjectName> all) {
// If no pattern, just return all names
if (pattern == null
|| all.isEmpty()
|| ObjectName.WILDCARD.equals(pattern))
return all;
// If there's a pattern, do the matching.
final Set<ObjectName> res = equivalentEmptySet(all);
for (ObjectName n : all) if (pattern.apply(n)) res.add(n);
return res;
}
/**
* Filters a set of ObjectInstance according to a given pattern.
*
* @param pattern the pattern that the returned names must match.
* @param all the set of instances to filter.
* @return a set of ObjectInstance from which non matching instances
* have been removed.
*/
public static Set<ObjectInstance>
filterMatchingInstances(ObjectName pattern,
Set<ObjectInstance> all) {
// If no pattern, just return all names
if (pattern == null
|| all.isEmpty()
|| ObjectName.WILDCARD.equals(pattern))
return all;
// If there's a pattern, do the matching.
final Set<ObjectInstance> res = equivalentEmptySet(all);
for (ObjectInstance n : all) {
if (n == null) continue;
if (pattern.apply(n.getObjectName()))
res.add(n);
}
return res;
}
/**
* An abstract ClassLoaderRepository that contains a single class loader.
**/
private final static class SingleClassLoaderRepository
implements ClassLoaderRepository {
private final ClassLoader singleLoader;
SingleClassLoaderRepository(ClassLoader loader) {
this.singleLoader = loader;
}
ClassLoader getSingleClassLoader() {
return singleLoader;
}
private Class<?> loadClass(String className, ClassLoader loader)
throws ClassNotFoundException {
return Class.forName(className, false, loader);
}
public Class<?> loadClass(String className)
throws ClassNotFoundException {
return loadClass(className, getSingleClassLoader());
}
public Class<?> loadClassWithout(ClassLoader exclude,
String className) throws ClassNotFoundException {
final ClassLoader loader = getSingleClassLoader();
if (exclude != null && exclude.equals(loader))
throw new ClassNotFoundException(className);
return loadClass(className, loader);
}
public Class<?> loadClassBefore(ClassLoader stop, String className)
throws ClassNotFoundException {
return loadClassWithout(stop, className);
}
}
/**
* Returns a ClassLoaderRepository that contains a single class loader.
* @param loader the class loader contained in the returned repository.
* @return a ClassLoaderRepository that contains the single loader.
*/
public static ClassLoaderRepository getSingleClassLoaderRepository(
final ClassLoader loader) {
return new SingleClassLoaderRepository(loader);
}
/**
* Returns the name of the given MBeanServer that should be put in a
* permission you need.
* This corresponds to the
* {@code *[;mbeanServerName=<mbeanServerName>[;*]]} property
* embedded in the MBeanServerId attribute of the
* server's {@link MBeanServerDelegate}.
*
* @param server The MBean server
* @return the name of the MBeanServer, or "*" if the name couldn't be
* obtained, or {@value MBeanServerFactory#DEFAULT_MBEANSERVER_NAME}
* if there was no name.
*/
public static String getMBeanServerSecurityName(MBeanServer server) {
final String notfound = "*";
try {
final String mbeanServerId = (String)
server.getAttribute(MBeanServerDelegate.DELEGATE_NAME,
"MBeanServerId");
final String found = extractMBeanServerName(mbeanServerId);
if (found.length()==0)
return MBeanServerFactory.DEFAULT_MBEANSERVER_NAME;
return found;
} catch (Exception x) {
logshort("Failed to retrieve MBeanServerName for server, " +
"using \"*\"",x);
return notfound;
}
}
/**
* Returns the name of the MBeanServer embedded in the given
* mbeanServerId. If the given mbeanServerId doesn't contain any name,
* an empty String is returned.
* The MBeanServerId is expected to be of the form:
* {@code *[;mbeanServerName=<mbeanServerName>[;*]]}
* @param mbeanServerId The MBean server ID
* @return the name of the MBeanServer if found, or "" if the name was
* not present in the mbeanServerId.
*/
public static String extractMBeanServerName(String mbeanServerId) {
if (mbeanServerId==null) return "";
final String beginMarker=";mbeanServerName=";
final String endMarker=";";
final int found = mbeanServerId.indexOf(beginMarker);
if (found < 0) return "";
final int start = found + beginMarker.length();
final int stop = mbeanServerId.indexOf(endMarker, start);
return mbeanServerId.substring(start,
(stop < 0 ? mbeanServerId.length() : stop));
}
/**
* Insert the given mbeanServerName into the given mbeanServerId.
* If mbeanServerName is null, empty, or equals to "-", the returned
* mbeanServerId will not contain any mbeanServerName.
* @param mbeanServerId The mbeanServerId in which to insert
* mbeanServerName
* @param mbeanServerName The mbeanServerName
* @return an mbeanServerId containing the given mbeanServerName
* @throws IllegalArgumentException if mbeanServerId already contains
* a different name, or if the given mbeanServerName is not valid.
*/
public static String insertMBeanServerName(String mbeanServerId,
String mbeanServerName) {
final String found = extractMBeanServerName(mbeanServerId);
if (found.length() > 0 &&
found.equals(checkServerName(mbeanServerName)))
return mbeanServerId;
if (found.length() > 0 && !isMBeanServerNameUndefined(found))
throw new IllegalArgumentException(
"MBeanServerName already defined");
if (isMBeanServerNameUndefined(mbeanServerName))
return mbeanServerId;
final String beginMarker=";mbeanServerName=";
return mbeanServerId+beginMarker+checkServerName(mbeanServerName);
}
/**
* Returns true if the given mbeanServerName corresponds to an
* undefined MBeanServerName.
* The mbeanServerName is considered undefined if it is one of:
* {@code null} or {@value MBeanServerFactory#DEFAULT_MBEANSERVER_NAME}.
* @param mbeanServerName The mbeanServerName, as returned by
* {@link #extractMBeanServerName(String)}.
* @return true if the given name corresponds to one of the forms that
* denotes an undefined MBeanServerName.
*/
public static boolean isMBeanServerNameUndefined(String mbeanServerName) {
return mbeanServerName == null ||
MBeanServerFactory.DEFAULT_MBEANSERVER_NAME.equals(mbeanServerName);
}
/**
* Check that the provided mbeanServername is syntactically valid.
* @param mbeanServerName An mbeanServerName, or {@code null}.
* @return mbeanServerName, or {@value
* MBeanServerFactory#DEFAULT_MBEANSERVER_NAME} if {@code mbeanServerName}
* is {@code null}.
* @throws IllegalArgumentException if mbeanServerName contains illegal
* characters, or is empty, or is {@code "-"}.
* Illegal characters are {@link #ILLEGAL_MBEANSERVER_NAME_CHARS}.
*/
public static String checkServerName(String mbeanServerName) {
if ("".equals(mbeanServerName))
throw new IllegalArgumentException(
"\"\" is not a valid MBean server name");
if ("-".equals(mbeanServerName))
throw new IllegalArgumentException(
"\"-\" is not a valid MBean server name");
if (isMBeanServerNameUndefined(mbeanServerName))
return MBeanServerFactory.DEFAULT_MBEANSERVER_NAME;
for (char c : ILLEGAL_MBEANSERVER_NAME_CHARS) {
if (mbeanServerName.indexOf(c) >= 0)
throw new IllegalArgumentException(
"invalid character in MBeanServer name: "+c);
}
return mbeanServerName;
}
/**
* Get the MBeanServer name that should be put in a permission you need.
*
* @param delegate The MBeanServerDelegate
* @return The MBeanServer name - or {@value
* MBeanServerFactory#DEFAULT_MBEANSERVER_NAME} if there was no name.
*/
public static String getMBeanServerSecurityName(
MBeanServerDelegate delegate) {
try {
final String serverName = delegate.getMBeanServerName();
if (isMBeanServerNameUndefined(serverName))
return MBeanServerFactory.DEFAULT_MBEANSERVER_NAME;
return serverName;
} catch (Exception x) {
logshort("Failed to retrieve MBeanServerName from delegate, " +
"using \"*\"",x);
return "*";
}
}
// Log the exception and its causes without logging the stack trace.
// Use with care - it is usually preferable to log the whole stack trace!
// We don't want to log the whole stack trace here: logshort() is
// called in those cases where the exception might not be abnormal.
private static void logshort(String msg, Throwable t) {
if (JmxProperties.MISC_LOGGER.isLoggable(Level.FINE)) {
StringBuilder toprint = new StringBuilder(msg);
do {
toprint.append("\nCaused By: ").append(String.valueOf(t));
} while ((t=t.getCause())!=null);
JmxProperties.MISC_LOGGER.fine(toprint.toString());
}
}
public static <T> Set<T> cloneSet(Set<T> set) {
if (set instanceof SortedSet<?>) {
@SuppressWarnings("unchecked")
SortedSet<T> sset = (SortedSet<T>) set;
set = new TreeSet<T>(sset.comparator());
set.addAll(sset);
} else
set = new HashSet<T>(set);
return set;
}
public static <T> Set<T> equivalentEmptySet(Set<T> set) {
if (set instanceof SortedSet<?>) {
@SuppressWarnings("unchecked")
SortedSet<T> sset = (SortedSet<T>) set;
set = new TreeSet<T>(sset.comparator());
} else
set = new HashSet<T>();
return set;
}
// This exception is used when wrapping a class that throws IOException
// in a class that doesn't.
// The typical example for this are JMXNamespaces, when the sub
// MBeanServer can be remote.
//
public static RuntimeException newRuntimeIOException(IOException io) {
final String msg = "Communication failed with underlying resource: "+
io.getMessage();
return new RuntimeException(msg,io);
}
}

View File

@ -1,463 +0,0 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.namespace;
import com.sun.jmx.defaults.JmxProperties;
import com.sun.jmx.mbeanserver.Util;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Queue;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.InstanceNotFoundException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanPermission;
import javax.management.MBeanServerDelegate;
import javax.management.MBeanServerNotification;
import javax.management.Notification;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.QueryExp;
import javax.management.namespace.JMXDomain;
/**
* A DomainInterceptor wraps a JMXDomain.
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
* @since 1.7
*/
public class DomainInterceptor extends HandlerInterceptor<JMXDomain> {
// TODO: Ideally DomainInterceptor should be replaced by
// something at Repository level.
// The problem there will be that we may need to
// reinstantiate the 'queryPerformedByRepos' boolean
// [or we will need to wrap the repository in
// a 'RepositoryInterceptor'?]
// Also there's no real need for a DomainInterceptor to
// extend RewritingMBeanServerConnection.
/**
* A logger for this class.
**/
private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
private final String domainName;
private volatile ObjectName ALL;
private final String serverName;
private volatile NotificationListener mbsListener;
private static class PatternNotificationFilter
implements NotificationFilter {
final ObjectName pattern;
public PatternNotificationFilter(ObjectName pattern) {
this.pattern = pattern==null?ObjectName.WILDCARD:pattern;
}
public boolean isNotificationEnabled(Notification notification) {
if (!(notification instanceof MBeanServerNotification))
return false;
final MBeanServerNotification mbsn =
(MBeanServerNotification) notification;
if (pattern.apply(mbsn.getMBeanName()))
return true;
return false;
}
static final long serialVersionUID = 7409950927025262111L;
}
/**
* Creates a new instance of NamespaceInterceptor
*/
public DomainInterceptor(String serverName,
JMXDomain handler,
String domainName) {
super(handler);
this.domainName = domainName;
this.serverName = serverName;
ALL = ObjectName.valueOf(domainName+":*");
}
@Override
public String toString() {
return this.getClass().getName()+"(parent="+serverName+
", domain="+this.domainName+")";
}
final void connectDelegate(final MBeanServerDelegate delegate)
throws InstanceNotFoundException {
final NotificationFilter filter =
new PatternNotificationFilter(getPatternFor(null));
synchronized (this) {
if (mbsListener == null) {
mbsListener = new NotificationListener() {
public void handleNotification(Notification notification,
Object handback) {
if (filter.isNotificationEnabled(notification))
delegate.sendNotification(notification);
}
};
}
}
getHandlerInterceptorMBean().
addMBeanServerNotificationListener(mbsListener, filter);
}
final void disconnectDelegate()
throws InstanceNotFoundException, ListenerNotFoundException {
final NotificationListener l;
synchronized (this) {
l = mbsListener;
if (l == null) return;
mbsListener = null;
}
getHandlerInterceptorMBean().removeMBeanServerNotificationListener(l);
}
public final void addPostRegisterTask(Queue<Runnable> queue,
final MBeanServerDelegate delegate) {
if (queue == null)
throw new IllegalArgumentException("task queue must not be null");
final Runnable task1 = new Runnable() {
public void run() {
try {
connectDelegate(delegate);
} catch (Exception x) {
throw new UnsupportedOperationException(
"notification forwarding",x);
}
}
};
queue.add(task1);
}
public final void addPostDeregisterTask(Queue<Runnable> queue,
final MBeanServerDelegate delegate) {
if (queue == null)
throw new IllegalArgumentException("task queue must not be null");
final Runnable task1 = new Runnable() {
public void run() {
try {
disconnectDelegate();
} catch (Exception x) {
throw new UnsupportedOperationException(
"notification forwarding",x);
}
}
};
queue.add(task1);
}
// No name conversion for JMXDomains...
// Throws IllegalArgumentException if targetName.getDomain() is not
// in the domain handled.
//
@Override
protected ObjectName toSource(ObjectName targetName) {
if (targetName == null) return null;
if (targetName.isDomainPattern()) return targetName;
final String targetDomain = targetName.getDomain();
// TODO: revisit this. RuntimeOperationsException may be better?
//
if (!targetDomain.equals(domainName))
throw new IllegalArgumentException(targetName.toString());
return targetName;
}
// No name conversion for JMXDomains...
@Override
protected ObjectName toTarget(ObjectName sourceName) {
return sourceName;
}
/**
* No rewriting: always return sources - stripping instances for which
* the caller doesn't have permissions.
**/
@Override
Set<ObjectInstance> processOutputInstances(Set<ObjectInstance> sources) {
if (sources == null || sources.isEmpty() || !checkOn())
return sources;
final Set<ObjectInstance> res = Util.equivalentEmptySet(sources);
for (ObjectInstance o : sources) {
if (checkQuery(o.getObjectName(), "queryMBeans"))
res.add(o);
}
return res;
}
/**
* No rewriting: always return sourceNames - stripping names for which
* the caller doesn't have permissions.
**/
@Override
Set<ObjectName> processOutputNames(Set<ObjectName> sourceNames) {
if (sourceNames == null || sourceNames.isEmpty() || !checkOn())
return sourceNames;
final Set<ObjectName> res = Util.equivalentEmptySet(sourceNames);
for (ObjectName o : sourceNames) {
if (checkQuery(o, "queryNames"))
res.add(o);
}
return res;
}
/** No rewriting: always return source **/
@Override
ObjectInstance processOutputInstance(ObjectInstance source) {
return source;
}
@Override
public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
try {
// We don't trust the wrapped JMXDomain...
final ObjectName pattern = getPatternFor(name);
final Set<ObjectName> res = super.queryNames(pattern,query);
return Util.filterMatchingNames(pattern,res);
} catch (Exception x) {
if (LOG.isLoggable(Level.FINE))
LOG.fine("Unexpected exception raised in queryNames: "+x);
LOG.log(Level.FINEST,"Unexpected exception raised in queryNames",x);
return Collections.emptySet();
}
}
// Compute a new pattern which is a sub pattern of 'name' but only selects
// the MBeans in domain 'domainName'
// When we reach here, it has been verified that 'name' matches our domain
// name (done by DomainDispatchInterceptor)
private ObjectName getPatternFor(final ObjectName name) {
if (name == null) return ALL;
if (name.getDomain().equals(domainName)) return name;
return name.withDomain(domainName);
}
@Override
public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
try {
// We don't trust the wrapped JMXDomain...
final ObjectName pattern = getPatternFor(name);
final Set<ObjectInstance> res = super.queryMBeans(pattern,query);
return Util.filterMatchingInstances(pattern,res);
} catch (Exception x) {
if (LOG.isLoggable(Level.FINE))
LOG.fine("Unexpected exception raised in queryNames: "+x);
LOG.log(Level.FINEST,"Unexpected exception raised in queryNames",x);
return Collections.emptySet();
}
}
@Override
public String getDefaultDomain() {
return domainName;
}
@Override
public String[] getDomains() {
return new String[] {domainName};
}
// We call getMBeanCount() on the namespace rather than on the
// source server in order to avoid counting MBeans which are not
// in the domain.
@Override
public Integer getMBeanCount() {
return getHandlerInterceptorMBean().getMBeanCount();
}
private boolean checkOn() {
final SecurityManager sm = System.getSecurityManager();
return (sm != null);
}
//
// Implements permission checks.
//
@Override
void check(ObjectName routingName, String member, String action) {
if (!checkOn()) return;
final String act = (action==null)?"-":action;
if("queryMBeans".equals(act) || "queryNames".equals(act)) {
// This is tricky. check with 3 parameters is called
// by queryNames/queryMBeans before performing the query.
// At this point we must check with no class name.
// Therefore we pass a className of "-".
// The filtering will be done later - processOutputNames and
// processOutputInstance will call checkQuery.
//
check(routingName, "-", "-", act);
} else {
// This is also tricky:
// passing null here will cause check to retrieve the classname,
// if needed.
check(routingName, null, member, act);
}
}
//
// Implements permission checks.
//
@Override
void checkCreate(ObjectName routingName, String className, String action) {
if (!checkOn()) return;
check(routingName,className,"-",action);
}
//
// Implements permission checks.
//
void check(ObjectName routingName, String className, String member,
String action) {
if (!checkOn()) return;
final MBeanPermission perm;
final String act = (action==null)?"-":action;
if ("getDomains".equals(act)) { // ES: OK
perm = new MBeanPermission(serverName,"-",member,
routingName,act);
} else {
final String clazz =
(className==null)?getClassName(routingName):className;
perm = new MBeanPermission(serverName,clazz,member,
routingName,act);
}
final SecurityManager sm = System.getSecurityManager();
if (sm != null)
sm.checkPermission(perm);
}
String getClassName(ObjectName routingName) {
if (routingName == null || routingName.isPattern()) return "-";
try {
return getHandlerInterceptorMBean().getSourceServer().
getObjectInstance(routingName).getClassName();
} catch (InstanceNotFoundException ex) {
LOG.finest("Can't get class name for "+routingName+
", using \"-\". Cause is: "+ex);
return "-";
}
}
//
// Implements permission filters for attributes...
//
@Override
AttributeList checkAttributes(ObjectName routingName,
AttributeList attributes, String action) {
if (!checkOn()) return attributes;
final String className = getClassName(routingName);
check(routingName,className,"-",action);
if (attributes == null || attributes.isEmpty()) return attributes;
final AttributeList res = new AttributeList();
for (Attribute at : attributes.asList()) {
try {
check(routingName,className,at.getName(),action);
res.add(at);
} catch (SecurityException x) { // DLS: OK
continue;
}
}
return res;
}
//
// Implements permission filters for attributes...
//
@Override
String[] checkAttributes(ObjectName routingName, String[] attributes,
String action) {
if (!checkOn()) return attributes;
final String className = getClassName(routingName);
check(routingName,className,"-",action);
if (attributes == null || attributes.length==0) return attributes;
final List<String> res = new ArrayList<String>(attributes.length);
for (String at : attributes) {
try {
check(routingName,className,at,action);
res.add(at);
} catch (SecurityException x) { // DLS: OK
continue;
}
}
return res.toArray(new String[res.size()]);
}
//
// Implements permission filters for domains...
//
@Override
String[] checkDomains(String[] domains, String action) {
if (domains == null || domains.length==0 || !checkOn())
return domains;
int count=0;
for (int i=0;i<domains.length;i++) {
try {
check(ObjectName.valueOf(domains[i]+":x=x"),"-",
"-","getDomains");
} catch (SecurityException x) { // DLS: OK
count++;
domains[i]=null;
}
}
if (count == 0) return domains;
final String[] res = new String[domains.length-count];
count = 0;
for (int i=0;i<domains.length;i++)
if (domains[i]!=null) res[count++]=domains[i];
return res;
}
//
// Implements permission filters for queries...
//
@Override
boolean checkQuery(ObjectName routingName, String action) {
try {
final String className = getClassName(routingName);
check(routingName,className,"-",action);
return true;
} catch (SecurityException x) { // DLS: OK
return false;
}
}
}

View File

@ -1,734 +0,0 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.namespace;
import com.sun.jmx.defaults.JmxProperties;
import com.sun.jmx.interceptor.MBeanServerInterceptor;
import com.sun.jmx.mbeanserver.Util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.InvalidAttributeValueException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.OperationsException;
import javax.management.QueryExp;
import javax.management.ReflectionException;
import javax.management.RuntimeOperationsException;
import javax.management.loading.ClassLoaderRepository;
import javax.management.namespace.JMXNamespace;
/**
* This interceptor wraps a JMXNamespace, and performs
* {@code ObjectName} rewriting. {@code HandlerInterceptor} are
* created and managed by a {@link NamespaceDispatchInterceptor} or a
* {@link DomainDispatchInterceptor}.
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
* @since 1.7
*/
public abstract class HandlerInterceptor<T extends JMXNamespace>
extends RoutingMBeanServerConnection<MBeanServer>
implements MBeanServerInterceptor {
/**
* A logger for this class.
**/
private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
// The wrapped JMXNamespace
private final T handler;
/**
* Creates a new instance of HandlerInterceptor
*/
public HandlerInterceptor(T handler) {
if (handler == null) throw new IllegalArgumentException("null");
this.handler = handler;
}
//
// The {@code source} connection is a connection to the MBeanServer
// that contains the actual MBeans.
// In the case of cascading, that would be a connection to the sub
// agent. Practically, this is JMXNamespace.getSourceServer();
//
@Override
protected MBeanServer source() {
return handler.getSourceServer();
}
// The MBeanServer on which getClassLoader / getClassLoaderFor
// will be called.
// The NamespaceInterceptor overrides this method - so that it
// getClassLoader / getClassLoaderFor don't trigger the loop
// detection mechanism.
//
MBeanServer getServerForLoading() {
return source();
}
// The namespace or domain handler - this either a JMXNamespace or a
// a JMXDomain
T getHandlerInterceptorMBean() {
return handler;
}
// If the underlying JMXNamespace throws an IO, the IO will be
// wrapped in a RuntimeOperationsException.
RuntimeException handleIOException(IOException x,String fromMethodName,
Object... params) {
// Must do something here?
if (LOG.isLoggable(Level.FINEST)) {
LOG.finest("IO Exception in "+fromMethodName+": "+x+
" - "+" rethrowing as RuntimeOperationsException.");
}
throw new RuntimeOperationsException(
Util.newRuntimeIOException(x));
}
// From MBeanServerConnection: catch & handles IOException
@Override
public AttributeList getAttributes(ObjectName name, String[] attributes)
throws InstanceNotFoundException, ReflectionException {
try {
final String[] authorized =
checkAttributes(name,attributes,"getAttribute");
final AttributeList attrList =
super.getAttributes(name,authorized);
return attrList;
} catch (IOException ex) {
throw handleIOException(ex,"getAttributes",name,attributes);
}
}
// From MBeanServer
public ClassLoader getClassLoaderFor(ObjectName mbeanName)
throws InstanceNotFoundException {
final ObjectName sourceName = toSourceOrRuntime(mbeanName);
try {
check(mbeanName,null,"getClassLoaderFor");
return getServerForLoading().getClassLoaderFor(sourceName);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// From MBeanServer
public ClassLoader getClassLoader(ObjectName loaderName)
throws InstanceNotFoundException {
final ObjectName sourceName = toSourceOrRuntime(loaderName);
try {
check(loaderName,null,"getClassLoader");
return getServerForLoading().getClassLoader(sourceName);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// From MBeanServer
public ObjectInstance registerMBean(Object object, ObjectName name)
throws InstanceAlreadyExistsException, MBeanRegistrationException,
NotCompliantMBeanException {
final ObjectName sourceName = newSourceMBeanName(name);
try {
checkCreate(name,object.getClass().getName(),"registerMBean");
return processOutputInstance(
source().registerMBean(object,sourceName));
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public void removeNotificationListener(ObjectName name, ObjectName listener)
throws InstanceNotFoundException, ListenerNotFoundException {
try {
check(name,null,"removeNotificationListener");
super.removeNotificationListener(name,listener);
} catch (IOException ex) {
throw handleIOException(ex,"removeNotificationListener",name,listener);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public String getDefaultDomain() {
try {
return super.getDefaultDomain();
} catch (IOException ex) {
throw handleIOException(ex,"getDefaultDomain");
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public String[] getDomains() {
try {
check(null,null,"getDomains");
final String[] domains = super.getDomains();
return checkDomains(domains,"getDomains");
} catch (IOException ex) {
throw handleIOException(ex,"getDomains");
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public Integer getMBeanCount() {
try {
return super.getMBeanCount();
} catch (IOException ex) {
throw handleIOException(ex,"getMBeanCount");
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public void setAttribute(ObjectName name, Attribute attribute)
throws InstanceNotFoundException, AttributeNotFoundException,
InvalidAttributeValueException, MBeanException,
ReflectionException {
try {
check(name,
(attribute==null?null:attribute.getName()),
"setAttribute");
super.setAttribute(name,attribute);
} catch (IOException ex) {
throw handleIOException(ex,"setAttribute",name, attribute);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
if (name == null) name=ObjectName.WILDCARD;
try {
checkPattern(name,null,"queryNames");
return super.queryNames(name,query);
} catch (IOException ex) {
throw handleIOException(ex,"queryNames",name, query);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
if (name == null) name=ObjectName.WILDCARD;
try {
checkPattern(name,null,"queryMBeans");
return super.queryMBeans(name,query);
} catch (IOException ex) {
throw handleIOException(ex,"queryMBeans",name, query);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public boolean isInstanceOf(ObjectName name, String className)
throws InstanceNotFoundException {
try {
check(name, null, "isInstanceOf");
return super.isInstanceOf(name, className);
} catch (IOException ex) {
throw handleIOException(ex,"isInstanceOf",name, className);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public ObjectInstance createMBean(String className, ObjectName name)
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException {
try {
checkCreate(name, className, "instantiate");
checkCreate(name, className, "registerMBean");
return super.createMBean(className, name);
} catch (IOException ex) {
throw handleIOException(ex,"createMBean",className, name);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public ObjectInstance createMBean(String className, ObjectName name,
ObjectName loaderName)
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, InstanceNotFoundException {
try {
checkCreate(name, className, "instantiate");
checkCreate(name, className, "registerMBean");
return super.createMBean(className, name, loaderName);
} catch (IOException ex) {
throw handleIOException(ex,"createMBean",className, name, loaderName);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public Object getAttribute(ObjectName name, String attribute)
throws MBeanException, AttributeNotFoundException,
InstanceNotFoundException, ReflectionException {
try {
check(name, attribute, "getAttribute");
return super.getAttribute(name, attribute);
} catch (IOException ex) {
throw handleIOException(ex,"getAttribute",name, attribute);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public void removeNotificationListener(ObjectName name, ObjectName listener,
NotificationFilter filter, Object handback)
throws InstanceNotFoundException, ListenerNotFoundException {
try {
check(name,null,"removeNotificationListener");
super.removeNotificationListener(name, listener, filter, handback);
} catch (IOException ex) {
throw handleIOException(ex,"removeNotificationListener",name,
listener, filter, handback);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public void removeNotificationListener(ObjectName name,
NotificationListener listener, NotificationFilter filter,
Object handback)
throws InstanceNotFoundException, ListenerNotFoundException {
try {
check(name,null,"removeNotificationListener");
super.removeNotificationListener(name, listener, filter, handback);
} catch (IOException ex) {
throw handleIOException(ex,"removeNotificationListener",name,
listener, filter, handback);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public void removeNotificationListener(ObjectName name,
NotificationListener listener)
throws InstanceNotFoundException, ListenerNotFoundException {
try {
check(name,null,"removeNotificationListener");
super.removeNotificationListener(name, listener);
} catch (IOException ex) {
throw handleIOException(ex,"removeNotificationListener",name,
listener);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public void addNotificationListener(ObjectName name,
NotificationListener listener, NotificationFilter filter,
Object handback) throws InstanceNotFoundException {
try {
check(name,null,"addNotificationListener");
super.addNotificationListener(name, listener, filter, handback);
} catch (IOException ex) {
throw handleIOException(ex,"addNotificationListener",name,
listener, filter, handback);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public void addNotificationListener(ObjectName name, ObjectName listener,
NotificationFilter filter, Object handback)
throws InstanceNotFoundException {
try {
check(name,null,"addNotificationListener");
super.addNotificationListener(name, listener, filter, handback);
} catch (IOException ex) {
throw handleIOException(ex,"addNotificationListener",name,
listener, filter, handback);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public boolean isRegistered(ObjectName name) {
try {
return super.isRegistered(name);
} catch (IOException ex) {
throw handleIOException(ex,"isRegistered",name);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public void unregisterMBean(ObjectName name)
throws InstanceNotFoundException, MBeanRegistrationException {
try {
check(name, null, "unregisterMBean");
super.unregisterMBean(name);
} catch (IOException ex) {
throw handleIOException(ex,"unregisterMBean",name);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public MBeanInfo getMBeanInfo(ObjectName name)
throws InstanceNotFoundException, IntrospectionException,
ReflectionException {
try {
check(name, null, "getMBeanInfo");
return super.getMBeanInfo(name);
} catch (IOException ex) {
throw handleIOException(ex,"getMBeanInfo",name);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public ObjectInstance getObjectInstance(ObjectName name)
throws InstanceNotFoundException {
try {
check(name, null, "getObjectInstance");
return super.getObjectInstance(name);
} catch (IOException ex) {
throw handleIOException(ex,"getObjectInstance",name);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public ObjectInstance createMBean(String className, ObjectName name,
Object[] params, String[] signature)
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException {
try {
checkCreate(name, className, "instantiate");
checkCreate(name, className, "registerMBean");
return super.createMBean(className, name, params, signature);
} catch (IOException ex) {
throw handleIOException(ex,"createMBean",className, name,
params, signature);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public ObjectInstance createMBean(String className, ObjectName name,
ObjectName loaderName, Object[] params, String[] signature)
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, InstanceNotFoundException {
try {
checkCreate(name, className, "instantiate");
checkCreate(name, className, "registerMBean");
return super.createMBean(className, name, loaderName, params,
signature);
} catch (IOException ex) {
throw handleIOException(ex,"createMBean",className, name,loaderName,
params, signature);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public AttributeList setAttributes(ObjectName name,AttributeList attributes)
throws InstanceNotFoundException, ReflectionException {
try {
final AttributeList authorized =
checkAttributes(name, attributes, "setAttribute");
return super.setAttributes(name, authorized);
} catch (IOException ex) {
throw handleIOException(ex,"setAttributes",name, attributes);
}
}
// From MBeanServerConnection: catch & handles IOException
@Override
public Object invoke(ObjectName name, String operationName, Object[] params,
String[] signature)
throws InstanceNotFoundException, MBeanException, ReflectionException {
try {
check(name, operationName, "invoke");
return super.invoke(name, operationName, params, signature);
} catch (IOException ex) {
throw handleIOException(ex,"invoke",name, operationName,
params, signature);
}
}
//
// These methods are inherited from MBeanServer....
//
/**
* This method should never be called.
* Throws UnsupportedOperationException.
*/
public Object instantiate(String className)
throws ReflectionException, MBeanException {
if (LOG.isLoggable(Level.FINE))
LOG.fine("call to unsupported instantiate method: " +
"trowing UnsupportedOperationException");
throw new UnsupportedOperationException("Not applicable.");
}
/**
* This method should never be called.
* Throws UnsupportedOperationException.
*/
public Object instantiate(String className, ObjectName loaderName)
throws ReflectionException, MBeanException,
InstanceNotFoundException {
if (LOG.isLoggable(Level.FINE))
LOG.fine("call to unsupported method: instantiate(...) -" +
"throwing UnsupportedOperationException");
throw new UnsupportedOperationException("Not applicable.");
}
/**
* This method should never be called.
* Throws UnsupportedOperationException.
*/
public Object instantiate(String className, Object[] params,
String[] signature) throws ReflectionException, MBeanException {
if (LOG.isLoggable(Level.FINE))
LOG.fine("call to unsupported method: instantiate(...) -" +
"throwing UnsupportedOperationException");
throw new UnsupportedOperationException("Not applicable.");
}
/**
* This method should never be called.
* Throws UnsupportedOperationException.
*/
public Object instantiate(String className, ObjectName loaderName,
Object[] params, String[] signature)
throws ReflectionException, MBeanException,
InstanceNotFoundException {
if (LOG.isLoggable(Level.FINE))
LOG.fine("call to unsupported method: instantiate(...) -" +
"throwing UnsupportedOperationException");
throw new UnsupportedOperationException("Not applicable.");
}
/**
* This method should never be called.
* Throws UnsupportedOperationException.
*/
@Deprecated
public ObjectInputStream deserialize(ObjectName name, byte[] data)
throws InstanceNotFoundException, OperationsException {
if (LOG.isLoggable(Level.FINE))
LOG.fine("call to unsupported method: deserialize(...) -" +
"throwing UnsupportedOperationException");
throw new UnsupportedOperationException("Not applicable.");
}
/**
* This method should never be called.
* Throws UnsupportedOperationException.
*/
@Deprecated
public ObjectInputStream deserialize(String className, byte[] data)
throws OperationsException, ReflectionException {
if (LOG.isLoggable(Level.FINE))
LOG.fine("call to unsupported method: deserialize(...) -" +
"throwing UnsupportedOperationException");
throw new UnsupportedOperationException("Not applicable.");
}
/**
* This method should never be called.
* Throws UnsupportedOperationException.
*/
@Deprecated
public ObjectInputStream deserialize(String className,
ObjectName loaderName, byte[] data)
throws InstanceNotFoundException, OperationsException,
ReflectionException {
if (LOG.isLoggable(Level.FINE))
LOG.fine("call to unsupported method: deserialize(...) -" +
"throwing UnsupportedOperationException");
throw new UnsupportedOperationException("Not applicable.");
}
/**
* This method should never be called.
* Throws UnsupportedOperationException.
*/
public ClassLoaderRepository getClassLoaderRepository() {
if (LOG.isLoggable(Level.FINE))
LOG.fine("call to unsupported method: getClassLoaderRepository() -" +
"throwing UnsupportedOperationException");
throw new UnsupportedOperationException("Not applicable.");
}
static RuntimeException newUnsupportedException(String namespace) {
return new RuntimeOperationsException(
new UnsupportedOperationException(
"Not supported in this namespace: "+namespace));
}
/**
* A result might be excluded for security reasons.
*/
@Override
boolean excludesFromResult(ObjectName targetName, String queryMethod) {
return !checkQuery(targetName, queryMethod);
}
//----------------------------------------------------------------------
// Hooks for checking permissions
//----------------------------------------------------------------------
/**
* This method is a hook to implement permission checking in subclasses.
* A subclass may override this method and throw a {@link
* SecurityException} if the permission is denied.
*
* @param routingName The name of the MBean in the enclosing context.
* This is of the form {@code <namespace>//<ObjectName>}.
* @param member The {@link
* javax.management.namespace.JMXNamespacePermission#getMember member}
* name.
* @param action The {@link
* javax.management.namespace.JMXNamespacePermission#getActions action}
* name.
* @throws SecurityException if the caller doesn't have the permission
* to perform the given action on the MBean pointed to
* by routingName.
*/
abstract void check(ObjectName routingName,
String member, String action);
// called in createMBean and registerMBean
abstract void checkCreate(ObjectName routingName, String className,
String action);
/**
* This is a hook to implement permission checking in subclasses.
*
* Checks that the caller has sufficient permission for returning
* information about {@code sourceName} in {@code action}.
*
* Subclass may override this method and return false if the caller
* doesn't have sufficient permissions.
*
* @param routingName The name of the MBean to include or exclude from
* the query, expressed in the enclosing context.
* This is of the form {@code <namespace>//<ObjectName>}.
* @param action one of "queryNames" or "queryMBeans"
* @return true if {@code sourceName} can be returned.
*/
abstract boolean checkQuery(ObjectName routingName, String action);
/**
* This method is a hook to implement permission checking in subclasses.
*
* @param routingName The name of the MBean in the enclosing context.
* This is of the form {@code <namespace>//<ObjectName>}.
* @param attributes The list of attributes to check permission for.
* @param action one of "getAttribute" or "setAttribute"
* @return The list of attributes for which the callers has the
* appropriate {@link
* javax.management.namespace.JMXNamespacePermission}.
* @throws SecurityException if the caller doesn't have the permission
* to perform {@code action} on the MBean pointed to by routingName.
*/
abstract String[] checkAttributes(ObjectName routingName,
String[] attributes, String action);
/**
* This method is a hook to implement permission checking in subclasses.
*
* @param routingName The name of the MBean in the enclosing context.
* This is of the form {@code <namespace>//<ObjectName>}.
* @param attributes The list of attributes to check permission for.
* @param action one of "getAttribute" or "setAttribute"
* @return The list of attributes for which the callers has the
* appropriate {@link
* javax.management.namespace.JMXNamespacePermission}.
* @throws SecurityException if the caller doesn't have the permission
* to perform {@code action} on the MBean pointed to by routingName.
*/
abstract AttributeList checkAttributes(ObjectName routingName,
AttributeList attributes, String action);
/**
* This method is a hook to implement permission checking in subclasses.
* Checks that the caller as the necessary permissions to view the
* given domain. If not remove the domains for which the caller doesn't
* have permission from the list.
* <p>
* By default, this method always returns {@code domains}
*
* @param domains The domains to return.
* @param action "getDomains"
* @return a filtered list of domains.
*/
String[] checkDomains(String[] domains, String action) {
return domains;
}
// A priori check for queryNames/queryMBeans/
void checkPattern(ObjectName routingPattern,
String member, String action) {
// pattern is checked only at posteriori by checkQuery.
// checking it a priori usually doesn't work, because ObjectName.apply
// does not work between two patterns.
// We only check that we have the permission requested for 'action'.
check(null,null,action);
}
}

View File

@ -1,220 +0,0 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.namespace;
import java.util.ArrayList;
import java.util.List;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.namespace.JMXNamespace;
import javax.management.namespace.JMXNamespacePermission;
/**
* A NamespaceInterceptor wraps a JMXNamespace, performing
* ObjectName rewriting.
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
* @since 1.7
*/
public class NamespaceInterceptor extends HandlerInterceptor<JMXNamespace> {
// The target name space in which the NamepsaceHandler is mounted.
private final String targetNs;
private final String serverName;
private final ObjectNameRouter proc;
/**
* Creates a new instance of NamespaceInterceptor
*/
public NamespaceInterceptor(
String serverName,
JMXNamespace handler,
String targetNamespace) {
super(handler);
this.serverName = serverName;
this.targetNs =
ObjectNameRouter.normalizeNamespacePath(targetNamespace,
true, true, false);
proc = new ObjectNameRouter(targetNamespace, "");
}
@Override
public String toString() {
return this.getClass().getName()+"(parent="+serverName+
", namespace="+this.targetNs+")";
}
/**
* This method will send a probe to detect self-linking name spaces.
* A self linking namespace is a namespace that links back directly
* on itslef. Calling a method on such a name space always results
* in an infinite loop going through:
* [1]MBeanServer -> [2]NamespaceDispatcher -> [3]NamespaceInterceptor
* [4]JMXNamespace -> { network // or cd // or ... } -> [5]MBeanServer
* with exactly the same request than [1]...
*
* The namespace interceptor [2] tries to detect such condition the
* *first time* that the connection is used. It does so by setting
* a flag, and sending a queryNames() through the name space. If the
* queryNames comes back, it knows that there's a loop.
*
* The DynamicProbe interface can also be used by a Sun JMXNamespace
* implementation to request the emission of a probe at any time
* (see JMXRemoteNamespace implementation).
*/
private MBeanServer connection() {
final MBeanServer c = super.source();
if (c != null) return c;
// should not come here
throw new NullPointerException("getMBeanServerConnection");
}
@Override
protected MBeanServer source() {
return connection();
}
@Override
protected MBeanServer getServerForLoading() {
// don't want to send probe on getClassLoader/getClassLoaderFor
return super.source();
}
@Override
protected ObjectName toSource(ObjectName targetName) {
return proc.toSourceContext(targetName, true);
}
@Override
protected ObjectName toTarget(ObjectName sourceName) {
return proc.toTargetContext(sourceName, false);
}
//
// Implements permission checks.
//
@Override
void check(ObjectName routingName, String member, String action) {
final SecurityManager sm = System.getSecurityManager();
if (sm == null) return;
if ("getDomains".equals(action)) return;
final JMXNamespacePermission perm =
new JMXNamespacePermission(serverName,member,
routingName,action);
sm.checkPermission(perm);
}
@Override
void checkCreate(ObjectName routingName, String className, String action) {
final SecurityManager sm = System.getSecurityManager();
if (sm == null) return;
final JMXNamespacePermission perm =
new JMXNamespacePermission(serverName,className,
routingName,action);
sm.checkPermission(perm);
}
//
// Implements permission filters for attributes...
//
@Override
AttributeList checkAttributes(ObjectName routingName,
AttributeList attributes, String action) {
check(routingName,null,action);
if (attributes == null || attributes.isEmpty()) return attributes;
final SecurityManager sm = System.getSecurityManager();
if (sm == null) return attributes;
final AttributeList res = new AttributeList();
for (Attribute at : attributes.asList()) {
try {
check(routingName,at.getName(),action);
res.add(at);
} catch (SecurityException x) { // DLS: OK
continue;
}
}
return res;
}
//
// Implements permission filters for attributes...
//
@Override
String[] checkAttributes(ObjectName routingName, String[] attributes,
String action) {
check(routingName,null,action);
if (attributes == null || attributes.length==0) return attributes;
final SecurityManager sm = System.getSecurityManager();
if (sm == null) return attributes;
final List<String> res = new ArrayList<String>(attributes.length);
for (String at : attributes) {
try {
check(routingName,at,action);
res.add(at);
} catch (SecurityException x) { // DLS: OK
continue;
}
}
return res.toArray(new String[res.size()]);
}
//
// Implements permission filters for domains...
//
@Override
String[] checkDomains(String[] domains, String action) {
// in principle, this method is never called because
// getDomains() will never be called - since there's
// no way that MBeanServer.getDomains() can be routed
// to a NamespaceInterceptor.
//
// This is also why there's no getDomains() in a
// JMXNamespacePermission...
//
return super.checkDomains(domains, action);
}
//
// Implements permission filters for queries...
//
@Override
boolean checkQuery(ObjectName routingName, String action) {
try {
check(routingName,null,action);
return true;
} catch (SecurityException x) { // DLS: OK
return false;
}
}
}

View File

@ -1,175 +0,0 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.namespace;
import static javax.management.namespace.JMXNamespaces.NAMESPACE_SEPARATOR;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
/**
* The ObjectNameRouter is used to rewrite routing object names.
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
* @since 1.7
*/
public class ObjectNameRouter {
private static final int NAMESPACE_SEPARATOR_LENGTH =
NAMESPACE_SEPARATOR.length();
final String targetPrefix;
final String sourcePrefix;
final int slen;
final int tlen;
final boolean identity;
/** Creates a new instance of ObjectNameRouter */
public ObjectNameRouter(final String remove, final String add) {
this.targetPrefix = (remove==null?"":remove);
this.sourcePrefix = (add==null?"":add);
tlen = targetPrefix.length();
slen = sourcePrefix.length();
identity = targetPrefix.equals(sourcePrefix);
}
public final ObjectName toTargetContext(ObjectName sourceName,
boolean removeLeadingSeparators) {
if (sourceName == null) return null;
if (identity) return sourceName;
String srcDomain = sourceName.getDomain();
// if the ObjectName starts with // and removeLeadingSeparators is
// true, then recursively strip leading //.
// Otherwise, do not rewrite ObjectName.
//
if (srcDomain.startsWith(NAMESPACE_SEPARATOR)) {
if (!removeLeadingSeparators) return sourceName;
else srcDomain = normalizeDomain(srcDomain,true);
}
if (slen != 0) {
if (!srcDomain.startsWith(sourcePrefix) ||
!srcDomain.startsWith(NAMESPACE_SEPARATOR,slen))
throw new IllegalArgumentException(
"ObjectName does not start with expected prefix "
+ sourcePrefix + ": " +
String.valueOf(sourceName));
srcDomain = srcDomain.substring(slen+NAMESPACE_SEPARATOR_LENGTH);
}
final String targetDomain =
(tlen>0?targetPrefix+NAMESPACE_SEPARATOR+srcDomain:srcDomain);
return sourceName.withDomain(targetDomain);
}
public final ObjectName toSourceContext(ObjectName targetName,
boolean removeLeadingSeparators) {
if (targetName == null) return null;
if (identity) return targetName;
String targetDomain = targetName.getDomain();
if (targetDomain.startsWith(NAMESPACE_SEPARATOR)) {
if (!removeLeadingSeparators) return targetName;
else targetDomain =
normalizeDomain(targetDomain,true);
}
if (tlen != 0) {
if (!targetDomain.startsWith(targetPrefix) ||
!targetDomain.startsWith(NAMESPACE_SEPARATOR,tlen))
throw new IllegalArgumentException(
"ObjectName does not start with expected prefix "
+ targetPrefix + ": " +
String.valueOf(targetName));
targetDomain = targetDomain.
substring(tlen+NAMESPACE_SEPARATOR_LENGTH);
}
final String sourceDomain =
(slen>0?sourcePrefix+NAMESPACE_SEPARATOR+targetDomain:
targetDomain);
return targetName.withDomain(sourceDomain);
}
public final ObjectInstance toTargetContext(ObjectInstance sourceMoi,
boolean removeLeadingSeparators) {
if (sourceMoi == null) return null;
if (identity) return sourceMoi;
return new ObjectInstance(
toTargetContext(sourceMoi.getObjectName(),
removeLeadingSeparators),
sourceMoi.getClassName());
}
/**
* Removes leading, trailing, or duplicate // in a name space path.
**/
public static String normalizeDomain(String domain,
boolean removeLeadingSep) {
return normalizeNamespacePath(domain,removeLeadingSep,false,true);
}
/**
* Removes leading, trailing, or duplicate // in a name space path.
**/
public static String normalizeNamespacePath(String namespacePath,
boolean removeLeadingSep,
boolean removeTrailingSep,
boolean endsWithDomain) {
if (namespacePath.equals(""))
return "";
final String[] components = namespacePath.split(NAMESPACE_SEPARATOR);
final StringBuilder b =
new StringBuilder(namespacePath.length()+NAMESPACE_SEPARATOR_LENGTH);
String sep = null;
if (!removeLeadingSep && namespacePath.startsWith(NAMESPACE_SEPARATOR))
b.append(NAMESPACE_SEPARATOR);
int count = 0;
for (int i=0; i<components.length; i++) {
final String n=components[i];
if (n.equals("")) continue;
if (n.startsWith("/")||n.endsWith("/")) {
// throw exception unless we're looking at the last domain
// part of the ObjectName
if (! (endsWithDomain && i==(components.length-1))) {
throw new IllegalArgumentException(n+
" is not a valid name space identifier");
} else {
// There's a dirty little corner case when the domain
// part (last item) is exactly '/' - in that case we must
// not append '//'
//
removeTrailingSep = removeTrailingSep || n.equals("/");
}
}
if (sep != null) b.append(sep);
b.append(n);
sep = NAMESPACE_SEPARATOR;
count++;
}
if (!removeTrailingSep && namespacePath.endsWith(NAMESPACE_SEPARATOR)
&& count > 0)
b.append(NAMESPACE_SEPARATOR);
return b.toString();
}
}

View File

@ -1,106 +0,0 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.namespace;
import com.sun.jmx.defaults.JmxProperties;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.MBeanServerConnection;
/**
* A RoutingConnectionProxy is an MBeanServerConnection proxy that proxies a
* source name space in a source MBeanServerConnection.
* It wraps a source MBeanServerConnection, and rewrites routing
* ObjectNames. It is used to implement
* {@code JMXNamespaces.narrowToNamespace(MBeanServerConnection)}.
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
* @since 1.7
*/
// See class hierarchy and detailled explanations in RoutingProxy in this
// package.
//
public class RoutingConnectionProxy
extends RoutingProxy<MBeanServerConnection> {
/**
* A logger for this class.
**/
private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
/**
* Creates a new instance of RoutingConnectionProxy
*/
public RoutingConnectionProxy(MBeanServerConnection source,
String sourceDir,
String targetDir,
boolean probe) {
super(source, sourceDir, targetDir, probe);
if (LOG.isLoggable(Level.FINER))
LOG.finer("RoutingConnectionProxy for " + getSourceNamespace() +
" created");
}
@Override
public String toString() {
final String targetNs = getTargetNamespace();
final String sourceNs = getSourceNamespace();
String wrapped = String.valueOf(source());
if ("".equals(targetNs)) {
return "JMXNamespaces.narrowToNamespace("+
wrapped+", \""+
sourceNs+"\")";
}
return this.getClass().getSimpleName()+"("+wrapped+", \""+
sourceNs+"\", \""+
targetNs+"\")";
}
static final RoutingProxyFactory
<MBeanServerConnection,RoutingConnectionProxy>
FACTORY = new RoutingProxyFactory
<MBeanServerConnection,RoutingConnectionProxy>() {
public RoutingConnectionProxy newInstance(MBeanServerConnection source,
String sourcePath, String targetPath, boolean probe) {
return new RoutingConnectionProxy(source,sourcePath,
targetPath, probe);
}
};
public static MBeanServerConnection cd(
MBeanServerConnection source, String sourcePath, boolean probe) {
return RoutingProxy.cd(RoutingConnectionProxy.class, FACTORY,
source, sourcePath, probe);
}
}

View File

@ -1,556 +0,0 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.namespace;
import com.sun.jmx.defaults.JmxProperties;
import com.sun.jmx.mbeanserver.Util;
import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.Set;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.InvalidAttributeValueException;
import javax.management.JMRuntimeException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServerConnection;
import javax.management.NotCompliantMBeanException;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.QueryExp;
import javax.management.ReflectionException;
import javax.management.RuntimeMBeanException;
import javax.management.RuntimeOperationsException;
/**
* A RoutingMBeanServerConnection wraps a MBeanServerConnection, defining
* abstract methods that can be implemented by subclasses to rewrite
* routing ObjectNames. It is used to implement
* HandlerInterceptors (wrapping JMXNamespace instances) and routing
* proxies (used to implement cd operations).
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
* @since 1.7
*/
public abstract class RoutingMBeanServerConnection<T extends MBeanServerConnection>
implements MBeanServerConnection {
/**
* A logger for this class.
**/
private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
/**
* Creates a new instance of RoutingMBeanServerConnection
*/
public RoutingMBeanServerConnection() {
}
/**
* Returns the wrapped source connection. The {@code source} connection
* is a connection to the MBeanServer that contains the actual MBean.
* In the case of cascading, that would be a connection to the sub
* agent.
**/
protected abstract T source() throws IOException;
/**
* Converts a target ObjectName to a source ObjectName.
* The target ObjectName is the name of the MBean in the mount point
* target. In the case of cascading, that would be the name of the
* MBean in the master agent. So if a subagent S containing an MBean
* named "X" is mounted in the target namespace "foo//" of a master agent M,
* the source is S, the target is "foo//" in M, the source name is "X", and
* the target name is "foo//X".
* In the case of cascading - such as in NamespaceInterceptor, this method
* will convert "foo//X" (the targetName) into "X", the source name.
* @throws IllegalArgumentException if the name cannot be converted.
**/
protected abstract ObjectName toSource(ObjectName targetName);
/**
* Converts a source ObjectName to a target ObjectName.
* (see description of toSource above for explanations)
* In the case of cascading - such as in NamespaceInterceptor, this method
* will convert "X" (the sourceName) into "foo//X", the target name.
* @throws IllegalArgumentException if the name cannot be converted.
**/
protected abstract ObjectName toTarget(ObjectName sourceName);
/**
* Can be overridden by subclasses to check the validity of a new
* ObjectName used in createMBean or registerMBean.
* This method is typically used by subclasses which might require
* special handling for "null";
**/
protected ObjectName newSourceMBeanName(ObjectName targetName)
throws MBeanRegistrationException {
try {
return toSource(targetName);
} catch (Exception x) {
throw new MBeanRegistrationException(x,"Illegal MBean Name");
}
}
// Calls toSource(), Wraps IllegalArgumentException.
ObjectName toSourceOrRuntime(ObjectName targetName) {
try {
return toSource(targetName);
} catch (RuntimeException x) {
throw makeCompliantRuntimeException(x);
}
}
// Wraps given exception if needed.
RuntimeException makeCompliantRuntimeException(Exception x) {
if (x instanceof SecurityException) return (SecurityException)x;
if (x instanceof JMRuntimeException) return (JMRuntimeException)x;
if (x instanceof RuntimeException)
return new RuntimeOperationsException((RuntimeException)x);
if (x instanceof IOException)
return Util.newRuntimeIOException((IOException)x);
// shouldn't come here...
final RuntimeException x2 = new UndeclaredThrowableException(x);
return new RuntimeOperationsException(x2);
}
// from MBeanServerConnection
public AttributeList getAttributes(ObjectName name, String[] attributes)
throws InstanceNotFoundException, ReflectionException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
return source().getAttributes(sourceName, attributes);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public Object invoke(ObjectName name, String operationName, Object[] params,
String[] signature)
throws InstanceNotFoundException, MBeanException, ReflectionException,
IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
final Object result =
source().invoke(sourceName,operationName,params,
signature);
return result;
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public void unregisterMBean(ObjectName name)
throws InstanceNotFoundException, MBeanRegistrationException,
IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
source().unregisterMBean(sourceName);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public MBeanInfo getMBeanInfo(ObjectName name)
throws InstanceNotFoundException, IntrospectionException,
ReflectionException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
return source().getMBeanInfo(sourceName);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public ObjectInstance getObjectInstance(ObjectName name)
throws InstanceNotFoundException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
return processOutputInstance(
source().getObjectInstance(sourceName));
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public boolean isRegistered(ObjectName name) throws IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
return source().isRegistered(sourceName);
} catch (RuntimeMBeanException x) {
throw new RuntimeOperationsException(x.getTargetException());
} catch (RuntimeException x) {
throw makeCompliantRuntimeException(x);
}
}
// from MBeanServerConnection
public void setAttribute(ObjectName name, Attribute attribute)
throws InstanceNotFoundException, AttributeNotFoundException,
InvalidAttributeValueException, MBeanException,
ReflectionException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
source().setAttribute(sourceName,attribute);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public ObjectInstance createMBean(String className,
ObjectName name, ObjectName loaderName,
Object[] params, String[] signature)
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, InstanceNotFoundException, IOException {
final ObjectName sourceName = newSourceMBeanName(name);
// Loader Name is already a sourceLoaderName.
final ObjectName sourceLoaderName = loaderName;
try {
final ObjectInstance instance =
source().createMBean(className,sourceName,
sourceLoaderName,
params,signature);
return processOutputInstance(instance);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public ObjectInstance createMBean(String className, ObjectName name,
Object[] params, String[] signature)
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, IOException {
final ObjectName sourceName = newSourceMBeanName(name);
try {
return processOutputInstance(source().createMBean(className,
sourceName,params,signature));
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public ObjectInstance createMBean(String className, ObjectName name,
ObjectName loaderName)
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, InstanceNotFoundException, IOException {
final ObjectName sourceName = newSourceMBeanName(name);
// Loader Name is already a source Loader Name.
final ObjectName sourceLoaderName = loaderName;
try {
return processOutputInstance(source().createMBean(className,
sourceName,sourceLoaderName));
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public ObjectInstance createMBean(String className, ObjectName name)
throws ReflectionException, InstanceAlreadyExistsException,
MBeanRegistrationException, MBeanException,
NotCompliantMBeanException, IOException {
final ObjectName sourceName = newSourceMBeanName(name);
try {
return processOutputInstance(source().
createMBean(className,sourceName));
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public Object getAttribute(ObjectName name, String attribute)
throws MBeanException, AttributeNotFoundException,
InstanceNotFoundException, ReflectionException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
return source().getAttribute(sourceName,attribute);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public boolean isInstanceOf(ObjectName name, String className)
throws InstanceNotFoundException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
return source().isInstanceOf(sourceName,className);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public AttributeList setAttributes(ObjectName name, AttributeList attributes)
throws InstanceNotFoundException, ReflectionException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
return source().
setAttributes(sourceName,attributes);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// Return names in the target's context.
Set<ObjectInstance> processOutputInstances(Set<ObjectInstance> sources) {
final Set<ObjectInstance> result = Util.equivalentEmptySet(sources);
for (ObjectInstance i : sources) {
try {
final ObjectInstance target = processOutputInstance(i);
if (excludesFromResult(target.getObjectName(), "queryMBeans"))
continue;
result.add(target);
} catch (Exception x) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("Skiping returned item: " +
"Unexpected exception while processing " +
"ObjectInstance: " + x);
}
continue;
}
}
return result;
}
// Return names in the target's context.
ObjectInstance processOutputInstance(ObjectInstance source) {
if (source == null) return null;
final ObjectName sourceName = source.getObjectName();
try {
final ObjectName targetName = toTarget(sourceName);
return new ObjectInstance(targetName,source.getClassName());
} catch (RuntimeException x) {
throw makeCompliantRuntimeException(x);
}
}
// Returns names in the target's context.
Set<ObjectName> processOutputNames(Set<ObjectName> sourceNames) {
final Set<ObjectName> names = Util.equivalentEmptySet(sourceNames);
for (ObjectName n : sourceNames) {
try {
final ObjectName targetName = toTarget(n);
if (excludesFromResult(targetName, "queryNames")) continue;
names.add(targetName);
} catch (Exception x) {
if (LOG.isLoggable(Level.FINE)) {
LOG.fine("Skiping returned item: " +
"Unexpected exception while processing " +
"ObjectInstance: " + x);
}
continue;
}
}
return names;
}
// from MBeanServerConnection
public Set<ObjectInstance> queryMBeans(ObjectName name,
QueryExp query) throws IOException {
if (name == null) name=ObjectName.WILDCARD;
final ObjectName sourceName = toSourceOrRuntime(name);
try {
return processOutputInstances(
source().queryMBeans(sourceName,query));
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public Set<ObjectName> queryNames(ObjectName name, QueryExp query)
throws IOException {
if (name == null) name=ObjectName.WILDCARD;
final ObjectName sourceName = toSourceOrRuntime(name);
try {
final Set<ObjectName> tmp = source().queryNames(sourceName,query);
final Set<ObjectName> out = processOutputNames(tmp);
//System.err.println("queryNames: out: "+out);
return out;
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public void removeNotificationListener(ObjectName name,
NotificationListener listener)
throws InstanceNotFoundException,
ListenerNotFoundException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
source().removeNotificationListener(sourceName,listener);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public void addNotificationListener(ObjectName name, ObjectName listener,
NotificationFilter filter, Object handback)
throws InstanceNotFoundException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
// Listener name is already a source listener name.
try {
source().addNotificationListener(sourceName,listener,
filter,handback);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public void addNotificationListener(ObjectName name,
NotificationListener listener, NotificationFilter filter,
Object handback) throws InstanceNotFoundException, IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
source().addNotificationListener(sourceName, listener, filter,
handback);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public void removeNotificationListener(ObjectName name,
NotificationListener listener, NotificationFilter filter,
Object handback)
throws InstanceNotFoundException, ListenerNotFoundException,
IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
source().removeNotificationListener(sourceName,listener,filter,
handback);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public void removeNotificationListener(ObjectName name, ObjectName listener,
NotificationFilter filter, Object handback)
throws InstanceNotFoundException, ListenerNotFoundException,
IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
source().removeNotificationListener(sourceName,listener,
filter,handback);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public void removeNotificationListener(ObjectName name, ObjectName listener)
throws InstanceNotFoundException, ListenerNotFoundException,
IOException {
final ObjectName sourceName = toSourceOrRuntime(name);
// listener name is already a source name...
final ObjectName sourceListener = listener;
try {
source().removeNotificationListener(sourceName,sourceListener);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public Integer getMBeanCount() throws IOException {
try {
return source().getMBeanCount();
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public String[] getDomains() throws IOException {
try {
return source().getDomains();
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// from MBeanServerConnection
public String getDefaultDomain() throws IOException {
try {
return source().getDefaultDomain();
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
/**
* Returns true if the given targetName must be excluded from the
* query result.
* In this base class, always return {@code false}.
* By default all object names returned by the sources are
* transmitted to the caller - there is no filtering.
*
* @param name A target object name expressed in the caller's
* context. In the case of cascading, where the source
* is a sub agent mounted on e.g. namespace "foo",
* that would be a name prefixed by "foo//"...
* @param queryMethod either "queryNames" or "queryMBeans".
* @return true if the name must be excluded.
*/
boolean excludesFromResult(ObjectName targetName, String queryMethod) {
return false;
}
}

View File

@ -1,395 +0,0 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.namespace;
import com.sun.jmx.defaults.JmxProperties;
import java.io.IOException;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.InstanceNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServerConnection;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.management.namespace.JMXNamespaces;
/**
* A RoutingProxy narrows on a given name space in a
* source object implementing MBeanServerConnection.
* It is used to implement
* {@code JMXNamespaces.narrowToNamespace(...)}.
* This abstract class has two concrete subclasses:
* <p>{@link RoutingConnectionProxy}: to narrow down into an
* MBeanServerConnection.</p>
* <p>{@link RoutingServerProxy}: to narrow down into an MBeanServer.</p>
*
* <p>This class can also be used to "broaden" from a namespace. The same
* class is used for both purposes because in both cases all that happens
* is that ObjectNames are rewritten in one way on the way in (e.g. the
* parameter of getMBeanInfo) and another way on the way out (e.g. the
* return value of queryNames).</p>
*
* <p>Specifically, if you narrow into "a//" then you want to add the
* "a//" prefix to ObjectNames on the way in and subtract it on the way
* out. But ClientContext uses this class to subtract the
* "jmx.context//foo=bar//" prefix on the way in and add it back on the
* way out.</p>
*
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
* @since 1.7
*/
//
// RoutingProxies are client side objects which are used to narrow down
// into a namespace. They are used to perform ObjectName translation,
// adding the namespace to the routing ObjectName before sending it over
// to the source connection, and removing that prefix from results of
// queries, createMBean, registerMBean, and getObjectInstance.
// This translation is the opposite to that which is performed by
// NamespaceInterceptors.
//
// There is however a special case where routing proxies are used on the
// 'server' side to remove a namespace - rather than to add it:
// This the case of ClientContext.
// When an ObjectName like "jmx.context//c1=v1,c2=v2//D:k=v" reaches the
// jmx.context namespace, a routing proxy is used to remove the prefix
// c1=v1,c2=v2// from the routing objectname.
//
// For a RoutingProxy used in a narrowDownToNamespace operation, we have:
// targetNs="" // targetNS is the namespace 'to remove'
// sourceNS=<namespace-we-narrow-down-to> // namespace 'to add'
//
// For a RoutingProxy used in a ClientContext operation, we have:
// targetNs=<encoded-context> // context must be removed from object name
// sourceNs="" // nothing to add...
//
// Finally, in order to avoid too many layers of wrapping,
// RoutingConnectionProxy and RoutingServerProxy can be created through a
// factory method that can concatenate namespace paths in order to
// return a single RoutingProxy - rather than wrapping a RoutingProxy inside
// another RoutingProxy. See RoutingConnectionProxy.cd and
// RoutingServerProxy.cd
//
// The class hierarchy is as follows:
//
// RoutingMBeanServerConnection
// [abstract class for all routing interceptors,
// such as RoutingProxies and HandlerInterceptors]
// / \
// / \
// RoutingProxy HandlerInterceptor
// [base class for [base class for server side
// client-side objects used objects, created by
// in narrowDownTo] DispatchInterceptors]
// / \ | \
// RoutingConnectionProxy \ | NamespaceInterceptor
// [wraps MBeanServerConnection \ | [used to remove
// objects] \ | namespace prefix and
// RoutingServerProxy | wrap JMXNamespace]
// [wraps MBeanServer |
// Objects] |
// DomainInterceptor
// [used to wrap JMXDomain]
//
// RoutingProxies also differ from HandlerInterceptors in that they transform
// calls to MBeanServerConnection operations that do not have any parameters
// into a call to the underlying JMXNamespace MBean.
// So for instance a call to:
// JMXNamespaces.narrowDownToNamespace(conn,"foo").getDomains()
// is transformed into
// conn.getAttribute("foo//type=JMXNamespace","Domains");
//
public abstract class RoutingProxy<T extends MBeanServerConnection>
extends RoutingMBeanServerConnection<T> {
/**
* A logger for this class.
**/
private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
// The source MBeanServerConnection
private final T source;
// The name space we're narrowing to (usually some name space in
// the source MBeanServerConnection), e.g. "a" for the namespace
// "a//". This is empty in the case of ClientContext described above.
private final String sourceNs;
// The name space we pretend to be mounted in. This is empty except
// in the case of ClientContext described above (where it will be
// something like "jmx.context//foo=bar".
private final String targetNs;
// The name of the JMXNamespace that handles the source name space
private final ObjectName handlerName;
private final ObjectNameRouter router;
private volatile String defaultDomain = null;
/**
* Creates a new instance of RoutingProxy
*/
protected RoutingProxy(T source,
String sourceNs,
String targetNs,
boolean probe) {
if (source == null) throw new IllegalArgumentException("null");
this.sourceNs = JMXNamespaces.normalizeNamespaceName(sourceNs);
// Usually sourceNs is not null, except when implementing
// Client Contexts
//
if (sourceNs.equals("")) {
this.handlerName = null;
} else {
// System.err.println("sourceNs: "+sourceNs);
this.handlerName =
JMXNamespaces.getNamespaceObjectName(this.sourceNs);
if (probe) {
try {
if (!source.isRegistered(handlerName)) {
InstanceNotFoundException infe =
new InstanceNotFoundException(handlerName);
throw new IllegalArgumentException(sourceNs +
": no such name space", infe);
}
} catch (IOException x) {
throw new IllegalArgumentException("source stale: "+x,x);
}
}
}
this.source = source;
this.targetNs = (targetNs==null?"":
JMXNamespaces.normalizeNamespaceName(targetNs));
this.router =
new ObjectNameRouter(this.targetNs,this.sourceNs);
if (LOG.isLoggable(Level.FINER))
LOG.finer("RoutingProxy for " + this.sourceNs + " created");
}
@Override
public T source() { return source; }
@Override
public ObjectName toSource(ObjectName targetName) {
if (targetName == null) return null;
if (targetName.getDomain().equals("") && targetNs.equals("")) {
try {
if (defaultDomain == null)
defaultDomain = getDefaultDomain();
} catch(Exception x) {
LOG.log(Level.FINEST,"Failed to get default domain",x);
}
if (defaultDomain != null)
targetName = targetName.withDomain(defaultDomain);
}
return router.toSourceContext(targetName,true);
}
@Override
protected ObjectName newSourceMBeanName(ObjectName targetName)
throws MBeanRegistrationException {
if (targetName != null) return super.newSourceMBeanName(targetName);
// OK => we can accept null if sourceNs is empty.
if (sourceNs.equals("")) return null;
throw new MBeanRegistrationException(
new IllegalArgumentException(
"Can't use null ObjectName with namespaces"));
}
@Override
public ObjectName toTarget(ObjectName sourceName) {
if (sourceName == null) return null;
return router.toTargetContext(sourceName,false);
}
private Object getAttributeFromHandler(String attributeName)
throws IOException {
try {
return source().getAttribute(handlerName,attributeName);
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
} catch (IOException x) {
throw x;
} catch (MBeanException ex) {
throw new IOException("Failed to get "+attributeName+": "+
ex.getCause(),
ex.getCause());
} catch (Exception ex) {
throw new IOException("Failed to get "+attributeName+": "+
ex,ex);
}
}
// We cannot call getMBeanCount() on the underlying
// MBeanServerConnection, because it would return the number of
// 'top-level' MBeans, not the number of MBeans in the name space
// we are narrowing to. Instead we're calling getMBeanCount() on
// the JMXNamespace that handles the source name space.
//
// There is however one particular case when the sourceNs is empty.
// In that case, there's no handler - and the 'source' is the top
// level namespace. In that particular case, handlerName will be null,
// and we directly invoke the top level source().
// This later complex case is only used when implementing ClientContexts.
//
@Override
public Integer getMBeanCount() throws IOException {
try {
if (handlerName == null) return source().getMBeanCount();
return (Integer) getAttributeFromHandler("MBeanCount");
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// We cannot call getDomains() on the underlying
// MBeanServerConnection, because it would return the domains of
// 'top-level' MBeans, not the domains of MBeans in the name space
// we are narrowing to. Instead we're calling getDomains() on
// the JMXNamespace that handles the source name space.
//
// There is however one particular case when the sourceNs is empty.
// In that case, there's no handler - and the 'source' is the top
// level namespace. In that particular case, handlerName will be null,
// and we directly invoke the top level source().
// This later complex case is only used when implementing ClientContexts.
//
@Override
public String[] getDomains() throws IOException {
try {
if (handlerName == null) return source().getDomains();
return (String[]) getAttributeFromHandler("Domains");
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
// We cannot call getDefaultDomain() on the underlying
// MBeanServerConnection, because it would return the default domain of
// 'top-level' namespace, not the default domain in the name space
// we are narrowing to. Instead we're calling getDefaultDomain() on
// the JMXNamespace that handles the source name space.
//
// There is however one particular case when the sourceNs is empty.
// In that case, there's no handler - and the 'source' is the top
// level namespace. In that particular case, handlerName will be null,
// and we directly invoke the top level source().
// This later complex case is only used when implementing ClientContexts.
//
@Override
public String getDefaultDomain() throws IOException {
try {
if (handlerName == null) {
defaultDomain = source().getDefaultDomain();
} else {
defaultDomain =(String)
getAttributeFromHandler("DefaultDomain");
}
return defaultDomain;
} catch (RuntimeException ex) {
throw makeCompliantRuntimeException(ex);
}
}
public String getSourceNamespace() {
return sourceNs;
}
public String getTargetNamespace() {
return targetNs;
}
@Override
public String toString() {
return super.toString()+", sourceNs="+
sourceNs + (targetNs.equals("")?"":
(" mounted on targetNs="+targetNs));
}
// Creates an instance of a subclass 'R' of RoutingProxy<T>
// RoutingServerProxy and RoutingConnectionProxy have their own factory
// instance.
static interface RoutingProxyFactory<T extends MBeanServerConnection,
R extends RoutingProxy<T>> {
public R newInstance(
T source, String sourcePath, String targetPath, boolean probe);
}
// Performs a narrowDownToNamespace operation.
// This method will attempt to merge two RoutingProxies in a single
// one if they are of the same class.
//
// This method is never called directly - it should be called only by
// subclasses of RoutingProxy.
//
// As for now it is called by:
// RoutingServerProxy.cd and RoutingConnectionProxy.cd.
//
static <T extends MBeanServerConnection, R extends RoutingProxy<T>>
R cd(Class<R> routingProxyClass,
RoutingProxyFactory<T,R> factory,
T source, String sourcePath, boolean probe) {
if (source == null) throw new IllegalArgumentException("null");
if (source.getClass().equals(routingProxyClass)) {
// cast is OK here, but findbugs complains unless we use class.cast
final R other = routingProxyClass.cast(source);
final String target = other.getTargetNamespace();
// Avoid multiple layers of serialization.
//
// We construct a new proxy from the original source instead of
// stacking a new proxy on top of the old one.
// - that is we replace
// cd ( cd ( x, dir1), dir2);
// by
// cd (x, dir1//dir2);
//
// We can do this only when the source class is exactly
// RoutingServerProxy.
//
if (target == null || target.equals("")) {
final String path =
JMXNamespaces.concat(other.getSourceNamespace(),
sourcePath);
return factory.newInstance(other.source(), path, "", probe);
}
// Note: we could do possibly something here - but it would involve
// removing part of targetDir, and possibly adding
// something to sourcePath.
// Too complex to bother! => simply default to stacking...
}
return factory.newInstance(source, sourcePath, "", probe);
}
}

View File

@ -1,576 +0,0 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.namespace;
import com.sun.jmx.mbeanserver.Util;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.lang.reflect.UndeclaredThrowableException;
import java.util.Collections;
import java.util.Set;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.InstanceAlreadyExistsException;
import javax.management.InstanceNotFoundException;
import javax.management.IntrospectionException;
import javax.management.InvalidAttributeValueException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanRegistrationException;
import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
import javax.management.OperationsException;
import javax.management.QueryExp;
import javax.management.ReflectionException;
import javax.management.loading.ClassLoaderRepository;
/**
* A RoutingServerProxy is an MBeanServer proxy that proxies a
* source name space in a source MBeanServer.
* It wraps a source MBeanServer, and rewrites routing ObjectNames.
* It is typically use for implementing 'cd' operations, and
* will add the source name space to routing ObjectNames at input,
* and remove it at output.
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
*
* @since 1.7
*/
// See class hierarchy and detailled explanations in RoutingProxy in this
// package.
//
public class RoutingServerProxy
extends RoutingProxy<MBeanServer>
implements MBeanServer {
public RoutingServerProxy(MBeanServer source,
String sourceNs,
String targetNs,
boolean probe) {
super(source, sourceNs, targetNs, probe);
}
/**
* This method is called each time an IOException is raised when
* trying to forward an operation to the underlying
* MBeanServerConnection, as a result of calling
* {@link #getMBeanServerConnection()} or as a result of invoking the
* operation on the returned connection.
* Subclasses may redefine this method if they need to perform any
* specific handling of IOException (logging etc...).
* @param x The raised IOException.
* @param method The name of the method in which the exception was
* raised. This is one of the methods of the MBeanServer
* interface.
* @return A RuntimeException that should be thrown by the caller.
* In this default implementation, this is an
* {@link UndeclaredThrowableException} wrapping <var>x</var>.
**/
protected RuntimeException handleIOException(IOException x,
String method) {
return Util.newRuntimeIOException(x);
}
//--------------------------------------------
//--------------------------------------------
//
// Implementation of the MBeanServer interface
//
//--------------------------------------------
//--------------------------------------------
@Override
public void addNotificationListener(ObjectName name,
NotificationListener listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException {
try {
super.addNotificationListener(name, listener,
filter, handback);
} catch (IOException x) {
throw handleIOException(x,"addNotificationListener");
}
}
@Override
public void addNotificationListener(ObjectName name,
ObjectName listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException {
try {
super.addNotificationListener(name, listener,
filter, handback);
} catch (IOException x) {
throw handleIOException(x,"addNotificationListener");
}
}
@Override
public ObjectInstance createMBean(String className, ObjectName name)
throws
ReflectionException,
InstanceAlreadyExistsException,
MBeanRegistrationException,
MBeanException,
NotCompliantMBeanException {
try {
return super.createMBean(className, name);
} catch (IOException x) {
throw handleIOException(x,"createMBean");
}
}
@Override
public ObjectInstance createMBean(String className, ObjectName name,
Object params[], String signature[])
throws
ReflectionException,
InstanceAlreadyExistsException,
MBeanRegistrationException,
MBeanException,
NotCompliantMBeanException {
try {
return super.createMBean(className, name,
params, signature);
} catch (IOException x) {
throw handleIOException(x,"createMBean");
}
}
@Override
public ObjectInstance createMBean(String className,
ObjectName name,
ObjectName loaderName)
throws
ReflectionException,
InstanceAlreadyExistsException,
MBeanRegistrationException,
MBeanException,
NotCompliantMBeanException,
InstanceNotFoundException {
try {
return super.createMBean(className, name, loaderName);
} catch (IOException x) {
throw handleIOException(x,"createMBean");
}
}
@Override
public ObjectInstance createMBean(String className,
ObjectName name,
ObjectName loaderName,
Object params[],
String signature[])
throws
ReflectionException,
InstanceAlreadyExistsException,
MBeanRegistrationException,
MBeanException,
NotCompliantMBeanException,
InstanceNotFoundException {
try {
return super.createMBean(className, name, loaderName,
params, signature);
} catch (IOException x) {
throw handleIOException(x,"createMBean");
}
}
/**
* @deprecated see {@link MBeanServer#deserialize(ObjectName,byte[])
* MBeanServer}
**/
@Deprecated
public ObjectInputStream deserialize(ObjectName name, byte[] data)
throws InstanceNotFoundException, OperationsException {
final ObjectName sourceName = toSourceOrRuntime(name);
try {
return source().deserialize(sourceName,data);
} catch (RuntimeException x) {
throw makeCompliantRuntimeException(x);
}
}
/**
* @deprecated see {@link MBeanServer#deserialize(String,byte[])
* MBeanServer}
*/
@Deprecated
public ObjectInputStream deserialize(String className, byte[] data)
throws OperationsException, ReflectionException {
try {
return source().deserialize(className,data);
} catch (RuntimeException x) {
throw makeCompliantRuntimeException(x);
}
}
/**
* @deprecated see {@link MBeanServer#deserialize(String,ObjectName,byte[])
* MBeanServer}
*/
@Deprecated
public ObjectInputStream deserialize(String className,
ObjectName loaderName,
byte[] data)
throws
InstanceNotFoundException,
OperationsException,
ReflectionException {
try {
return source().deserialize(className,loaderName,data);
} catch (RuntimeException x) {
throw makeCompliantRuntimeException(x);
}
}
@Override
public Object getAttribute(ObjectName name, String attribute)
throws
MBeanException,
AttributeNotFoundException,
InstanceNotFoundException,
ReflectionException {
try {
return super.getAttribute(name, attribute);
} catch (IOException x) {
throw handleIOException(x,"getAttribute");
}
}
@Override
public AttributeList getAttributes(ObjectName name, String[] attributes)
throws InstanceNotFoundException, ReflectionException {
try {
return super.getAttributes(name, attributes);
} catch (IOException x) {
throw handleIOException(x,"getAttributes");
}
}
public ClassLoader getClassLoader(ObjectName loaderName)
throws InstanceNotFoundException {
final ObjectName sourceName = toSourceOrRuntime(loaderName);
try {
return source().getClassLoader(sourceName);
} catch (RuntimeException x) {
throw makeCompliantRuntimeException(x);
}
}
public ClassLoader getClassLoaderFor(ObjectName mbeanName)
throws InstanceNotFoundException {
final ObjectName sourceName = toSourceOrRuntime(mbeanName);
try {
return source().getClassLoaderFor(sourceName);
} catch (RuntimeException x) {
throw makeCompliantRuntimeException(x);
}
}
public ClassLoaderRepository getClassLoaderRepository() {
try {
return source().getClassLoaderRepository();
} catch (RuntimeException x) {
throw makeCompliantRuntimeException(x);
}
}
@Override
public String getDefaultDomain() {
try {
return super.getDefaultDomain();
} catch (IOException x) {
throw handleIOException(x,"getDefaultDomain");
}
}
@Override
public String[] getDomains() {
try {
return super.getDomains();
} catch (IOException x) {
throw handleIOException(x,"getDomains");
}
}
@Override
public Integer getMBeanCount() {
try {
return super.getMBeanCount();
} catch (IOException x) {
throw handleIOException(x,"getMBeanCount");
}
}
@Override
public MBeanInfo getMBeanInfo(ObjectName name)
throws
InstanceNotFoundException,
IntrospectionException,
ReflectionException {
try {
return super.getMBeanInfo(name);
} catch (IOException x) {
throw handleIOException(x,"getMBeanInfo");
}
}
@Override
public ObjectInstance getObjectInstance(ObjectName name)
throws InstanceNotFoundException {
try {
return super.getObjectInstance(name);
} catch (IOException x) {
throw handleIOException(x,"getObjectInstance");
}
}
public Object instantiate(String className)
throws ReflectionException, MBeanException {
try {
return source().instantiate(className);
} catch (RuntimeException x) {
throw makeCompliantRuntimeException(x);
}
}
public Object instantiate(String className,
Object params[],
String signature[])
throws ReflectionException, MBeanException {
try {
return source().instantiate(className,
params,signature);
} catch (RuntimeException x) {
throw makeCompliantRuntimeException(x);
}
}
public Object instantiate(String className, ObjectName loaderName)
throws ReflectionException, MBeanException,
InstanceNotFoundException {
final ObjectName srcLoaderName = toSourceOrRuntime(loaderName);
try {
return source().instantiate(className,srcLoaderName);
} catch (RuntimeException x) {
throw makeCompliantRuntimeException(x);
}
}
public Object instantiate(String className, ObjectName loaderName,
Object params[], String signature[])
throws ReflectionException, MBeanException,
InstanceNotFoundException {
final ObjectName srcLoaderName = toSourceOrRuntime(loaderName);
try {
return source().instantiate(className,srcLoaderName,
params,signature);
} catch (RuntimeException x) {
throw makeCompliantRuntimeException(x);
}
}
@Override
public Object invoke(ObjectName name, String operationName,
Object params[], String signature[])
throws
InstanceNotFoundException,
MBeanException,
ReflectionException {
try {
return super.invoke(name,operationName,params,signature);
} catch (IOException x) {
throw handleIOException(x,"invoke");
}
}
@Override
public boolean isInstanceOf(ObjectName name, String className)
throws InstanceNotFoundException {
try {
return super.isInstanceOf(name, className);
} catch (IOException x) {
throw handleIOException(x,"isInstanceOf");
}
}
@Override
public boolean isRegistered(ObjectName name) {
try {
return super.isRegistered(name);
} catch (IOException x) {
throw handleIOException(x,"isRegistered");
}
}
@Override
public Set<ObjectInstance> queryMBeans(ObjectName name, QueryExp query) {
try {
return super.queryMBeans(name, query);
} catch (IOException x) {
handleIOException(x,"queryMBeans");
return Collections.emptySet();
}
}
@Override
public Set<ObjectName> queryNames(ObjectName name, QueryExp query) {
try {
return super.queryNames(name, query);
} catch (IOException x) {
handleIOException(x,"queryNames");
return Collections.emptySet();
}
}
public ObjectInstance registerMBean(Object object, ObjectName name)
throws
InstanceAlreadyExistsException,
MBeanRegistrationException,
NotCompliantMBeanException {
final ObjectName sourceName = newSourceMBeanName(name);
try {
return processOutputInstance(
source().registerMBean(object,sourceName));
} catch (RuntimeException x) {
throw makeCompliantRuntimeException(x);
}
}
@Override
public void removeNotificationListener(ObjectName name,
NotificationListener listener)
throws InstanceNotFoundException, ListenerNotFoundException {
try {
super.removeNotificationListener(name, listener);
} catch (IOException x) {
throw handleIOException(x,"removeNotificationListener");
}
}
@Override
public void removeNotificationListener(ObjectName name,
NotificationListener listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException, ListenerNotFoundException {
try {
super.removeNotificationListener(name, listener,
filter, handback);
} catch (IOException x) {
throw handleIOException(x,"removeNotificationListener");
}
}
@Override
public void removeNotificationListener(ObjectName name,
ObjectName listener)
throws InstanceNotFoundException, ListenerNotFoundException {
try {
super.removeNotificationListener(name, listener);
} catch (IOException x) {
throw handleIOException(x,"removeNotificationListener");
}
}
@Override
public void removeNotificationListener(ObjectName name,
ObjectName listener,
NotificationFilter filter,
Object handback)
throws InstanceNotFoundException, ListenerNotFoundException {
try {
super.removeNotificationListener(name, listener,
filter, handback);
} catch (IOException x) {
throw handleIOException(x,"removeNotificationListener");
}
}
@Override
public void setAttribute(ObjectName name, Attribute attribute)
throws
InstanceNotFoundException,
AttributeNotFoundException,
InvalidAttributeValueException,
MBeanException,
ReflectionException {
try {
super.setAttribute(name, attribute);
} catch (IOException x) {
throw handleIOException(x,"setAttribute");
}
}
@Override
public AttributeList setAttributes(ObjectName name,
AttributeList attributes)
throws InstanceNotFoundException, ReflectionException {
try {
return super.setAttributes(name, attributes);
} catch (IOException x) {
throw handleIOException(x,"setAttributes");
}
}
@Override
public void unregisterMBean(ObjectName name)
throws InstanceNotFoundException, MBeanRegistrationException {
try {
super.unregisterMBean(name);
} catch (IOException x) {
throw handleIOException(x,"unregisterMBean");
}
}
static final RoutingProxyFactory<MBeanServer,RoutingServerProxy>
FACTORY = new RoutingProxyFactory<MBeanServer,RoutingServerProxy>() {
public RoutingServerProxy newInstance(MBeanServer source,
String sourcePath, String targetPath, boolean probe) {
return new RoutingServerProxy(
source, sourcePath, targetPath, probe);
}
};
public static MBeanServer cd(
MBeanServer source, String sourcePath, boolean probe) {
return RoutingProxy.cd(RoutingServerProxy.class, FACTORY,
source, sourcePath, probe);
}
}

View File

@ -1,45 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>The <code>com.sun.jmx.namespace</code> package</title>
<!--
Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
This code is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 only, as
published by the Free Software Foundation. Sun designates this
particular file as subject to the "Classpath" exception as provided
by Sun in the LICENSE file that accompanied this code.
This code is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
version 2 for more details (a copy is included in the LICENSE file that
accompanied this code).
You should have received a copy of the GNU General Public License version
2 along with this work; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
CA 95054 USA or visit www.sun.com if you need additional information or
have any questions.
-->
</head>
<body bgcolor="white">
<p>The <code>com.sun.jmx.namespace</code> package contains
sun specific implementation classes used to implement the
JMX namespaces.
</p>
<p><b>DO NOT USE THESE CLASSES DIRECTLY</b></p>
<p><b>
This API is a Sun internal API and is subject to changes without notice.
</b></p>
<p>The public API through wich these proprietary classes can be
invoked is located in <code>javax.management.namespace</code>
package.
</p>
</body>
</html>

View File

@ -1,150 +0,0 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.namespace.serial;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
/**
* Class DefaultRewritingProcessor. Rewrite ObjectName in input & output
* parameters.
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
* @since 1.7
*/
// We know that rewriting using serialization is costly.
// This object tries to determine whether an object needs rewriting prior
// to rewriting, and rewrites by creating a new object in those cases
// where we know how to recreate a new object (e.g. a Notification).
// Rewriting is however usually not used - so this object is just a
// skeleton that eventually uses serialization...
//
class DefaultRewritingProcessor extends RewritingProcessor {
private static enum RewriteMode {
INPUT, // Input from target to source (parameters)
OUTPUT // Output from source to target (results)
};
private final boolean identity;
public DefaultRewritingProcessor(String targetDirName) {
this(targetDirName,null);
}
/** Creates a new instance of SerialParamProcessor */
public DefaultRewritingProcessor(final String remove, final String add) {
super(new SerialRewritingProcessor(remove, add));
identity = remove.equals(add);
}
private ObjectName rewriteObjectName(RewriteMode mode,
ObjectName name) {
return changeContext(mode, name);
}
private ObjectInstance rewriteObjectInstance(RewriteMode mode,
ObjectInstance moi) {
final ObjectName srcName = moi.getObjectName();
final ObjectName targetName = changeContext(mode,srcName);
if (targetName == srcName) return moi;
return new ObjectInstance(targetName,moi.getClassName());
}
private Object processObject(RewriteMode mode, Object obj) {
if (obj == null) return null;
// Some things which will always needs rewriting:
// ObjectName, ObjectInstance, and Notifications.
// Take care of those we can handle here...
//
if (obj instanceof ObjectName)
return rewriteObjectName(mode,(ObjectName) obj);
else if (obj instanceof ObjectInstance)
return rewriteObjectInstance(mode,(ObjectInstance) obj);
// TODO: add other standard JMX classes - like e.g. MBeanInfo...
//
// Well, the object may contain an ObjectName => pass it to
// our serial rewriting delegate...
//
return processAnyObject(mode,obj);
}
private Object processAnyObject(RewriteMode mode, Object obj) {
switch (mode) {
case INPUT:
return super.rewriteInput(obj);
case OUTPUT:
return super.rewriteOutput(obj);
default: // can't happen.
throw new AssertionError();
}
}
private ObjectName changeContext(RewriteMode mode, ObjectName name) {
switch (mode) {
case INPUT:
return toSourceContext(name);
case OUTPUT:
return toTargetContext(name);
default: // can't happen.
throw new AssertionError();
}
}
@Override
public ObjectName toTargetContext(ObjectName srcName) {
if (identity) return srcName;
return super.toTargetContext(srcName);
}
@Override
public ObjectName toSourceContext(ObjectName targetName) {
if (identity) return targetName;
return super.toSourceContext(targetName);
}
@SuppressWarnings("unchecked")
@Override
public <T> T rewriteInput(T input) {
if (identity) return input;
return (T) processObject(RewriteMode.INPUT,input);
}
@SuppressWarnings("unchecked")
@Override
public <T> T rewriteOutput(T result) {
if (identity) return result;
return (T) processObject(RewriteMode.OUTPUT,result);
}
}

View File

@ -1,145 +0,0 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.namespace.serial;
import com.sun.jmx.defaults.JmxProperties;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* The JMXNamespaceContext class is used to implement a thread local
* serialization / deserialization context for namespaces.
* <p>
* This class is consulted by {@link javax.management.ObjectName} at
* serialization / deserialization time.
* The serialization or deserialization context is established by
* by the {@link SerialRewritingProcessor} defined in this package.
* <p>
* These classes are Sun proprietary APIs, subject to change without
* notice. Do not use these classes directly.
* The public API to rewrite ObjectNames embedded in parameters is
* defined in {@link javax.management.namespace.JMXNamespaces}.
*
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
* @since 1.7
*/
public class JMXNamespaceContext {
private static final Logger LOG = JmxProperties.NAMESPACE_LOGGER;
public final String prefixToRemove;
public final String prefixToAdd;
private JMXNamespaceContext(String add, String remove) {
prefixToRemove = (remove==null?"":remove);
prefixToAdd = (add==null?"":add);
}
private final static class SerialContext {
private JMXNamespaceContext serializationContext;
private JMXNamespaceContext deserializationContext;
public SerialContext(){
serializationContext = new JMXNamespaceContext("","");
deserializationContext = new JMXNamespaceContext("","");
}
}
private final static ThreadLocal<SerialContext> prefix =
new ThreadLocal<SerialContext>() {
@Override
protected SerialContext initialValue() {
return new SerialContext();
}
};
public static JMXNamespaceContext getSerializationContext() {
return prefix.get().serializationContext;
}
public static JMXNamespaceContext getDeserializationContext() {
return prefix.get().deserializationContext;
}
private static String[] setSerializationContext(String oldPrefix,
String newPrefix) {
final SerialContext c = prefix.get();
JMXNamespaceContext dc = c.serializationContext;
String[] old = {dc.prefixToRemove, dc.prefixToAdd};
c.serializationContext = new JMXNamespaceContext(newPrefix,oldPrefix);
return old;
}
private static String[] setDeserializationContext(String oldPrefix,
String newPrefix) {
final SerialContext c = prefix.get();
JMXNamespaceContext dc = c.deserializationContext;
String[] old = {dc.prefixToRemove, dc.prefixToAdd};
c.deserializationContext = new JMXNamespaceContext(newPrefix,oldPrefix);
return old;
}
static void serialize(ObjectOutputStream stream, Object obj,
String prefixToRemove, String prefixToAdd)
throws IOException {
final String[] old =
setSerializationContext(prefixToRemove,prefixToAdd);
try {
stream.writeObject(obj);
} finally {
try {
setSerializationContext(old[0],old[1]);
} catch (Exception x) {
LOG.log(Level.FINEST,
"failed to restore serialization context",x);
}
}
}
static Object deserialize(ObjectInputStream stream,
String prefixToRemove,
String prefixToAdd)
throws IOException, ClassNotFoundException {
final String[] old =
setDeserializationContext(prefixToRemove,prefixToAdd);
try {
return stream.readObject();
} finally {
try {
setDeserializationContext(old[0],old[1]);
} catch (Exception x) {
LOG.log(Level.FINEST,
"failed to restore serialization context",x);
}
}
}
}

View File

@ -1,362 +0,0 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.namespace.serial;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
/**
* An object that can rewrite ObjectNames contained in input/output
* parameters when entering/leaving a {@link javax.management.namespace
* namespace}.
* <p>When entering a {@link javax.management.namespace
* namespace}, the {@code namespace} prefix is stripped from
* ObjectNames contained in input parameters. When leaving a
* {@code namespace},
* the {@code namespace} prefix is prepended to the ObjectNames contained in
* the result parameters returned from that {@code namespace}.
* </p>
* <p>Objects that need to perform these operations usually use a
* {@code RewritingProcessor} for that purpose.<br>
* The {@code RewritingProcessor} allows a somewhat larger
* transformation in which part of a prefix {@link #newRewritingProcessor
* remove} can be replaced by another prefix {@link #newRewritingProcessor
* add}. The transformation described above correspond to the case where
* {@code remove} is the stripped {@link javax.management.namespace
* namespace} prefix (removed when entering the {@code namespace}) and
* {@code add} is the empty String {@code ""}.
* <br>
* It is interesting to note that {@link
* javax.management.JMXNamespaces#narrowToNamespace narrowToNamespace}
* operations use the inverse transformation (that is, {@code remove} is
* the empty String {@code ""} and {@code add} is the {@link
* javax.management.namespace namespace} prefix).
* <br>
* On a more general scale, {@link #rewriteInput rewriteInput} removes
* {@link #newRewritingProcessor remove} and the prepend {@link
* #newRewritingProcessor add}, and {@link #rewriteOutput rewriteOutput}
* does the opposite, removing {@link #newRewritingProcessor add}, and
* then adding {@link #newRewritingProcessor remove}.
* <br>
* An implementation of {@code RewritingProcessor} should make sure that
* <code>rewriteInput(rewriteOutput(x,clp),clp)</code> and
* <code>rewriteOutput(rewriteInput(x,clp),clp)</code> always return
* {@code x} or an exact clone of {@code x}.
* </p>
* <p>A default implementation of {@code RewritingProcessor} based on
* Java Object Serialization can be
* obtained from {@link #newRewritingProcessor newRewritingProcessor}.
* </p>
* <p>
* By default, the instances of {@code RewritingProcessor} returned by
* {@link #newRewritingProcessor newRewritingProcessor} will rewrite
* ObjectNames contained in instances of classes they don't know about by
* serializing and then deserializing such object instances. This will
* happen even if such instances don't - or can't contain ObjectNames,
* because the default implementation of {@code RewritingProcessor} will
* not be able to determine whether instances of such classes can/do contain
* instance of ObjectNames before serializing/deserializing them.
* </p>
* <p>If you are using custom classes that the default implementation of
* {@code RewritingProcessor} don't know about, it can be interesting to
* prevent an instance of {@code RewritingProcessor} to serialize/deserialize
* instances of such classes for nothing. In that case, you could customize
* the behavior of such a {@code RewritingProcessor} by wrapping it in a
* custom subclass of {@code RewritingProcessor} as shown below:
* <pre>
* public class MyRewritingProcessor extends RewritingProcessor {
* MyRewritingProcessor(String remove, String add) {
* this(RewritingProcessor.newRewritingProcessor(remove,add));
* }
* MyRewritingProcessor(RewritingProcessor delegate) {
* super(delegate);
* }
*
* <T> T rewriteInput(T input) {
* if (input == null) return null;
* if (MyClass.equals(input.getClass())) {
* // I know that MyClass doesn't contain any ObjectName
* return (T) input;
* }
* return super.rewriteInput(input);
* }
* <T> T rewriteOutput(T result) {
* if (result == null) return null;
* if (MyClass.equals(result.getClass())) {
* // I know that MyClass doesn't contain any ObjectName
* return (T) result;
* }
* return super.rewriteOutput(result);
* }
* }
* </pre>
* </p>
* <p>Such a subclass may also provide an alternate way of rewriting
* custom subclasses for which rewriting is needed - for instance:
* <pre>
* public class MyRewritingProcessor extends RewritingProcessor {
* MyRewritingProcessor(String remove, String add) {
* this(RewritingProcessor.newRewritingProcessor(remove,add));
* }
* MyRewritingProcessor(RewritingProcessor delegate) {
* super(delegate);
* }
*
* <T> T rewriteInput(T input) {
* if (input == null) return null;
* if (MyClass.equals(input.getClass())) {
* // I know that MyClass doesn't contain any ObjectName
* return (T) input;
* } else if (MyOtherClass.equals(input.getClass())) {
* // Returns a new instance in which ObjectNames have been
* // replaced.
* final ObjectName aname = ((MyOtherClass)input).getName();
* return (T) (new MyOtherClass(super.rewriteInput(aname)));
* }
* return super.rewriteInput(input,clp);
* }
* <T> T rewriteOutput(T result) {
* if (result == null) return null;
* if (MyClass.equals(result.getClass())) {
* // I know that MyClass doesn't contain any ObjectName
* return (T) result;
* } else if (MyOtherClass.equals(result.getClass())) {
* // Returns a new instance in which ObjectNames have been
* // replaced.
* final ObjectName aname = ((MyOtherClass)result).getName();
* return (T) (new MyOtherClass(super.rewriteOutput(aname)));
* }
* return super.rewriteOutput(result,clp);
* }
* }
* </pre>
* </p>
* <p>If your application only uses {@link javax.management.MXBean MXBeans},
* or MBeans using simple types, and doesn't define any custom subclass of
* {@link javax.management.Notification}, you should never write such
* such {@code RewitingProcessor} implementations.
* </p>
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
* @since 1.7
*/
public abstract class RewritingProcessor {
/**
* A logger for this class.
**/
private final RewritingProcessor delegate;
/**
* Creates a new instance of RewritingProcessor.
* <p>This is equivalent to calling {@link
* #RewritingProcessor(RewritingProcessor) RewritingProcessor(null)}.
* </p>
**/
protected RewritingProcessor() {
this(null);
}
/**
* Creates a new instance of RewritingProcessor, with a delegate.
* @param delegate a {@code RewritingProcessor} to which all the
* calls will be delegated. When implementing a subclass
* of {@code RewritingProcessor}, calling {@link
* #rewriteInput super.rewriteInput} will invoke
* {@code delegate.rewriteInput} and calling {@link
* #rewriteOutput super.rewriteOutput} will invoke
* {@code delegate.rewriteOutput}.
*
**/
protected RewritingProcessor(RewritingProcessor delegate) {
this.delegate = delegate;
}
/**
* Rewrites ObjectNames when {@link RewritingProcessor leaving} a {@link
* javax.management.namespace namespace}.
* <p>
* Returns {@code obj}, if it is known that {@code obj} doesn't contain
* any ObjectName, or a new copied instance of {@code obj} in which
* ObjectNames (if any) will have been rewritten, if {@code obj} contains
* ObjectNames, or if it is not known whether {@code obj} contains
* ObjectNames or not.
* </p>
* <p>
* The default implementation of this method is as follows: if the
* {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code
* null}, throws an {@link IllegalArgumentException}. Otherwise,
* returns {@code delegate.rewriteOutput(obj)}.
* </p>
* <p>This behavior can be overridden by subclasses as shown in this
* class {@link RewritingProcessor description}.
* </p>
* @param obj The result to be rewritten if needed.
*
* @return {@code obj}, or a clone of {@code obj} in which ObjectNames
* have been rewritten. See this class {@link RewritingProcessor
* description} for more details.
* @throws IllegalArgumentException if this implementation does not know
* how to rewrite the object.
**/
public <T> T rewriteOutput(T obj) {
if (obj == null) return null;
if (delegate != null)
return delegate.rewriteOutput(obj);
throw new IllegalArgumentException("can't rewrite "+
obj.getClass().getName());
}
/**
* Rewrites ObjectNames when {@link RewritingProcessor entering} a {@link
* javax.management.namespace namespace}.
* <p>
* Returns {@code obj}, if it is known that {@code obj} doesn't contain
* any ObjectName, or a new copied instance of {@code obj} in which
* ObjectNames (if any) will have been rewritten, if {@code obj} contains
* ObjectNames, or if it is not known whether {@code obj} contains
* ObjectNames or not.
* </p>
* <p>
* The default implementation of this method is as follows: if the
* {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code
* null}, throws an {@link IllegalArgumentException}. Otherwise,
* returns {@code delegate.rewriteInput(obj)}.
* </p>
* <p>This behavior can be overridden by subclasses as shown in this
* class {@link RewritingProcessor description}.
* </p>
* @param obj The result to be rewritten if needed.
* @return {@code obj}, or a clone of {@code obj} in which ObjectNames
* have been rewritten. See this class {@link RewritingProcessor
* description} for more details.
* @throws IllegalArgumentException if this implementation does not know
* how to rewrite the object.
**/
public <T> T rewriteInput(T obj) {
if (obj == null) return null;
if (delegate != null)
return delegate.rewriteInput(obj);
throw new IllegalArgumentException("can't rewrite "+
obj.getClass().getName());
}
/**
* Translate a routing ObjectName from the target (calling) context to
* the source (called) context when {@link RewritingProcessor entering} a
* {@link javax.management.namespace namespace}.
* <p>
* The default implementation of this method is as follows: if the
* {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code
* null}, throws an {@link IllegalArgumentException}. Otherwise,
* returns {@code delegate.toSourceContext(targetName)}.
* </p>
* <p>This behavior can be overridden by subclasses as shown in this
* class {@link RewritingProcessor description}.
* </p>
* @param targetName The routing target ObjectName to translate.
* @return The ObjectName translated to the source context.
* @throws IllegalArgumentException if this implementation does not know
* how to rewrite the object.
**/
public ObjectName toSourceContext(ObjectName targetName) {
if (delegate != null)
return delegate.toSourceContext(targetName);
throw new IllegalArgumentException("can't rewrite targetName: "+
" no delegate.");
}
/**
* Translate an ObjectName returned from the source context into
* the target (calling) context when {@link RewritingProcessor leaving} a
* {@link javax.management.namespace namespace}.
* <p>
* The default implementation of this method is as follows: if the
* {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code
* null}, throws an {@link IllegalArgumentException}. Otherwise,
* returns {@code delegate.toTargetContext(sourceName)}.
* </p>
* <p>This behavior can be overridden by subclasses as shown in this
* class {@link RewritingProcessor description}.
* </p>
* @param sourceName The routing source ObjectName to translate to the
* target context.
* @return The ObjectName translated to the target context.
* @throws IllegalArgumentException if this implementation does not know
* how to rewrite the object.
**/
public ObjectName toTargetContext(ObjectName sourceName) {
if (delegate != null)
return delegate.toTargetContext(sourceName);
throw new IllegalArgumentException("can't rewrite sourceName: "+
" no delegate.");
}
/**
* Translate an ObjectInstance returned from the source context into
* the target (calling) context when {@link RewritingProcessor leaving} a
* {@link javax.management.namespace namespace}.
* <p>
* The default implementation of this method is as follows: if the
* {@link #RewritingProcessor(RewritingProcessor) delegate} is {@code
* null}, throws an {@link IllegalArgumentException}. Otherwise,
* returns {@code delegate.toTargetContext(sourceMoi)}.
* </p>
* <p>This behavior can be overridden by subclasses as shown in this
* class {@link RewritingProcessor description}.
* </p>
* @param sourceMoi The routing source ObjectInstance to translate.
* @return The ObjectInstance translated to the target context.
* @throws IllegalArgumentException if this implementation does not know
* how to rewrite the object.
**/
public ObjectInstance toTargetContext(ObjectInstance sourceMoi) {
if (delegate != null)
return delegate.toTargetContext(sourceMoi);
throw new IllegalArgumentException("can't rewrite sourceName: "+
" no delegate.");
}
/**
* Creates a new default instance of {@link RewritingProcessor}.
* @param remove The prefix to remove from {@link ObjectName ObjectNames}
* when {@link RewritingProcessor entering} the {@link
* javax.management.namespace namespace}.
* @param add The prefix to add to {@link ObjectName ObjectNames}
* when {@link RewritingProcessor entering} the {@link
* javax.management.namespace namespace} (this is performed
* after having removed the {@code remove} prefix.
* @return A new {@link RewritingProcessor} processor object that will
* perform the requested operation, using Java serialization if
* necessary.
**/
public static RewritingProcessor newRewritingProcessor(String remove,
String add) {
return new DefaultRewritingProcessor(remove,add);
}
}

View File

@ -1,74 +0,0 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.namespace.serial;
import com.sun.jmx.namespace.ObjectNameRouter;
import javax.management.ObjectInstance;
import javax.management.ObjectName;
/**
* Class RoutingOnlyProcessor. A RewritingProcessor that uses
* Java Serialization to rewrite ObjectNames contained in
* input and results...
*
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
* @since 1.7
*/
class RoutingOnlyProcessor extends RewritingProcessor {
final ObjectNameRouter router;
public RoutingOnlyProcessor(String targetDirName) {
this(targetDirName,null);
}
/** Creates a new instance of RoutingOnlyProcessor */
public RoutingOnlyProcessor(final String remove, final String add) {
super(new IdentityProcessor());
if (remove == null || add == null)
throw new IllegalArgumentException("Null argument");
router = new ObjectNameRouter(remove,add);
}
@Override
public final ObjectName toTargetContext(ObjectName sourceName) {
return router.toTargetContext(sourceName,false);
}
@Override
public final ObjectName toSourceContext(ObjectName targetName) {
return router.toSourceContext(targetName,false);
}
@Override
public final ObjectInstance toTargetContext(ObjectInstance sourceMoi) {
return router.toTargetContext(sourceMoi,false);
}
}

View File

@ -1,172 +0,0 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.namespace.serial;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InvalidClassException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.ObjectStreamClass;
import java.io.OutputStream;
import java.util.LinkedList;
import java.util.Queue;
import javax.management.ObjectName;
/**
* Class SerialRewritingProcessor. A RewritingProcessor that uses
* Java Serialization to rewrite ObjectNames contained in
* input & results...
* <p><b>
* This API is a Sun internal API and is subject to changes without notice.
* </b></p>
* @since 1.7
*/
class SerialRewritingProcessor extends RewritingProcessor {
private static class CloneOutput extends ObjectOutputStream {
Queue<Class<?>> classQueue = new LinkedList<Class<?>>();
CloneOutput(OutputStream out) throws IOException {
super(out);
}
@Override
protected void annotateClass(Class<?> c) {
classQueue.add(c);
}
@Override
protected void annotateProxyClass(Class<?> c) {
classQueue.add(c);
}
}
private static class CloneInput extends ObjectInputStream {
private final CloneOutput output;
CloneInput(InputStream in, CloneOutput output) throws IOException {
super(in);
this.output = output;
}
@Override
protected Class<?> resolveClass(ObjectStreamClass osc)
throws IOException, ClassNotFoundException {
Class<?> c = output.classQueue.poll();
String expected = osc.getName();
String found = (c == null) ? null : c.getName();
if (!expected.equals(found)) {
throw new InvalidClassException("Classes desynchronized: " +
"found " + found + " when expecting " + expected);
}
return c;
}
@Override
protected Class<?> resolveProxyClass(String[] interfaceNames)
throws IOException, ClassNotFoundException {
return output.classQueue.poll();
}
}
final String targetPrefix;
final String sourcePrefix;
final boolean identity;
public SerialRewritingProcessor(String targetDirName) {
this(targetDirName,null);
}
/** Creates a new instance of SerialRewritingProcessor */
public SerialRewritingProcessor(final String remove, final String add) {
super(new RoutingOnlyProcessor(remove,add));
this.targetPrefix = remove;
this.sourcePrefix = add;
identity = targetPrefix.equals(sourcePrefix);
}
private <T> T switchContext(T result, String from,String to)
throws IOException, ClassNotFoundException {
final ByteArrayOutputStream baos = new ByteArrayOutputStream();
final CloneOutput ostream = new CloneOutput(baos);
JMXNamespaceContext.serialize(ostream,result,from,null);
ostream.flush();
final byte[] bytes = baos.toByteArray();
final ByteArrayInputStream bais = new ByteArrayInputStream(bytes);
final CloneInput istream = new CloneInput(bais, ostream);
@SuppressWarnings("unchecked")
final T clone = (T) JMXNamespaceContext.deserialize(istream,null,to);
return clone;
}
@Override
@SuppressWarnings("unchecked")
public <T> T rewriteOutput(T result) {
if (identity) return result;
return (T) processOutput(result);
}
private Object processOutput(Object result) {
try {
if (result instanceof ObjectName)
return toTargetContext((ObjectName) result);
return switchContext(result,sourcePrefix,targetPrefix);
} catch (ClassNotFoundException x) {
throw new IllegalArgumentException("Can't process result: "+x,x);
} catch (IOException x) {
throw new IllegalArgumentException("Can't process result: "+x,x);
}
}
@Override
@SuppressWarnings("unchecked")
public <T> T rewriteInput(T input) {
if (identity) return input;
return (T) processInput(input);
}
private Object processInput(Object input) {
try {
if (input instanceof ObjectName)
return toSourceContext((ObjectName) input);
return switchContext(input,targetPrefix,sourcePrefix);
} catch (ClassNotFoundException x) {
throw new IllegalArgumentException("Can't process input: "+x,x);
} catch (IOException x) {
throw new IllegalArgumentException("Can't process input: "+x,x);
}
}
}

View File

@ -1,44 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>The <code>com.sun.jmx.namespace.serial</code> package</title>
<!--
Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
This code is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License version 2 only, as
published by the Free Software Foundation. Sun designates this
particular file as subject to the "Classpath" exception as provided
by Sun in the LICENSE file that accompanied this code.
This code is distributed in the hope that it will be useful, but WITHOUT
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
version 2 for more details (a copy is included in the LICENSE file that
accompanied this code).
You should have received a copy of the GNU General Public License version
2 along with this work; if not, write to the Free Software Foundation,
Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
CA 95054 USA or visit www.sun.com if you need additional information or
have any questions.
-->
</head>
<body bgcolor="white">
<p>The <code>com.sun.jmx.namespace.serial</code> package contains
sun specific implementation classes used to switch namespace
prefixes in ObjectName during serialization.
</p>
<p><b>NEVER USE THESE CLASSES DIRECTLY</b></p>
<p><b>
This API is a Sun internal API and is subject to changes without notice.
</b></p>
<p>The public API through which these proprietary classes can be invoked is
located in <code>javax.management.namespace.JMXNamespaces</code>
</p>
</body>
</html>

View File

@ -0,0 +1,188 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.remote.internal;
import java.util.Properties;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.NoSuchObjectException;
import java.util.Properties;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.NoSuchObjectException;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* A helper class for RMI-IIOP and CORBA APIs.
*/
public final class IIOPHelper {
private IIOPHelper() { }
// loads IIOPProxy implementation class if available
private static final String IMPL_CLASS =
"com.sun.jmx.remote.protocol.iiop.IIOPProxyImpl";
private static final IIOPProxy proxy =
AccessController.doPrivileged(new PrivilegedAction<IIOPProxy>() {
public IIOPProxy run() {
try {
Class<?> c = Class.forName(IMPL_CLASS, true, null);
return (IIOPProxy)c.newInstance();
} catch (ClassNotFoundException cnf) {
return null;
} catch (InstantiationException e) {
throw new AssertionError(e);
} catch (IllegalAccessException e) {
throw new AssertionError(e);
}
}});
/**
* Returns true if RMI-IIOP and CORBA is available.
*/
public static boolean isAvailable() {
return proxy != null;
}
private static void ensureAvailable() {
if (proxy == null)
throw new AssertionError("Should not here");
}
/**
* Returns true if the given object is a Stub.
*/
public static boolean isStub(Object obj) {
return (proxy == null) ? false : proxy.isStub(obj);
}
/**
* Returns the Delegate to which the given Stub delegates.
*/
public static Object getDelegate(Object stub) {
ensureAvailable();
return proxy.getDelegate(stub);
}
/**
* Sets the Delegate for a given Stub.
*/
public static void setDelegate(Object stub, Object delegate) {
ensureAvailable();
proxy.setDelegate(stub, delegate);
}
/**
* Returns the ORB associated with the given stub
*
* @throws UnsupportedOperationException
* if the object does not support the operation that
* was invoked
*/
public static Object getOrb(Object stub) {
ensureAvailable();
return proxy.getOrb(stub);
}
/**
* Connects the Stub to the given ORB.
*/
public static void connect(Object stub, Object orb)
throws RemoteException
{
ensureAvailable();
proxy.connect(stub, orb);
}
/**
* Returns true if the given object is an ORB.
*/
public static boolean isOrb(Object obj) {
ensureAvailable();
return proxy.isOrb(obj);
}
/**
* Creates, and returns, a new ORB instance.
*/
public static Object createOrb(String[] args, Properties props) {
ensureAvailable();
return proxy.createOrb(args, props);
}
/**
* Converts a string, produced by the object_to_string method, back
* to a CORBA object reference.
*/
public static Object stringToObject(Object orb, String str) {
ensureAvailable();
return proxy.stringToObject(orb, str);
}
/**
* Converts the given CORBA object reference to a string.
*/
public static String objectToString(Object orb, Object obj) {
ensureAvailable();
return proxy.objectToString(orb, obj);
}
/**
* Checks to ensure that an object of a remote or abstract interface
* type can be cast to a desired type.
*/
public static <T> T narrow(Object narrowFrom, Class<T> narrowTo) {
ensureAvailable();
return proxy.narrow(narrowFrom, narrowTo);
}
/**
* Makes a server object ready to receive remote calls
*/
public static void exportObject(Remote obj) throws RemoteException {
ensureAvailable();
proxy.exportObject(obj);
}
/**
* Deregisters a server object from the runtime.
*/
public static void unexportObject(Remote obj) throws NoSuchObjectException {
ensureAvailable();
proxy.unexportObject(obj);
}
/**
* Returns a stub for the given server object.
*/
public static Remote toStub(Remote obj) throws NoSuchObjectException {
ensureAvailable();
return proxy.toStub(obj);
}
}

View File

@ -0,0 +1,110 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.remote.internal;
import java.util.Properties;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.NoSuchObjectException;
/**
* An interface to a subset of the RMI-IIOP and CORBA APIs to avoid a
* static dependencies on the types defined by these APIs.
*/
public interface IIOPProxy {
/**
* Returns true if the given object is a Stub.
*/
boolean isStub(Object obj);
/**
* Returns the Delegate to which the given Stub delegates.
*/
Object getDelegate(Object stub);
/**
* Sets the Delegate for a given Stub.
*/
void setDelegate(Object stub, Object delegate);
/**
* Returns the ORB associated with the given stub
*
* @throws UnsupportedOperationException
* if the object does not support the operation that
* was invoked
*/
Object getOrb(Object stub);
/**
* Connects the Stub to the given ORB.
*/
void connect(Object stub, Object orb) throws RemoteException;
/**
* Returns true if the given object is an ORB.
*/
boolean isOrb(Object obj);
/**
* Creates, and returns, a new ORB instance.
*/
Object createOrb(String[] args, Properties props);
/**
* Converts a string, produced by the object_to_string method, back
* to a CORBA object reference.
*/
Object stringToObject(Object orb, String str);
/**
* Converts the given CORBA object reference to a string.
*/
String objectToString(Object orb, Object obj);
/**
* Checks to ensure that an object of a remote or abstract interface
* type can be cast to a desired type.
*/
<T> T narrow(Object narrowFrom, Class<T> narrowTo);
/**
* Makes a server object ready to receive remote calls
*/
void exportObject(Remote obj) throws RemoteException;
/**
* Deregisters a server object from the runtime.
*/
void unexportObject(Remote obj) throws NoSuchObjectException;
/**
* Returns a stub for the given server object.
*/
Remote toStub(Remote obj) throws NoSuchObjectException;
}

View File

@ -86,8 +86,7 @@ public class ServerNotifForwarder {
// Explicitly check MBeanPermission for addNotificationListener
//
checkMBeanPermission(getMBeanServerName(),
mbeanServer, name, "addNotificationListener");
checkMBeanPermission(name, "addNotificationListener");
if (notificationAccessController != null) {
notificationAccessController.addNotificationListener(
connectionId, name, getSubject());
@ -157,8 +156,7 @@ public class ServerNotifForwarder {
// Explicitly check MBeanPermission for removeNotificationListener
//
checkMBeanPermission(getMBeanServerName(),
mbeanServer, name, "removeNotificationListener");
checkMBeanPermission(name, "removeNotificationListener");
if (notificationAccessController != null) {
notificationAccessController.removeNotificationListener(
connectionId, name, getSubject());
@ -333,8 +331,8 @@ public class ServerNotifForwarder {
* Explicitly check the MBeanPermission for
* the current access control context.
*/
public static void checkMBeanPermission(String serverName,
final MBeanServer mbs, final ObjectName name, final String actions)
public void checkMBeanPermission(
final ObjectName name, final String actions)
throws InstanceNotFoundException, SecurityException {
SecurityManager sm = System.getSecurityManager();
if (sm != null) {
@ -345,7 +343,7 @@ public class ServerNotifForwarder {
new PrivilegedExceptionAction<ObjectInstance>() {
public ObjectInstance run()
throws InstanceNotFoundException {
return mbs.getObjectInstance(name);
return mbeanServer.getObjectInstance(name);
}
});
} catch (PrivilegedActionException e) {
@ -353,7 +351,6 @@ public class ServerNotifForwarder {
}
String classname = oi.getClassName();
MBeanPermission perm = new MBeanPermission(
serverName,
classname,
null,
name,
@ -369,8 +366,7 @@ public class ServerNotifForwarder {
TargetedNotification tn) {
try {
if (checkNotificationEmission) {
checkMBeanPermission(getMBeanServerName(),
mbeanServer, name, "addNotificationListener");
checkMBeanPermission(name, "addNotificationListener");
}
if (notificationAccessController != null) {
notificationAccessController.fetchNotification(
@ -432,27 +428,12 @@ public class ServerNotifForwarder {
}
}
private String getMBeanServerName() {
if (mbeanServerName != null) return mbeanServerName;
else return (mbeanServerName = getMBeanServerName(mbeanServer));
}
private static String getMBeanServerName(final MBeanServer server) {
final PrivilegedAction<String> action = new PrivilegedAction<String>() {
public String run() {
return Util.getMBeanServerSecurityName(server);
}
};
return AccessController.doPrivileged(action);
}
//------------------
// PRIVATE VARIABLES
//------------------
private MBeanServer mbeanServer;
private volatile String mbeanServerName;
private final String connectionId;
@ -462,7 +443,7 @@ public class ServerNotifForwarder {
private final static int[] listenerCounterLock = new int[0];
private NotificationBuffer notifBuffer;
private Map<ObjectName, Set<IdAndFilter>> listenerMap =
private final Map<ObjectName, Set<IdAndFilter>> listenerMap =
new HashMap<ObjectName, Set<IdAndFilter>>();
private boolean terminated = false;

View File

@ -0,0 +1,119 @@
/*
* Copyright 2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.remote.protocol.iiop;
import org.omg.CORBA.ORB;
import org.omg.CORBA.portable.Delegate;
import javax.rmi.PortableRemoteObject;
import javax.rmi.CORBA.Stub;
import java.util.Properties;
import java.rmi.Remote;
import java.rmi.RemoteException;
import java.rmi.NoSuchObjectException;
import com.sun.jmx.remote.internal.IIOPProxy;
/**
* An implementatin of IIOPProxy that simply delegates to the appropriate
* RMI-IIOP and CORBA APIs.
*/
public class IIOPProxyImpl implements IIOPProxy {
public IIOPProxyImpl() { }
@Override
public boolean isStub(Object obj) {
return (obj instanceof Stub);
}
@Override
public Object getDelegate(Object stub) {
return ((Stub)stub)._get_delegate();
}
@Override
public void setDelegate(Object stub, Object delegate) {
((Stub)stub)._set_delegate((Delegate)delegate);
}
@Override
public Object getOrb(Object stub) {
try {
return ((Stub)stub)._orb();
} catch (org.omg.CORBA.BAD_OPERATION x) {
throw new UnsupportedOperationException(x);
}
}
@Override
public void connect(Object stub, Object orb)
throws RemoteException
{
((Stub)stub).connect((ORB)orb);
}
@Override
public boolean isOrb(Object obj) {
return (obj instanceof ORB);
}
@Override
public Object createOrb(String[] args, Properties props) {
return ORB.init(args, props);
}
@Override
public Object stringToObject(Object orb, String str) {
return ((ORB)orb).string_to_object(str);
}
@Override
public String objectToString(Object orb, Object obj) {
return ((ORB)orb).object_to_string((org.omg.CORBA.Object)obj);
}
@Override
@SuppressWarnings("unchecked")
public <T> T narrow(Object narrowFrom, Class<T> narrowTo) {
return (T)PortableRemoteObject.narrow(narrowFrom, narrowTo);
}
@Override
public void exportObject(Remote obj) throws RemoteException {
PortableRemoteObject.exportObject(obj);
}
@Override
public void unexportObject(Remote obj) throws NoSuchObjectException {
PortableRemoteObject.unexportObject(obj);
}
@Override
public Remote toStub(Remote obj) throws NoSuchObjectException {
return PortableRemoteObject.toStub(obj);
}
}

View File

@ -23,7 +23,7 @@
* have any questions.
*/
package com.sun.jmx.remote.internal;
package com.sun.jmx.remote.protocol.iiop;
import java.io.IOException;
import java.io.Serializable;

View File

@ -780,25 +780,6 @@ public class EnvHelp {
return new Hashtable<K, V>(m);
}
/**
* Returns true if the parameter JMXConnector.USE_EVENT_SERVICE is set to a
* String equals "true" by ignoring case in the map or in the System.
*/
public static boolean eventServiceEnabled(Map<String, ?> env) {
return computeBooleanFromString(env, JMXConnector.USE_EVENT_SERVICE, true);
}
/**
* Returns true if the parameter JMXConnectorServer.DELEGATE_TO_EVENT_SERVICE
* is set to a String equals "true" (ignores case).
* If the property DELEGATE_TO_EVENT_SERVICE is not set, returns
* a default value of "true".
*/
public static boolean delegateToEventService(Map<String, ?> env) {
return computeBooleanFromString(env,
JMXConnectorServer.DELEGATE_TO_EVENT_SERVICE, true, true);
}
/**
* <p>Name of the attribute that specifies whether a connector server
* should not prevent the VM from exiting
@ -817,46 +798,6 @@ public class EnvHelp {
("true".equalsIgnoreCase((String)env.get(JMX_SERVER_DAEMON)));
}
// /**
// * <p>Name of the attribute that specifies an EventRelay object to use.
// */
// public static final String EVENT_RELAY =
// "jmx.remote.x.event.relay";
//
//
// /**
// * Returns an EventRelay object. The default one is FetchingEventRelay.
// * If {@code EVENT_RELAY} is specified in {@code env} as a key,
// * its value will be returned as an EventRelay object, if the value is
// * not of type {@code EventRelay}, the default {@code FetchingEventRelay}
// * will be returned.
// * If {@code EVENT_RELAY} is not specified but {@code ENABLE_EVENT_RELAY}
// * is specified as a key and its value is <code true>, the default {@code FetchingEventRelay}
// * will be returned.
// */
// public static EventRelay getEventRelay(Map env) {
// Map info = env == null ?
// Collections.EMPTY_MAP : env;
//
// Object o = env.get(EVENT_RELAY);
// if (o instanceof EventRelay) {
// return (EventRelay)o;
// } else if (o != null) {
// logger.warning("getEventRelay",
// "The user specified object is not an EventRelay object, " +
// "using the default class FetchingEventRelay.");
//
// return new FetchingEventRelay();
// }
//
// if (enableEventRelay(env)) {
// return new FetchingEventRelay();
// }
//
// return null;
// }
private static final class SinkOutputStream extends OutputStream {
public void write(byte[] b, int off, int len) {}
public void write(int b) {}

View File

@ -1,469 +0,0 @@
/*
* Copyright 2007-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Sun designates this
* particular file as subject to the "Classpath" exception as provided
* by Sun in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
package com.sun.jmx.remote.util;
import com.sun.jmx.defaults.JmxProperties;
import com.sun.jmx.event.EventClientFactory;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.Arrays;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.management.MBeanServerConnection;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.event.EventClient;
import javax.management.event.EventClientDelegate;
import javax.management.namespace.JMXNamespaces;
/**
* Class EventClientConnection - a {@link Proxy} that wraps an
* {@link MBeanServerConnection} and an {@link EventClient}.
* All methods are routed to the underlying {@code MBeanServerConnection},
* except add/remove notification listeners which are routed to the
* {@code EventClient}.
* The caller only sees an {@code MBeanServerConnection} which uses an
* {@code EventClient} behind the scenes.
*
* @author Sun Microsystems, Inc.
*/
public class EventClientConnection implements InvocationHandler,
EventClientFactory {
/**
* A logger for this class.
**/
private static final Logger LOG = JmxProperties.NOTIFICATION_LOGGER;
private static final int NAMESPACE_SEPARATOR_LENGTH =
JMXNamespaces.NAMESPACE_SEPARATOR.length();
/**
* Creates a new {@code EventClientConnection}.
* @param connection The underlying MBeanServerConnection.
*/
public EventClientConnection(MBeanServerConnection connection) {
this(connection,null);
}
/**
* Creates a new {@code EventClientConnection}.
* @param connection The underlying MBeanServerConnection.
* @param eventClientFactory a factory object that will be invoked
* to create an {@link EventClient} when needed.
* The {@code EventClient} is created lazily, when it is needed
* for the first time. If null, a default factory will be used
* (see {@link #createEventClient}).
*/
public EventClientConnection(MBeanServerConnection connection,
Callable<EventClient> eventClientFactory) {
if (connection == null) {
throw new IllegalArgumentException("Null connection");
}
this.connection = connection;
if (eventClientFactory == null) {
eventClientFactory = new Callable<EventClient>() {
public final EventClient call() throws Exception {
return createEventClient(EventClientConnection.this.connection);
}
};
}
this.eventClientFactory = eventClientFactory;
this.lock = new ReentrantLock();
}
/**
* <p>The MBean server connection through which the methods of
* a proxy using this handler are forwarded.</p>
*
* @return the MBean server connection.
*
* @since 1.6
*/
public MBeanServerConnection getMBeanServerConnection() {
return connection;
}
/**
* Creates a new EventClientConnection proxy instance.
*
* @param <T> The underlying {@code MBeanServerConnection} - which should
* not be using the Event Service itself.
* @param interfaceClass {@code MBeanServerConnection.class}, or a subclass.
* @param eventClientFactory a factory used to create the EventClient.
* If null, a default factory is used (see {@link
* #createEventClient}).
* @return the new proxy instance, which will route add/remove notification
* listener calls through an {@code EventClient}.
*
*/
private static <T extends MBeanServerConnection> T
newProxyInstance(T connection,
Class<T> interfaceClass, Callable<EventClient> eventClientFactory) {
final InvocationHandler handler =
new EventClientConnection(connection,eventClientFactory);
final Class<?>[] interfaces =
new Class<?>[] {interfaceClass, EventClientFactory.class};
Object proxy =
Proxy.newProxyInstance(interfaceClass.getClassLoader(),
interfaces,
handler);
return interfaceClass.cast(proxy);
}
public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable {
final String methodName = method.getName();
// add/remove notification listener are routed to the EventClient
if (methodName.equals("addNotificationListener")
|| methodName.equals("removeNotificationListener")) {
final Class<?>[] sig = method.getParameterTypes();
if (sig.length>1 &&
NotificationListener.class.isAssignableFrom(sig[1])) {
return invokeBroadcasterMethod(proxy,method,args);
}
}
// subscribe/unsubscribe are also routed to the EventClient.
final Class<?> clazz = method.getDeclaringClass();
if (clazz.equals(EventClientFactory.class)) {
return invokeEventClientSubscriberMethod(proxy,method,args);
}
// local or not: equals, toString, hashCode
if (shouldDoLocally(proxy, method))
return doLocally(proxy, method, args);
return call(connection,method,args);
}
// The purpose of this method is to unwrap InvocationTargetException,
// in order to avoid throwing UndeclaredThrowableException for
// declared exceptions.
//
// When calling method.invoke(), any exception thrown by the invoked
// method will be wrapped in InvocationTargetException. If we don't
// unwrap this exception, the proxy will always throw
// UndeclaredThrowableException, even for runtime exceptions.
//
private Object call(final Object obj, final Method m,
final Object[] args)
throws Throwable {
try {
return m.invoke(obj,args);
} catch (InvocationTargetException x) {
final Throwable xx = x.getTargetException();
if (xx == null) throw x;
else throw xx;
}
}
/**
* Route add/remove notification listener to the event client.
**/
private Object invokeBroadcasterMethod(Object proxy, Method method,
Object[] args) throws Exception {
final String methodName = method.getName();
final int nargs = (args == null) ? 0 : args.length;
if (nargs < 1) {
final String msg =
"Bad arg count: " + nargs;
throw new IllegalArgumentException(msg);
}
final ObjectName mbean = (ObjectName) args[0];
final EventClient evtClient = getEventClient();
// Fails if evtClient is null AND the MBean we try to listen to is
// in a subnamespace. We fail here because we know this will not
// work.
//
// Note that if the wrapped MBeanServerConnection points to a an
// earlier agent (JDK 1.6 or earlier), then the EventClient will
// be null (we can't use the event service with earlier JDKs).
//
// In principle a null evtClient indicates that the remote VM is of
// an earlier version, in which case it shouldn't contain any namespace.
//
// So having a null evtClient AND an MBean contained in a namespace is
// clearly an error case.
//
if (evtClient == null) {
final String domain = mbean.getDomain();
final int index = domain.indexOf(JMXNamespaces.NAMESPACE_SEPARATOR);
if (index > -1 && index <
(domain.length()-NAMESPACE_SEPARATOR_LENGTH)) {
throw new UnsupportedOperationException(method.getName()+
" on namespace "+domain.substring(0,index+
NAMESPACE_SEPARATOR_LENGTH));
}
}
if (methodName.equals("addNotificationListener")) {
/* The various throws of IllegalArgumentException here
should not happen, since we know what the methods in
NotificationBroadcaster and NotificationEmitter
are. */
if (nargs != 4) {
final String msg =
"Bad arg count to addNotificationListener: " + nargs;
throw new IllegalArgumentException(msg);
}
/* Other inconsistencies will produce ClassCastException
below. */
final NotificationListener listener = (NotificationListener) args[1];
final NotificationFilter filter = (NotificationFilter) args[2];
final Object handback = args[3];
if (evtClient != null) {
// general case
evtClient.addNotificationListener(mbean,listener,filter,handback);
} else {
// deprecated case. Only works for mbean in local namespace.
connection.addNotificationListener(mbean,listener,filter,
handback);
}
return null;
} else if (methodName.equals("removeNotificationListener")) {
/* NullPointerException if method with no args, but that
shouldn't happen because removeNL does have args. */
NotificationListener listener = (NotificationListener) args[1];
switch (nargs) {
case 2:
if (evtClient != null) {
// general case
evtClient.removeNotificationListener(mbean,listener);
} else {
// deprecated case. Only works for mbean in local namespace.
connection.removeNotificationListener(mbean, listener);
}
return null;
case 4:
NotificationFilter filter = (NotificationFilter) args[2];
Object handback = args[3];
if (evtClient != null) {
evtClient.removeNotificationListener(mbean,
listener,
filter,
handback);
} else {
connection.removeNotificationListener(mbean,
listener,
filter,
handback);
}
return null;
default:
final String msg =
"Bad arg count to removeNotificationListener: " + nargs;
throw new IllegalArgumentException(msg);
}
} else {
throw new IllegalArgumentException("Bad method name: " +
methodName);
}
}
private boolean shouldDoLocally(Object proxy, Method method) {
final String methodName = method.getName();
if ((methodName.equals("hashCode") || methodName.equals("toString"))
&& method.getParameterTypes().length == 0
&& isLocal(proxy, method))
return true;
if (methodName.equals("equals")
&& Arrays.equals(method.getParameterTypes(),
new Class<?>[] {Object.class})
&& isLocal(proxy, method))
return true;
return false;
}
private Object doLocally(Object proxy, Method method, Object[] args) {
final String methodName = method.getName();
if (methodName.equals("equals")) {
if (this == args[0]) {
return true;
}
if (!(args[0] instanceof Proxy)) {
return false;
}
final InvocationHandler ihandler =
Proxy.getInvocationHandler(args[0]);
if (ihandler == null ||
!(ihandler instanceof EventClientConnection)) {
return false;
}
final EventClientConnection handler =
(EventClientConnection)ihandler;
return connection.equals(handler.connection) &&
proxy.getClass().equals(args[0].getClass());
} else if (methodName.equals("hashCode")) {
return connection.hashCode();
}
throw new RuntimeException("Unexpected method name: " + methodName);
}
private static boolean isLocal(Object proxy, Method method) {
final Class<?>[] interfaces = proxy.getClass().getInterfaces();
if(interfaces == null) {
return true;
}
final String methodName = method.getName();
final Class<?>[] params = method.getParameterTypes();
for (Class<?> intf : interfaces) {
try {
intf.getMethod(methodName, params);
return false; // found method in one of our interfaces
} catch (NoSuchMethodException nsme) {
// OK.
}
}
return true; // did not find in any interface
}
/**
* Return the EventClient used by this object. Can be null if the
* remote VM is of an earlier JDK version which doesn't have the
* event service.<br>
* This method will invoke the event client factory the first time
* it is called.
**/
public final EventClient getEventClient() {
if (initialized) return client;
try {
if (!lock.tryLock(TRYLOCK_TIMEOUT,TimeUnit.SECONDS))
throw new IllegalStateException("can't acquire lock");
try {
client = eventClientFactory.call();
initialized = true;
} finally {
lock.unlock();
}
} catch (RuntimeException x) {
throw x;
} catch (Exception x) {
throw new IllegalStateException("Can't create EventClient: "+x,x);
}
return client;
}
/**
* Returns an event client for the wrapped {@code MBeanServerConnection}.
* This is the method invoked by the default event client factory.
* @param connection the wrapped {@code MBeanServerConnection}.
**/
protected EventClient createEventClient(MBeanServerConnection connection)
throws Exception {
final ObjectName name =
EventClientDelegate.OBJECT_NAME;
if (connection.isRegistered(name)) {
return new EventClient(connection);
}
return null;
}
/**
* Creates a new {@link MBeanServerConnection} that goes through an
* {@link EventClient} to receive/subscribe to notifications.
* @param connection the underlying {@link MBeanServerConnection}.
* The given <code>connection</code> shouldn't be already
* using an {@code EventClient}.
* @param eventClientFactory a factory object that will be invoked
* to create an {@link EventClient} when needed.
* The {@code EventClient} is created lazily, when it is needed
* for the first time. If null, a default factory will be used
* (see {@link #createEventClient}).
* @return the MBeanServerConnection.
**/
public static MBeanServerConnection getEventConnectionFor(
MBeanServerConnection connection,
Callable<EventClient> eventClientFactory) {
if (connection instanceof EventClientFactory
&& eventClientFactory != null)
throw new IllegalArgumentException("connection already uses EventClient");
if (connection instanceof EventClientFactory)
return connection;
// create a new proxy using an event client.
//
if (LOG.isLoggable(Level.FINE))
LOG.fine("Creating EventClient for: "+connection);
return newProxyInstance(connection,
MBeanServerConnection.class,
eventClientFactory);
}
private Object invokeEventClientSubscriberMethod(Object proxy,
Method method, Object[] args) throws Throwable {
return call(this,method,args);
}
// Maximum lock timeout in seconds. Obviously arbitrary.
//
private final static short TRYLOCK_TIMEOUT = 3;
private final MBeanServerConnection connection;
private final Callable<EventClient> eventClientFactory;
private final Lock lock;
private volatile EventClient client = null;
private volatile boolean initialized = false;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright 1999-2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1999-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -32,12 +32,8 @@ import java.io.IOException;
import java.io.OutputStream;
import java.io.InputStream;
import java.net.Socket;
import java.util.Vector;
import java.util.Hashtable;
import javax.naming.CommunicationException;
import javax.naming.AuthenticationException;
import javax.naming.AuthenticationNotSupportedException;
import javax.naming.ServiceUnavailableException;
import javax.naming.NamingException;
import javax.naming.InterruptedNamingException;
@ -47,6 +43,8 @@ import javax.naming.ldap.Control;
import java.lang.reflect.Method;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.Arrays;
import sun.misc.IOUtils;
//import javax.net.SocketFactory;
/**
@ -799,7 +797,6 @@ public final class Connection implements Runnable {
byte inbuf[]; // Buffer for reading incoming bytes
int inMsgId; // Message id of incoming response
int bytesread; // Number of bytes in inbuf
int bytesleft; // Number of bytes that need to read for completing resp
int br; // Temp; number of bytes read from stream
int offset; // Offset of where to store bytes in inbuf
int seqlen; // Length of ASN sequence
@ -811,7 +808,7 @@ public final class Connection implements Runnable {
try {
while (true) {
try {
inbuf = new byte[2048];
inbuf = new byte[10];
offset = 0;
seqlen = 0;
@ -871,19 +868,10 @@ public final class Connection implements Runnable {
}
// read in seqlen bytes
bytesleft = seqlen;
if ((offset + bytesleft) > inbuf.length) {
byte nbuf[] = new byte[offset + bytesleft];
System.arraycopy(inbuf, 0, nbuf, 0, offset);
inbuf = nbuf;
}
while (bytesleft > 0) {
bytesread = in.read(inbuf, offset, bytesleft);
if (bytesread < 0)
break; // EOF
offset += bytesread;
bytesleft -= bytesread;
}
byte[] left = IOUtils.readFully(in, seqlen, false);
inbuf = Arrays.copyOf(inbuf, offset + left.length);
System.arraycopy(left, 0, inbuf, offset, left.length);
offset += left.length;
/*
if (dump > 0) {
System.err.println("seqlen: " + seqlen);

View File

@ -40,7 +40,6 @@ import java.util.List;
import java.security.Principal;
import java.security.cert.X509Certificate;
import java.security.cert.CertificateException;
import javax.security.auth.kerberos.KerberosPrincipal;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
@ -413,14 +412,15 @@ final public class StartTlsResponseImpl extends StartTlsResponse {
try {
HostnameChecker checker = HostnameChecker.getInstance(
HostnameChecker.TYPE_LDAP);
Principal principal = getPeerPrincipal(session);
if (principal instanceof KerberosPrincipal) {
if (!checker.match(hostname, (KerberosPrincipal) principal)) {
// Use ciphersuite to determine whether Kerberos is active.
if (session.getCipherSuite().startsWith("TLS_KRB5")) {
Principal principal = getPeerPrincipal(session);
if (!checker.match(hostname, principal)) {
throw new SSLPeerUnverifiedException(
"hostname of the kerberos principal:" + principal +
" does not match the hostname:" + hostname);
}
} else {
} else { // X.509
// get the subject's certificate
certs = session.getPeerCertificates();

View File

@ -36,7 +36,6 @@ import java.security.Principal;
import java.security.cert.*;
import javax.security.auth.x500.X500Principal;
import javax.security.auth.kerberos.KerberosPrincipal;
import sun.security.util.HostnameChecker;
import sun.security.util.DerValue;
@ -109,20 +108,18 @@ class VerifierWrapper implements javax.net.ssl.HostnameVerifier {
/*
* In com.sun.net.ssl.HostnameVerifier the method is defined
* as verify(String urlHostname, String certHostname).
* This means we need to extract the hostname from the certificate
* in this wrapper
* This means we need to extract the hostname from the X.509 certificate
* or from the Kerberos principal name, in this wrapper.
*/
public boolean verify(String hostname, javax.net.ssl.SSLSession session) {
try {
String serverName;
Principal principal = getPeerPrincipal(session);
// X.500 principal or Kerberos principal.
// (Use ciphersuite check to determine whether Kerberos is present.)
if (session.getCipherSuite().startsWith("TLS_KRB5") &&
principal instanceof KerberosPrincipal) {
// Use ciphersuite to determine whether Kerberos is active.
if (session.getCipherSuite().startsWith("TLS_KRB5")) {
serverName =
HostnameChecker.getServerName((KerberosPrincipal)principal);
} else {
HostnameChecker.getServerName(getPeerPrincipal(session));
} else { // X.509
Certificate[] serverChain = session.getPeerCertificates();
if ((serverChain == null) || (serverChain.length == 0)) {
return false;

View File

@ -229,6 +229,21 @@ public class Applet extends Panel {
resize(d.width, d.height);
}
/**
* Indicates if this container is a validate root.
* <p>
* {@code Applet} objects are the validate roots, and, therefore, they
* override this method to return {@code true}.
*
* @return {@code true}
* @since 1.7
* @see java.awt.Container#isValidateRoot
*/
@Override
public boolean isValidateRoot() {
return true;
}
/**
* Requests that the argument string be displayed in the
* "status window". Many browsers and applet viewers

View File

@ -1,5 +1,5 @@
/*
* Copyright 1997-2005 Sun Microsystems, Inc. All Rights Reserved.
* Copyright 1997-2009 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -92,7 +92,15 @@ import java.security.BasicPermission;
* <td>Enter full-screen exclusive mode</td>
* <td>Entering full-screen exclusive mode allows direct access to
* low-level graphics card memory. This could be used to spoof the
* system, since the program is in direct control of rendering.</td>
* system, since the program is in direct control of rendering. Depending on
* the implementation, the security warning may not be shown for the windows
* used to enter the full-screen exclusive mode (assuming that the {@code
* fullScreenExclusive} permission has been granted to this application). Note
* that this behavior does not mean that the {@code
* showWindowWithoutWarningBanner} permission will be automatically granted to
* the application which has the {@code fullScreenExclusive} permission:
* non-full-screen windows will continue to be shown with the security
* warning.</td>
* </tr>
*
* <tr>

View File

@ -2764,8 +2764,11 @@ public abstract class Component implements ImageObserver, MenuContainer,
}
/**
* Ensures that this component has a valid layout. This method is
* primarily intended to operate on instances of <code>Container</code>.
* Validates this component.
* <p>
* The meaning of the term <i>validating</i> is defined by the ancestors of
* this class. See {@link Container#validate} for more details.
*
* @see #invalidate
* @see #doLayout()
* @see LayoutManager
@ -2794,12 +2797,24 @@ public abstract class Component implements ImageObserver, MenuContainer,
}
/**
* Invalidates this component. This component and all parents
* above it are marked as needing to be laid out. This method can
* be called often, so it needs to execute quickly.
* Invalidates this component and its ancestors.
* <p>
* All the ancestors of this component up to the nearest validate root are
* marked invalid also. If there is no a validate root container for this
* component, all of its ancestors up to the root of the hierarchy are
* marked invalid as well. Marking a container <i>invalid</i> indicates
* that the container needs to be laid out.
* <p>
* This method is called automatically when any layout-related information
* changes (e.g. setting the bounds of the component, or adding the
* component to a container).
* <p>
* This method might be called often, so it should work fast.
*
* @see #validate
* @see #doLayout
* @see LayoutManager
* @see java.awt.Container#isValidateRoot
* @since JDK1.0
*/
public void invalidate() {
@ -2818,9 +2833,18 @@ public abstract class Component implements ImageObserver, MenuContainer,
if (!isMaximumSizeSet()) {
maxSize = null;
}
if (parent != null) {
parent.invalidateIfValid();
}
invalidateParent();
}
}
/**
* Invalidates the parent of this component if any.
*
* This method MUST BE invoked under the TreeLock.
*/
void invalidateParent() {
if (parent != null) {
parent.invalidateIfValid();
}
}
@ -6727,12 +6751,13 @@ public abstract class Component implements ImageObserver, MenuContainer,
}
}
} else {
// It's native. If the parent is lightweight it
// will need some help.
Container parent = this.parent;
if (parent != null && parent.peer instanceof LightweightPeer) {
// It's native. If the parent is lightweight it will need some
// help.
Container parent = getContainer();
if (parent != null && parent.isLightweight()) {
relocateComponent();
if (!isRecursivelyVisible()) {
if (!parent.isRecursivelyVisibleUpToHeavyweightContainer())
{
peer.setVisible(false);
}
}

View File

@ -1492,20 +1492,59 @@ public class Container extends Component {
}
/**
* Invalidates the container. The container and all parents
* above it are marked as needing to be laid out. This method can
* be called often, so it needs to execute quickly.
* Indicates if this container is a <i>validate root</i>.
* <p>
* Layout-related changes, such as bounds of the validate root descendants,
* do not affect the layout of the validate root parent. This peculiarity
* enables the {@code invalidate()} method to stop invalidating the
* component hierarchy when the method encounters a validate root.
* <p>
* If a component hierarchy contains validate roots, the {@code validate()}
* method must be invoked on the validate root of a previously invalidated
* component, rather than on the top-level container (such as a {@code
* Frame} object) to restore the validity of the hierarchy later.
* <p>
* The {@code Window} class and the {@code Applet} class are the validate
* roots in AWT. Swing introduces more validate roots.
*
* <p> If the {@code LayoutManager} installed on this container is
* an instance of {@code LayoutManager2}, then
* {@link LayoutManager2#invalidateLayout(Container)} is invoked on
* it supplying this {@code Container} as the argument.
* @return whether this container is a validate root
* @see #invalidate
* @see java.awt.Component#invalidate
* @see javax.swing.JComponent#isValidateRoot
* @see javax.swing.JComponent#revalidate
* @since 1.7
*/
public boolean isValidateRoot() {
return false;
}
/**
* Invalidates the parent of the container unless the container
* is a validate root.
*/
@Override
void invalidateParent() {
if (!isValidateRoot()) {
super.invalidateParent();
}
}
/**
* Invalidates the container.
* <p>
* If the {@code LayoutManager} installed on this container is an instance
* of the {@code LayoutManager2} interface, then
* the {@link LayoutManager2#invalidateLayout(Container)} method is invoked
* on it supplying this {@code Container} as the argument.
* <p>
* Afterwards this method marks this container invalid, and invalidates its
* ancestors. See the {@link Component#invalidate} method for more details.
*
* @see #validate
* @see #layout
* @see LayoutManager
* @see LayoutManager2#invalidateLayout(Container)
* @see LayoutManager2
*/
@Override
public void invalidate() {
LayoutManager layoutMgr = this.layoutMgr;
if (layoutMgr instanceof LayoutManager2) {
@ -1518,52 +1557,90 @@ public class Container extends Component {
/**
* Validates this container and all of its subcomponents.
* <p>
* The <code>validate</code> method is used to cause a container
* to lay out its subcomponents again. It should be invoked when
* this container's subcomponents are modified (added to or
* removed from the container, or layout-related information
* changed) after the container has been displayed.
*
* <p>If this {@code Container} is not valid, this method invokes
* Validating a container means laying out its subcomponents.
* Layout-related changes, such as setting the bounds of a component, or
* adding a component to the container, invalidate the container
* automatically. Note that the ancestors of the container may be
* invalidated also (see {@link Component#invalidate} for details.)
* Therefore, to restore the validity of the hierarchy, the {@code
* validate()} method should be invoked on a validate root of an
* invalidated component, or on the top-most container if the hierarchy
* does not contain validate roots.
* <p>
* Validating the container may be a quite time-consuming operation. For
* performance reasons a developer may postpone the validation of the
* hierarchy till a set of layout-related operations completes, e.g. after
* adding all the children to the container.
* <p>
* If this {@code Container} is not valid, this method invokes
* the {@code validateTree} method and marks this {@code Container}
* as valid. Otherwise, no action is performed.
* <p>
* Note that the {@code invalidate()} method may invalidate not only the
* component it is called upon, but also the parents of the component.
* Therefore, to restore the validity of the hierarchy, the {@code
* validate()} method must be invoked on the top-most invalid container of
* the hierarchy. For performance reasons a developer may postpone the
* validation of the hierarchy till a bunch of layout-related operations
* completes, e.g. after adding all the children to the container.
*
* @see #add(java.awt.Component)
* @see #invalidate
* @see Container#isValidateRoot
* @see javax.swing.JComponent#revalidate()
* @see #validateTree
*/
public void validate() {
/* Avoid grabbing lock unless really necessary. */
if (!isValid()) {
boolean updateCur = false;
synchronized (getTreeLock()) {
if (!isValid() && peer != null) {
ContainerPeer p = null;
if (peer instanceof ContainerPeer) {
p = (ContainerPeer) peer;
}
if (p != null) {
p.beginValidate();
}
validateTree();
if (p != null) {
p.endValidate();
boolean updateCur = false;
synchronized (getTreeLock()) {
if ((!isValid() || descendUnconditionallyWhenValidating)
&& peer != null)
{
ContainerPeer p = null;
if (peer instanceof ContainerPeer) {
p = (ContainerPeer) peer;
}
if (p != null) {
p.beginValidate();
}
validateTree();
if (p != null) {
p.endValidate();
// Avoid updating cursor if this is an internal call.
// See validateUnconditionally() for details.
if (!descendUnconditionallyWhenValidating) {
updateCur = isVisible();
}
}
}
if (updateCur) {
updateCursorImmediately();
}
if (updateCur) {
updateCursorImmediately();
}
}
/**
* Indicates whether valid containers should also traverse their
* children and call the validateTree() method on them.
*
* Synchronization: TreeLock.
*
* The field is allowed to be static as long as the TreeLock itself is
* static.
*
* @see #validateUnconditionally()
*/
private static boolean descendUnconditionallyWhenValidating = false;
/**
* Unconditionally validate the component hierarchy.
*/
final void validateUnconditionally() {
boolean updateCur = false;
synchronized (getTreeLock()) {
descendUnconditionallyWhenValidating = true;
validate();
if (peer instanceof ContainerPeer) {
updateCur = isVisible();
}
descendUnconditionallyWhenValidating = false;
}
if (updateCur) {
updateCursorImmediately();
}
}
@ -1578,16 +1655,20 @@ public class Container extends Component {
*/
protected void validateTree() {
checkTreeLock();
if (!isValid()) {
if (!isValid() || descendUnconditionallyWhenValidating) {
if (peer instanceof ContainerPeer) {
((ContainerPeer)peer).beginLayout();
}
doLayout();
if (!isValid()) {
doLayout();
}
for (int i = 0; i < component.size(); i++) {
Component comp = component.get(i);
if ( (comp instanceof Container)
&& !(comp instanceof Window)
&& !comp.isValid()) {
&& (!comp.isValid() ||
descendUnconditionallyWhenValidating))
{
((Container)comp).validateTree();
} else {
comp.validate();
@ -4092,16 +4173,29 @@ public class Container extends Component {
}
}
/*
/**
* Checks if the container and its direct lightweight containers are
* visible.
*
* Consider the heavyweight container hides or shows the HW descendants
* automatically. Therefore we care of LW containers' visibility only.
*
* This method MUST be invoked under the TreeLock.
*/
private boolean isRecursivelyVisibleUpToHeavyweightContainer() {
final boolean isRecursivelyVisibleUpToHeavyweightContainer() {
if (!isLightweight()) {
return true;
}
return isVisible() && (getContainer() == null ||
getContainer().isRecursivelyVisibleUpToHeavyweightContainer());
for (Container cont = getContainer();
cont != null && cont.isLightweight();
cont = cont.getContainer())
{
if (!cont.isVisible()) {
return false;
}
}
return true;
}
@Override

View File

@ -1027,7 +1027,9 @@ public class EventQueue {
synchronized (lock) {
Toolkit.getEventQueue().postEvent(event);
lock.wait();
while (!event.isDispatched()) {
lock.wait();
}
}
Throwable eventThrowable = event.getThrowable();

Some files were not shown because too many files have changed in this diff Show More