提交 6fd650ad 编写于 作者: T tbell

Merge

...@@ -160,10 +160,8 @@ CORE_PKGS = \ ...@@ -160,10 +160,8 @@ CORE_PKGS = \
javax.lang.model.type \ javax.lang.model.type \
javax.lang.model.util \ javax.lang.model.util \
javax.management \ javax.management \
javax.management.event \
javax.management.loading \ javax.management.loading \
javax.management.monitor \ javax.management.monitor \
javax.management.namespace \
javax.management.relation \ javax.management.relation \
javax.management.openmbean \ javax.management.openmbean \
javax.management.timer \ javax.management.timer \
......
...@@ -251,6 +251,7 @@ JAVA_JAVA_java = \ ...@@ -251,6 +251,7 @@ JAVA_JAVA_java = \
java/util/IdentityHashMap.java \ java/util/IdentityHashMap.java \
java/util/EnumMap.java \ java/util/EnumMap.java \
java/util/Arrays.java \ java/util/Arrays.java \
java/util/DualPivotQuicksort.java \
java/util/TimSort.java \ java/util/TimSort.java \
java/util/ComparableTimSort.java \ java/util/ComparableTimSort.java \
java/util/ConcurrentModificationException.java \ java/util/ConcurrentModificationException.java \
......
...@@ -83,7 +83,7 @@ endif ...@@ -83,7 +83,7 @@ endif
# #
# Find platform specific native code # 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 # Include rules
......
# #
# 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. # DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
# #
# This code is free software; you can redistribute it and/or modify it # This code is free software; you can redistribute it and/or modify it
...@@ -34,8 +34,8 @@ solaris_i586_5.10,\ ...@@ -34,8 +34,8 @@ solaris_i586_5.10,\
solaris_x64_5.10,\ solaris_x64_5.10,\
linux_i586_2.6,\ linux_i586_2.6,\
linux_x64_2.6,\ linux_x64_2.6,\
windows_i586,\ windows_i586_5.0,\
windows_x64 windows_x64_5.2
# The different build flavors we want # The different build flavors we want
jprt.build.flavors=product,fastdebug jprt.build.flavors=product,fastdebug
...@@ -51,21 +51,37 @@ jprt.run.flavor.c2.option=-server ...@@ -51,21 +51,37 @@ jprt.run.flavor.c2.option=-server
jprt.solaris_sparcv9.build.platform.match32=solaris_sparc_5.10 jprt.solaris_sparcv9.build.platform.match32=solaris_sparc_5.10
jprt.solaris_x64.build.platform.match32=solaris_i586_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.test.targets=*-*-*-jvm98
jprt.regression.test.targets= \
*-product-*-java/lang, \
*-product-*-java/security, \
*-product-*-java/text, \
*-product-*-java/util
#jprt.regression.test.targets= \ # Test targets in test/Makefile (some longer running tests only test c2)
# *-product-*-java/awt, \ jprt.make.rule.test.targets= \
# *-product-*-java/beans, \ *-product-*-jdk_beans1, \
# *-product-*-java/io, \ *-product-*-jdk_beans2, \
# *-product-*-java/net, \ *-product-*-jdk_beans3, \
# *-product-*-java/nio, \ *-product-*-jdk_io, \
# *-product-*-java/rmi, \ *-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 # Directories needed to build
jprt.bundle.exclude.src.dirs=build jprt.bundle.exclude.src.dirs=build
......
...@@ -53,7 +53,6 @@ SUNWprivate_1.1 { ...@@ -53,7 +53,6 @@ SUNWprivate_1.1 {
Java_sun_awt_image_GifImageDecoder_initIDs; Java_sun_awt_image_GifImageDecoder_initIDs;
Java_sun_awt_image_GifImageDecoder_parseImage; Java_sun_awt_image_GifImageDecoder_parseImage;
Java_sun_awt_image_ImageRepresentation_initIDs; Java_sun_awt_image_ImageRepresentation_initIDs;
Java_sun_awt_image_ImageRepresentation_setBytePixels;
Java_sun_awt_image_ImageRepresentation_setDiffICM; Java_sun_awt_image_ImageRepresentation_setDiffICM;
Java_sun_awt_image_ImageRepresentation_setICMpixels; Java_sun_awt_image_ImageRepresentation_setICMpixels;
Java_sun_awt_image_ImagingLib_convolveBI; Java_sun_awt_image_ImagingLib_convolveBI;
......
...@@ -55,7 +55,6 @@ SUNWprivate_1.1 { ...@@ -55,7 +55,6 @@ SUNWprivate_1.1 {
Java_sun_awt_image_GifImageDecoder_parseImage; Java_sun_awt_image_GifImageDecoder_parseImage;
Java_sun_awt_image_Image_initIDs; Java_sun_awt_image_Image_initIDs;
Java_sun_awt_image_ImageRepresentation_initIDs; Java_sun_awt_image_ImageRepresentation_initIDs;
Java_sun_awt_image_ImageRepresentation_setBytePixels;
Java_sun_awt_image_ImageRepresentation_setDiffICM; Java_sun_awt_image_ImageRepresentation_setDiffICM;
Java_sun_awt_image_ImageRepresentation_setICMpixels; Java_sun_awt_image_ImageRepresentation_setICMpixels;
Java_sun_awt_image_ImagingLib_convolveBI; Java_sun_awt_image_ImagingLib_convolveBI;
......
...@@ -45,8 +45,14 @@ FILES_java = \ ...@@ -45,8 +45,14 @@ FILES_java = \
sun/net/dns/ResolverConfiguration.java \ sun/net/dns/ResolverConfiguration.java \
sun/net/dns/ResolverConfigurationImpl.java \ sun/net/dns/ResolverConfigurationImpl.java \
sun/net/ftp/FtpClient.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/FtpLoginException.java \
sun/net/ftp/FtpProtocolException.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/DefaultProxySelector.java \
sun/net/spi/nameservice/NameServiceDescriptor.java \ sun/net/spi/nameservice/NameServiceDescriptor.java \
sun/net/spi/nameservice/NameService.java \ sun/net/spi/nameservice/NameService.java \
...@@ -79,7 +85,6 @@ FILES_java = \ ...@@ -79,7 +85,6 @@ FILES_java = \
sun/net/www/http/Hurryable.java \ sun/net/www/http/Hurryable.java \
sun/net/www/protocol/http/Handler.java \ sun/net/www/protocol/http/Handler.java \
sun/net/www/protocol/http/HttpURLConnection.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/HttpAuthenticator.java \
sun/net/www/protocol/http/AuthenticationHeader.java \ sun/net/www/protocol/http/AuthenticationHeader.java \
sun/net/www/protocol/http/AuthenticationInfo.java \ sun/net/www/protocol/http/AuthenticationInfo.java \
...@@ -89,11 +94,13 @@ FILES_java = \ ...@@ -89,11 +94,13 @@ FILES_java = \
sun/net/www/protocol/http/AuthScheme.java \ sun/net/www/protocol/http/AuthScheme.java \
sun/net/www/protocol/http/BasicAuthentication.java \ sun/net/www/protocol/http/BasicAuthentication.java \
sun/net/www/protocol/http/DigestAuthentication.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/NTLMAuthenticationProxy.java \
sun/net/www/protocol/http/NegotiateAuthentication.java \ sun/net/www/protocol/http/NegotiateAuthentication.java \
sun/net/www/protocol/http/NegotiatorImpl.java \ sun/net/www/protocol/http/Negotiator.java \
sun/net/www/protocol/http/NegotiateCallbackHandler.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/AbstractDelegateHttpsURLConnection.java \
sun/net/www/protocol/https/HttpsClient.java \ sun/net/www/protocol/https/HttpsClient.java \
sun/net/www/protocol/https/DefaultHostnameVerifier.java \ sun/net/www/protocol/https/DefaultHostnameVerifier.java \
...@@ -128,7 +135,7 @@ FILES_java = \ ...@@ -128,7 +135,7 @@ FILES_java = \
sun/net/idn/StringPrep.java sun/net/idn/StringPrep.java
ifeq ($(PLATFORM), windows) ifeq ($(PLATFORM), windows)
FILES_java += sun/net/www/protocol/http/NTLMAuthSequence.java FILES_java += sun/net/www/protocol/http/ntlm/NTLMAuthSequence.java
endif endif
ifeq ($(PLATFORM), solaris) ifeq ($(PLATFORM), solaris)
......
...@@ -39,6 +39,7 @@ AUTO_FILES_JAVA_DIRS = \ ...@@ -39,6 +39,7 @@ AUTO_FILES_JAVA_DIRS = \
sun/security/provider \ sun/security/provider \
sun/security/rsa \ sun/security/rsa \
sun/security/ssl \ sun/security/ssl \
sun/security/ssl/krb5 \
sun/security/timestamp \ sun/security/timestamp \
sun/security/validator \ sun/security/validator \
sun/security/x509 \ sun/security/x509 \
......
...@@ -62,6 +62,8 @@ import javax.imageio.event.IIOReadWarningListener; ...@@ -62,6 +62,8 @@ import javax.imageio.event.IIOReadWarningListener;
import java.io.*; import java.io.*;
import java.nio.*; import java.nio.*;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Iterator; import java.util.Iterator;
import java.util.StringTokenizer; import java.util.StringTokenizer;
...@@ -502,12 +504,18 @@ public class BMPImageReader extends ImageReader implements BMPConstants { ...@@ -502,12 +504,18 @@ public class BMPImageReader extends ImageReader implements BMPConstants {
iis.reset(); iis.reset();
try { try {
if (metadata.colorSpace == PROFILE_LINKED) if (metadata.colorSpace == PROFILE_LINKED &&
isLinkedProfileAllowed() &&
!isUncOrDevicePath(profile))
{
String path = new String(profile, "windows-1252");
colorSpace = colorSpace =
new ICC_ColorSpace(ICC_Profile.getInstance(new String(profile))); new ICC_ColorSpace(ICC_Profile.getInstance(path));
else } else {
colorSpace = colorSpace =
new ICC_ColorSpace(ICC_Profile.getInstance(profile)); new ICC_ColorSpace(ICC_Profile.getInstance(profile));
}
} catch (Exception e) { } catch (Exception e) {
colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB); colorSpace = ColorSpace.getInstance(ColorSpace.CS_sRGB);
} }
...@@ -1745,4 +1753,69 @@ public class BMPImageReader extends ImageReader implements BMPConstants { ...@@ -1745,4 +1753,69 @@ public class BMPImageReader extends ImageReader implements BMPConstants {
public void sequenceStarted(ImageReader src, int minIndex) {} public void sequenceStarted(ImageReader src, int minIndex) {}
public void readAborted(ImageReader src) {} 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;
}
}
} }
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
package com.sun.java.swing.plaf.motif; package com.sun.java.swing.plaf.motif;
import sun.awt.AppContext;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.*; import javax.swing.border.*;
import javax.swing.plaf.basic.*; import javax.swing.plaf.basic.*;
...@@ -46,16 +48,23 @@ import javax.swing.plaf.*; ...@@ -46,16 +48,23 @@ import javax.swing.plaf.*;
*/ */
public class MotifButtonUI extends BasicButtonUI { public class MotifButtonUI extends BasicButtonUI {
private final static MotifButtonUI motifButtonUI = new MotifButtonUI();
protected Color selectColor; protected Color selectColor;
private boolean defaults_initialized = false; private boolean defaults_initialized = false;
private static final Object MOTIF_BUTTON_UI_KEY = new Object();
// ******************************** // ********************************
// Create PLAF // 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; return motifButtonUI;
} }
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
package com.sun.java.swing.plaf.motif; package com.sun.java.swing.plaf.motif;
import sun.awt.AppContext;
import javax.swing.*; import javax.swing.*;
import javax.swing.plaf.*; import javax.swing.plaf.*;
...@@ -45,7 +47,7 @@ import java.awt.*; ...@@ -45,7 +47,7 @@ import java.awt.*;
*/ */
public class MotifCheckBoxUI extends MotifRadioButtonUI { 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" + "."; private final static String propertyPrefix = "CheckBox" + ".";
...@@ -55,7 +57,14 @@ public class MotifCheckBoxUI extends MotifRadioButtonUI { ...@@ -55,7 +57,14 @@ public class MotifCheckBoxUI extends MotifRadioButtonUI {
// ******************************** // ********************************
// Create PLAF // 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; return motifCheckBoxUI;
} }
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
package com.sun.java.swing.plaf.motif; package com.sun.java.swing.plaf.motif;
import sun.awt.AppContext;
import javax.swing.*; import javax.swing.*;
import javax.swing.plaf.basic.BasicLabelUI; import javax.swing.plaf.basic.BasicLabelUI;
import javax.swing.plaf.ComponentUI; import javax.swing.plaf.ComponentUI;
...@@ -44,9 +46,16 @@ import javax.swing.plaf.ComponentUI; ...@@ -44,9 +46,16 @@ import javax.swing.plaf.ComponentUI;
*/ */
public class MotifLabelUI extends BasicLabelUI 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) { 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;
} }
} }
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
package com.sun.java.swing.plaf.motif; package com.sun.java.swing.plaf.motif;
import sun.awt.AppContext;
import javax.swing.*; import javax.swing.*;
import javax.swing.border.*; import javax.swing.border.*;
import javax.swing.plaf.basic.BasicRadioButtonUI; import javax.swing.plaf.basic.BasicRadioButtonUI;
...@@ -47,7 +49,7 @@ import java.awt.*; ...@@ -47,7 +49,7 @@ import java.awt.*;
*/ */
public class MotifRadioButtonUI extends BasicRadioButtonUI { 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; protected Color focusColor;
...@@ -57,6 +59,13 @@ public class MotifRadioButtonUI extends BasicRadioButtonUI { ...@@ -57,6 +59,13 @@ public class MotifRadioButtonUI extends BasicRadioButtonUI {
// Create PLAF // Create PLAF
// ******************************** // ********************************
public static ComponentUI createUI(JComponent c) { 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; return motifRadioButtonUI;
} }
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
package com.sun.java.swing.plaf.motif; package com.sun.java.swing.plaf.motif;
import sun.awt.AppContext;
import java.awt.*; import java.awt.*;
import java.awt.event.*; import java.awt.event.*;
...@@ -48,7 +50,7 @@ import javax.swing.plaf.basic.*; ...@@ -48,7 +50,7 @@ import javax.swing.plaf.basic.*;
*/ */
public class MotifToggleButtonUI extends BasicToggleButtonUI 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; protected Color selectColor;
...@@ -58,6 +60,13 @@ public class MotifToggleButtonUI extends BasicToggleButtonUI ...@@ -58,6 +60,13 @@ public class MotifToggleButtonUI extends BasicToggleButtonUI
// Create PLAF // Create PLAF
// ******************************** // ********************************
public static ComponentUI createUI(JComponent b) { 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; return motifToggleButtonUI;
} }
......
...@@ -35,6 +35,7 @@ import java.awt.*; ...@@ -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.*;
import static com.sun.java.swing.plaf.windows.TMSchema.Part.*; import static com.sun.java.swing.plaf.windows.TMSchema.Part.*;
import static com.sun.java.swing.plaf.windows.XPStyle.Skin; 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; ...@@ -52,8 +53,6 @@ import static com.sun.java.swing.plaf.windows.XPStyle.Skin;
*/ */
public class WindowsButtonUI extends BasicButtonUI public class WindowsButtonUI extends BasicButtonUI
{ {
private final static WindowsButtonUI windowsButtonUI = new WindowsButtonUI();
protected int dashedRectGapX; protected int dashedRectGapX;
protected int dashedRectGapY; protected int dashedRectGapY;
protected int dashedRectGapWidth; protected int dashedRectGapWidth;
...@@ -63,11 +62,19 @@ public class WindowsButtonUI extends BasicButtonUI ...@@ -63,11 +62,19 @@ public class WindowsButtonUI extends BasicButtonUI
private boolean defaults_initialized = false; private boolean defaults_initialized = false;
private static final Object WINDOWS_BUTTON_UI_KEY = new Object();
// ******************************** // ********************************
// Create PLAF // 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; return windowsButtonUI;
} }
...@@ -151,7 +158,7 @@ public class WindowsButtonUI extends BasicButtonUI ...@@ -151,7 +158,7 @@ public class WindowsButtonUI extends BasicButtonUI
* allocating them in each paint call substantially reduced the time * allocating them in each paint call substantially reduced the time
* it took paint to run. Obviously, this method can't be re-entered. * 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) { public void paint(Graphics g, JComponent c) {
if (XPStyle.getXP() != null) { if (XPStyle.getXP() != null) {
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
package com.sun.java.swing.plaf.windows; package com.sun.java.swing.plaf.windows;
import sun.awt.AppContext;
import javax.swing.plaf.basic.*; import javax.swing.plaf.basic.*;
import javax.swing.*; import javax.swing.*;
import javax.swing.plaf.*; import javax.swing.plaf.*;
...@@ -49,7 +51,7 @@ public class WindowsCheckBoxUI extends WindowsRadioButtonUI ...@@ -49,7 +51,7 @@ public class WindowsCheckBoxUI extends WindowsRadioButtonUI
// of BasicCheckBoxUI because we want to pick up all the // of BasicCheckBoxUI because we want to pick up all the
// painting changes made in MetalRadioButtonUI. // 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" + "."; private final static String propertyPrefix = "CheckBox" + ".";
...@@ -59,6 +61,13 @@ public class WindowsCheckBoxUI extends WindowsRadioButtonUI ...@@ -59,6 +61,13 @@ public class WindowsCheckBoxUI extends WindowsRadioButtonUI
// Create PLAF // Create PLAF
// ******************************** // ********************************
public static ComponentUI createUI(JComponent c) { 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; return windowsCheckBoxUI;
} }
......
...@@ -26,6 +26,8 @@ ...@@ -26,6 +26,8 @@
package com.sun.java.swing.plaf.windows; package com.sun.java.swing.plaf.windows;
import sun.swing.SwingUtilities2; import sun.swing.SwingUtilities2;
import sun.awt.AppContext;
import java.awt.Color; import java.awt.Color;
import java.awt.Graphics; import java.awt.Graphics;
...@@ -51,12 +53,19 @@ import javax.swing.plaf.basic.BasicLabelUI; ...@@ -51,12 +53,19 @@ import javax.swing.plaf.basic.BasicLabelUI;
*/ */
public class WindowsLabelUI extends 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 // 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; return windowsLabelUI;
} }
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
package com.sun.java.swing.plaf.windows; package com.sun.java.swing.plaf.windows;
import sun.awt.AppContext;
import javax.swing.plaf.basic.*; import javax.swing.plaf.basic.*;
import javax.swing.*; import javax.swing.*;
import javax.swing.plaf.*; import javax.swing.plaf.*;
...@@ -44,7 +46,7 @@ import java.awt.*; ...@@ -44,7 +46,7 @@ import java.awt.*;
*/ */
public class WindowsRadioButtonUI extends BasicRadioButtonUI 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 dashedRectGapX;
protected int dashedRectGapY; protected int dashedRectGapY;
...@@ -59,6 +61,13 @@ public class WindowsRadioButtonUI extends BasicRadioButtonUI ...@@ -59,6 +61,13 @@ public class WindowsRadioButtonUI extends BasicRadioButtonUI
// Create PLAF // Create PLAF
// ******************************** // ********************************
public static ComponentUI createUI(JComponent c) { 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; return windowsRadioButtonUI;
} }
......
...@@ -25,6 +25,8 @@ ...@@ -25,6 +25,8 @@
package com.sun.java.swing.plaf.windows; package com.sun.java.swing.plaf.windows;
import sun.awt.AppContext;
import javax.swing.plaf.basic.*; import javax.swing.plaf.basic.*;
import javax.swing.border.*; import javax.swing.border.*;
import javax.swing.plaf.*; import javax.swing.plaf.*;
...@@ -49,18 +51,25 @@ import java.beans.PropertyChangeEvent; ...@@ -49,18 +51,25 @@ import java.beans.PropertyChangeEvent;
*/ */
public class WindowsToggleButtonUI extends BasicToggleButtonUI public class WindowsToggleButtonUI extends BasicToggleButtonUI
{ {
protected static int dashedRectGapX; protected int dashedRectGapX;
protected static int dashedRectGapY; protected int dashedRectGapY;
protected static int dashedRectGapWidth; protected int dashedRectGapWidth;
protected static int dashedRectGapHeight; protected int dashedRectGapHeight;
protected Color focusColor; 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; private boolean defaults_initialized = false;
public static ComponentUI createUI(JComponent b) { 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; return windowsToggleButtonUI;
} }
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -176,18 +176,6 @@ public class JmxProperties { ...@@ -176,18 +176,6 @@ public class JmxProperties {
public static final String RELATION_LOGGER_NAME = public static final String RELATION_LOGGER_NAME =
"javax.management.relation"; "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. * Logger for Relation Service.
*/ */
......
...@@ -69,9 +69,9 @@ public class ServiceName { ...@@ -69,9 +69,9 @@ public class ServiceName {
/** /**
* The version of the JMX specification implemented by this product. * The version of the JMX specification implemented by this product.
* <BR> * <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. * The vendor of the JMX specification implemented by this product.
......
/*
* 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");
}
/*
* 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");
}
/*
* 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);
}
}
}
/*
* 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");
}
/*
* 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");
}
/*
* 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");
}
/*
* 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");
}
/*
* 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;
}
}
/*
* 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.");
}
}
/*
* 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);
}
}
/*
* 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);
}
}
...@@ -31,15 +31,13 @@ import java.lang.reflect.Type; ...@@ -31,15 +31,13 @@ import java.lang.reflect.Type;
import javax.management.Descriptor; import javax.management.Descriptor;
import javax.management.MBeanException; import javax.management.MBeanException;
import javax.management.openmbean.MXBeanMapping;
import javax.management.openmbean.MXBeanMappingFactory;
import javax.management.openmbean.OpenDataException; import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType; import javax.management.openmbean.OpenType;
final class ConvertingMethod { final class ConvertingMethod {
static ConvertingMethod from(Method m, MXBeanMappingFactory mappingFactory) { static ConvertingMethod from(Method m) {
try { try {
return new ConvertingMethod(m, mappingFactory); return new ConvertingMethod(m);
} catch (OpenDataException ode) { } catch (OpenDataException ode) {
final String msg = "Method " + m.getDeclaringClass().getName() + final String msg = "Method " + m.getDeclaringClass().getName() +
"." + m.getName() + " has parameter or return type that " + "." + m.getName() + " has parameter or return type that " +
...@@ -53,7 +51,7 @@ final class ConvertingMethod { ...@@ -53,7 +51,7 @@ final class ConvertingMethod {
} }
Descriptor getDescriptor() { Descriptor getDescriptor() {
return Introspector.descriptorForElement(method, false); return Introspector.descriptorForElement(method);
} }
Type getGenericReturnType() { Type getGenericReturnType() {
...@@ -206,9 +204,9 @@ final class ConvertingMethod { ...@@ -206,9 +204,9 @@ final class ConvertingMethod {
return method.getDeclaringClass() + "." + method.getName(); return method.getDeclaringClass() + "." + method.getName();
} }
private ConvertingMethod(Method m, MXBeanMappingFactory mappingFactory) private ConvertingMethod(Method m) throws OpenDataException {
throws OpenDataException {
this.method = m; this.method = m;
MXBeanMappingFactory mappingFactory = MXBeanMappingFactory.DEFAULT;
returnMapping = returnMapping =
mappingFactory.mappingForType(m.getGenericReturnType(), mappingFactory); mappingFactory.mappingForType(m.getGenericReturnType(), mappingFactory);
Type[] params = m.getGenericParameterTypes(); Type[] params = m.getGenericParameterTypes();
......
...@@ -28,8 +28,6 @@ package com.sun.jmx.mbeanserver; ...@@ -28,8 +28,6 @@ package com.sun.jmx.mbeanserver;
import static com.sun.jmx.mbeanserver.Util.*; import static com.sun.jmx.mbeanserver.Util.*;
import static com.sun.jmx.mbeanserver.MXBeanIntrospector.typeName; import static com.sun.jmx.mbeanserver.MXBeanIntrospector.typeName;
import javax.management.openmbean.MXBeanMappingClass;
import static javax.management.openmbean.SimpleType.*; import static javax.management.openmbean.SimpleType.*;
import com.sun.jmx.remote.util.EnvHelp; import com.sun.jmx.remote.util.EnvHelp;
...@@ -69,8 +67,6 @@ import javax.management.openmbean.CompositeDataInvocationHandler; ...@@ -69,8 +67,6 @@ import javax.management.openmbean.CompositeDataInvocationHandler;
import javax.management.openmbean.CompositeDataSupport; import javax.management.openmbean.CompositeDataSupport;
import javax.management.openmbean.CompositeDataView; import javax.management.openmbean.CompositeDataView;
import javax.management.openmbean.CompositeType; import javax.management.openmbean.CompositeType;
import javax.management.openmbean.MXBeanMapping;
import javax.management.openmbean.MXBeanMappingFactory;
import javax.management.openmbean.OpenDataException; import javax.management.openmbean.OpenDataException;
import javax.management.openmbean.OpenType; import javax.management.openmbean.OpenType;
import javax.management.openmbean.SimpleType; import javax.management.openmbean.SimpleType;
...@@ -165,34 +161,29 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { ...@@ -165,34 +161,29 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
private static final class Mappings private static final class Mappings
extends WeakHashMap<Type, WeakReference<MXBeanMapping>> {} extends WeakHashMap<Type, WeakReference<MXBeanMapping>> {}
private static final Map<MXBeanMappingFactory, Mappings> factoryMappings = private static final Mappings mappings = new Mappings();
new WeakHashMap<MXBeanMappingFactory, 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( private static synchronized MXBeanMapping getMapping(Type type) {
Type type, MXBeanMappingFactory factory) {
Mappings mappings = factoryMappings.get(factory);
if (mappings == null) {
mappings = new Mappings();
factoryMappings.put(factory, mappings);
}
WeakReference<MXBeanMapping> wr = mappings.get(type); WeakReference<MXBeanMapping> wr = mappings.get(type);
return (wr == null) ? null : wr.get(); return (wr == null) ? null : wr.get();
} }
private static synchronized void putMapping( private static synchronized void putMapping(Type type, MXBeanMapping mapping) {
Type type, MXBeanMapping mapping, MXBeanMappingFactory factory) {
Mappings mappings = factoryMappings.get(factory);
if (mappings == null) {
mappings = new Mappings();
factoryMappings.put(factory, mappings);
}
WeakReference<MXBeanMapping> wr = WeakReference<MXBeanMapping> wr =
new WeakReference<MXBeanMapping>(mapping); new WeakReference<MXBeanMapping>(mapping);
mappings.put(type, wr); mappings.put(type, wr);
} }
private static synchronized void putPermanentMapping(
Type type, MXBeanMapping mapping) {
putMapping(type, mapping);
permanentMappings.add(mapping);
}
static { static {
/* Set up the mappings for Java types that map to SimpleType. */ /* Set up the mappings for Java types that map to SimpleType. */
...@@ -213,7 +204,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { ...@@ -213,7 +204,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
throw new Error(e); throw new Error(e);
} }
final MXBeanMapping mapping = new IdentityMapping(c, t); final MXBeanMapping mapping = new IdentityMapping(c, t);
permanentMappings.put(c, mapping); putPermanentMapping(c, mapping);
if (c.getName().startsWith("java.lang.")) { if (c.getName().startsWith("java.lang.")) {
try { try {
...@@ -221,7 +212,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { ...@@ -221,7 +212,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
final Class<?> primitiveType = (Class<?>) typeField.get(null); final Class<?> primitiveType = (Class<?>) typeField.get(null);
final MXBeanMapping primitiveMapping = final MXBeanMapping primitiveMapping =
new IdentityMapping(primitiveType, t); new IdentityMapping(primitiveType, t);
permanentMappings.put(primitiveType, primitiveMapping); putPermanentMapping(primitiveType, primitiveMapping);
if (primitiveType != void.class) { if (primitiveType != void.class) {
final Class<?> primitiveArrayType = final Class<?> primitiveArrayType =
Array.newInstance(primitiveType, 0).getClass(); Array.newInstance(primitiveType, 0).getClass();
...@@ -230,8 +221,8 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { ...@@ -230,8 +221,8 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
final MXBeanMapping primitiveArrayMapping = final MXBeanMapping primitiveArrayMapping =
new IdentityMapping(primitiveArrayType, new IdentityMapping(primitiveArrayType,
primitiveArrayOpenType); primitiveArrayOpenType);
permanentMappings.put(primitiveArrayType, putPermanentMapping(primitiveArrayType,
primitiveArrayMapping); primitiveArrayMapping);
} }
} catch (NoSuchFieldException e) { } catch (NoSuchFieldException e) {
// OK: must not be a primitive wrapper // OK: must not be a primitive wrapper
...@@ -255,7 +246,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { ...@@ -255,7 +246,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
MXBeanMapping mapping; MXBeanMapping mapping;
mapping = getMapping(objType, null); mapping = getMapping(objType);
if (mapping != null) if (mapping != null)
return mapping; return mapping;
...@@ -268,7 +259,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { ...@@ -268,7 +259,7 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
inProgress.remove(objType); inProgress.remove(objType);
} }
putMapping(objType, mapping, factory); putMapping(objType, mapping);
return mapping; return mapping;
} }
...@@ -278,14 +269,6 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { ...@@ -278,14 +269,6 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
/* It's not yet worth formalizing these tests by having for example /* It's not yet worth formalizing these tests by having for example
an array of factory classes, each of which says whether it an array of factory classes, each of which says whether it
recognizes the Type (Chain of Responsibility pattern). */ 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) { if (objType instanceof GenericArrayType) {
Type componentType = Type componentType =
((GenericArrayType) objType).getGenericComponentType(); ((GenericArrayType) objType).getGenericComponentType();
...@@ -313,51 +296,6 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory { ...@@ -313,51 +296,6 @@ public class DefaultMXBeanMappingFactory extends MXBeanMappingFactory {
throw new OpenDataException("Cannot map type: " + objType); 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 private static <T extends Enum<T>> MXBeanMapping
makeEnumMapping(Class<?> enumClass, Class<T> fake) { makeEnumMapping(Class<?> enumClass, Class<T> fake) {
return new EnumMapping<T>(Util.<Class<T>>cast(enumClass)); return new EnumMapping<T>(Util.<Class<T>>cast(enumClass));
......
/* /*
* 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. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -25,7 +25,7 @@ ...@@ -25,7 +25,7 @@
package com.sun.jmx.mbeanserver; package com.sun.jmx.mbeanserver;
import javax.management.DynamicWrapperMBean; import javax.management.DynamicMBean;
import javax.management.MBeanServer; import javax.management.MBeanServer;
import javax.management.ObjectName; import javax.management.ObjectName;
...@@ -35,7 +35,17 @@ import javax.management.ObjectName; ...@@ -35,7 +35,17 @@ import javax.management.ObjectName;
* *
* @since 1.6 * @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. * The name of this MBean's class, as used by permission checks.
* This is typically equal to getResource().getClass().getName(). * This is typically equal to getResource().getClass().getName().
......
...@@ -25,14 +25,9 @@ ...@@ -25,14 +25,9 @@
package com.sun.jmx.mbeanserver; 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.annotation.Annotation;
import java.lang.reflect.AnnotatedElement; import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor; import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.lang.reflect.Proxy; import java.lang.reflect.Proxy;
...@@ -40,39 +35,21 @@ import java.lang.reflect.UndeclaredThrowableException; ...@@ -40,39 +35,21 @@ import java.lang.reflect.UndeclaredThrowableException;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
import java.util.logging.Level;
import javax.management.AttributeNotFoundException;
import javax.management.Description;
import javax.management.Descriptor; import javax.management.Descriptor;
import javax.management.DescriptorFields;
import javax.management.DescriptorKey; import javax.management.DescriptorKey;
import javax.management.DynamicMBean; import javax.management.DynamicMBean;
import javax.management.ImmutableDescriptor; import javax.management.ImmutableDescriptor;
import javax.management.MBean;
import javax.management.MBeanInfo; import javax.management.MBeanInfo;
import javax.management.MXBean;
import javax.management.NotCompliantMBeanException; 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 com.sun.jmx.remote.util.EnvHelp;
import java.beans.BeanInfo; import java.beans.BeanInfo;
import java.beans.PropertyDescriptor; import java.beans.PropertyDescriptor;
import java.lang.reflect.Array; import java.lang.reflect.Array;
import java.lang.reflect.InvocationTargetException; 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.AttributeNotFoundException;
import javax.management.JMX;
import javax.management.ObjectName;
import javax.management.ObjectNameTemplate;
import javax.management.openmbean.CompositeData; import javax.management.openmbean.CompositeData;
import javax.management.openmbean.MXBeanMappingFactory;
/** /**
* This class contains the methods for performing all the tests needed to verify * This class contains the methods for performing all the tests needed to verify
...@@ -82,13 +59,7 @@ import javax.management.openmbean.MXBeanMappingFactory; ...@@ -82,13 +59,7 @@ import javax.management.openmbean.MXBeanMappingFactory;
*/ */
public class Introspector { 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 * PRIVATE CONSTRUCTORS
...@@ -164,10 +135,6 @@ public class Introspector { ...@@ -164,10 +135,6 @@ public class Introspector {
public static void checkCompliance(Class<?> mbeanClass) public static void checkCompliance(Class<?> mbeanClass)
throws NotCompliantMBeanException { throws NotCompliantMBeanException {
// Check that @Resource is used correctly (if it used).
MBeanInjector.validate(mbeanClass);
// Is DynamicMBean? // Is DynamicMBean?
// //
if (DynamicMBean.class.isAssignableFrom(mbeanClass)) if (DynamicMBean.class.isAssignableFrom(mbeanClass))
...@@ -190,36 +157,16 @@ public class Introspector { ...@@ -190,36 +157,16 @@ public class Introspector {
} catch (NotCompliantMBeanException e) { } catch (NotCompliantMBeanException e) {
mxbeanException = 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 = final String msg =
"MBean class " + mbeanClass.getName() + " does not implement " + "MBean class " + mbeanClass.getName() + " does not implement " +
"DynamicMBean; does not follow the Standard MBean conventions (" + "DynamicMBean, and neither follows the Standard MBean conventions (" +
mbeanException.toString() + "); does not follow the MXBean conventions (" + mbeanException.toString() + ") nor the MXBean conventions (" +
mxbeanException.toString() + "); and does not have or inherit the @" + mxbeanException.toString() + ")";
MBean.class.getSimpleName() + " or @" + MXBean.class.getSimpleName() +
" annotation";
throw new NotCompliantMBeanException(msg); 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) public static <T> DynamicMBean makeDynamicMBean(T mbean)
throws NotCompliantMBeanException { throws NotCompliantMBeanException {
if (mbean == null)
throw new NotCompliantMBeanException("Null MBean object");
if (mbean instanceof DynamicMBean) if (mbean instanceof DynamicMBean)
return (DynamicMBean) mbean; return (DynamicMBean) mbean;
final Class<?> mbeanClass = mbean.getClass(); final Class<?> mbeanClass = mbean.getClass();
...@@ -240,18 +187,8 @@ public class Introspector { ...@@ -240,18 +187,8 @@ public class Introspector {
// to be an MBean or an MXBean. We will call checkCompliance() // to be an MBean or an MXBean. We will call checkCompliance()
// to generate the appropriate exception. // to generate the appropriate exception.
} }
if (c != null) { if (c != null)
MXBeanMappingFactory factory; return new MXBeanSupport(mbean, c);
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);
}
checkCompliance(mbeanClass); checkCompliance(mbeanClass);
throw new NotCompliantMBeanException("Not compliant"); // not reached throw new NotCompliantMBeanException("Not compliant"); // not reached
} }
...@@ -280,10 +217,9 @@ public class Introspector { ...@@ -280,10 +217,9 @@ public class Introspector {
return testCompliance(baseClass, null); return testCompliance(baseClass, null);
} }
public static void testComplianceMXBeanInterface(Class<?> interfaceClass, public static void testComplianceMXBeanInterface(Class<?> interfaceClass)
MXBeanMappingFactory factory)
throws NotCompliantMBeanException { throws NotCompliantMBeanException {
MXBeanIntrospector.getInstance(factory).getAnalyzer(interfaceClass); MXBeanIntrospector.getInstance().getAnalyzer(interfaceClass);
} }
/** /**
...@@ -352,8 +288,6 @@ public class Introspector { ...@@ -352,8 +288,6 @@ public class Introspector {
*/ */
public static <T> Class<? super T> getStandardMBeanInterface(Class<T> baseClass) public static <T> Class<? super T> getStandardMBeanInterface(Class<T> baseClass)
throws NotCompliantMBeanException { throws NotCompliantMBeanException {
if (baseClass.isAnnotationPresent(MBean.class))
return baseClass;
Class<? super T> current = baseClass; Class<? super T> current = baseClass;
Class<? super T> mbeanInterface = null; Class<? super T> mbeanInterface = null;
while (current != null) { while (current != null) {
...@@ -384,8 +318,6 @@ public class Introspector { ...@@ -384,8 +318,6 @@ public class Introspector {
*/ */
public static <T> Class<? super T> getMXBeanInterface(Class<T> baseClass) public static <T> Class<? super T> getMXBeanInterface(Class<T> baseClass)
throws NotCompliantMBeanException { throws NotCompliantMBeanException {
if (hasMXBeanAnnotation(baseClass))
return baseClass;
try { try {
return MXBeanSupport.findMXBeanInterface(baseClass); return MXBeanSupport.findMXBeanInterface(baseClass);
} catch (Exception e) { } catch (Exception e) {
...@@ -393,61 +325,12 @@ public class Introspector { ...@@ -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 * 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 * Try to find the MBean interface corresponding to the class aName
...@@ -469,77 +352,11 @@ public class Introspector { ...@@ -469,77 +352,11 @@ public class Introspector {
return null; return null;
} }
public static String descriptionForElement(AnnotatedElement elmt) { public static Descriptor descriptorForElement(final 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) {
if (elmt == null) if (elmt == null)
return ImmutableDescriptor.EMPTY_DESCRIPTOR; return ImmutableDescriptor.EMPTY_DESCRIPTOR;
final Annotation[] annots = elmt.getAnnotations(); final Annotation[] annots = elmt.getAnnotations();
Descriptor descr = descriptorForAnnotations(annots); return 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});
} }
public static Descriptor descriptorForAnnotations(Annotation[] annots) { public static Descriptor descriptorForAnnotations(Annotation[] annots) {
...@@ -547,9 +364,36 @@ public class Introspector { ...@@ -547,9 +364,36 @@ public class Introspector {
return ImmutableDescriptor.EMPTY_DESCRIPTOR; return ImmutableDescriptor.EMPTY_DESCRIPTOR;
Map<String, Object> descriptorMap = new HashMap<String, Object>(); Map<String, Object> descriptorMap = new HashMap<String, Object>();
for (Annotation a : annots) { for (Annotation a : annots) {
if (a instanceof DescriptorFields) Class<? extends Annotation> c = a.annotationType();
addDescriptorFieldsToMap(descriptorMap, (DescriptorFields) a); Method[] elements = c.getMethods();
addAnnotationFieldsToMap(descriptorMap, a); 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()) if (descriptorMap.isEmpty())
...@@ -558,76 +402,6 @@ public class Introspector { ...@@ -558,76 +402,6 @@ public class Introspector {
return new ImmutableDescriptor(descriptorMap); 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. * Throws a NotCompliantMBeanException or a SecurityException.
* @param notCompliant the class which was under examination * @param notCompliant the class which was under examination
......
...@@ -25,14 +25,14 @@ ...@@ -25,14 +25,14 @@
package com.sun.jmx.mbeanserver; 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 static com.sun.jmx.defaults.JmxProperties.MBEANSERVER_LOGGER;
import com.sun.jmx.interceptor.NamespaceDispatchInterceptor;
import java.io.ObjectInputStream; import java.io.ObjectInputStream;
import java.security.AccessController; import java.security.AccessController;
import java.security.Permission; import java.security.Permission;
import java.security.PrivilegedExceptionAction; import java.security.PrivilegedExceptionAction;
import java.util.Iterator;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.logging.Level; import java.util.logging.Level;
...@@ -108,8 +108,6 @@ public final class JmxMBeanServer ...@@ -108,8 +108,6 @@ public final class JmxMBeanServer
/** The MBeanServerDelegate object representing the MBean Server */ /** The MBeanServerDelegate object representing the MBean Server */
private final MBeanServerDelegate mBeanServerDelegateObject; private final MBeanServerDelegate mBeanServerDelegateObject;
private final String mbeanServerName;
/** /**
* <b>Package:</b> Creates an MBeanServer with the * <b>Package:</b> Creates an MBeanServer with the
* specified default domain name, outer interface, and delegate. * specified default domain name, outer interface, and delegate.
...@@ -241,10 +239,9 @@ public final class JmxMBeanServer ...@@ -241,10 +239,9 @@ public final class JmxMBeanServer
final Repository repository = new Repository(domain); final Repository repository = new Repository(domain);
this.mbsInterceptor = this.mbsInterceptor =
new NamespaceDispatchInterceptor(outer, delegate, instantiator, new DefaultMBeanServerInterceptor(outer, delegate, instantiator,
repository); repository);
this.interceptorsEnabled = interceptors; this.interceptorsEnabled = interceptors;
this.mbeanServerName = Util.getMBeanServerSecurityName(delegate);
initialize(); initialize();
} }
...@@ -940,8 +937,7 @@ public final class JmxMBeanServer ...@@ -940,8 +937,7 @@ public final class JmxMBeanServer
throws ReflectionException, MBeanException { throws ReflectionException, MBeanException {
/* Permission check */ /* Permission check */
checkMBeanPermission(mbeanServerName, className, null, null, checkMBeanPermission(className, null, null, "instantiate");
"instantiate");
return instantiator.instantiate(className); return instantiator.instantiate(className);
} }
...@@ -978,8 +974,7 @@ public final class JmxMBeanServer ...@@ -978,8 +974,7 @@ public final class JmxMBeanServer
InstanceNotFoundException { InstanceNotFoundException {
/* Permission check */ /* Permission check */
checkMBeanPermission(mbeanServerName, className, null, checkMBeanPermission(className, null, null, "instantiate");
null, "instantiate");
ClassLoader myLoader = outerShell.getClass().getClassLoader(); ClassLoader myLoader = outerShell.getClass().getClassLoader();
return instantiator.instantiate(className, loaderName, myLoader); return instantiator.instantiate(className, loaderName, myLoader);
...@@ -1017,8 +1012,7 @@ public final class JmxMBeanServer ...@@ -1017,8 +1012,7 @@ public final class JmxMBeanServer
throws ReflectionException, MBeanException { throws ReflectionException, MBeanException {
/* Permission check */ /* Permission check */
checkMBeanPermission(mbeanServerName, className, null, null, checkMBeanPermission(className, null, null, "instantiate");
"instantiate");
ClassLoader myLoader = outerShell.getClass().getClassLoader(); ClassLoader myLoader = outerShell.getClass().getClassLoader();
return instantiator.instantiate(className, params, signature, return instantiator.instantiate(className, params, signature,
...@@ -1061,8 +1055,7 @@ public final class JmxMBeanServer ...@@ -1061,8 +1055,7 @@ public final class JmxMBeanServer
InstanceNotFoundException { InstanceNotFoundException {
/* Permission check */ /* Permission check */
checkMBeanPermission(mbeanServerName, className, null, checkMBeanPermission(className, null, null, "instantiate");
null, "instantiate");
ClassLoader myLoader = outerShell.getClass().getClassLoader(); ClassLoader myLoader = outerShell.getClass().getClassLoader();
return instantiator.instantiate(className,loaderName,params,signature, return instantiator.instantiate(className,loaderName,params,signature,
...@@ -1333,8 +1326,7 @@ public final class JmxMBeanServer ...@@ -1333,8 +1326,7 @@ public final class JmxMBeanServer
**/ **/
public ClassLoaderRepository getClassLoaderRepository() { public ClassLoaderRepository getClassLoaderRepository() {
/* Permission check */ /* Permission check */
checkMBeanPermission(mbeanServerName, null, null, checkMBeanPermission(null, null, null, "getClassLoaderRepository");
null, "getClassLoaderRepository");
return secureClr; return secureClr;
} }
...@@ -1487,16 +1479,14 @@ public final class JmxMBeanServer ...@@ -1487,16 +1479,14 @@ public final class JmxMBeanServer
// SECURITY CHECKS // SECURITY CHECKS
//---------------- //----------------
private static void checkMBeanPermission(String serverName, private static void checkMBeanPermission(String classname,
String classname,
String member, String member,
ObjectName objectName, ObjectName objectName,
String actions) String actions)
throws SecurityException { throws SecurityException {
SecurityManager sm = System.getSecurityManager(); SecurityManager sm = System.getSecurityManager();
if (sm != null) { if (sm != null) {
Permission perm = new MBeanPermission(serverName, Permission perm = new MBeanPermission(classname,
classname,
member, member,
objectName, objectName,
actions); actions);
......
...@@ -33,10 +33,6 @@ import java.util.Comparator; ...@@ -33,10 +33,6 @@ import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import javax.management.MBean;
import javax.management.MXBean;
import javax.management.ManagedAttribute;
import javax.management.ManagedOperation;
import javax.management.NotCompliantMBeanException; import javax.management.NotCompliantMBeanException;
/** /**
...@@ -55,15 +51,15 @@ import javax.management.NotCompliantMBeanException; ...@@ -55,15 +51,15 @@ import javax.management.NotCompliantMBeanException;
*/ */
class MBeanAnalyzer<M> { class MBeanAnalyzer<M> {
static interface MBeanVisitor<M, X extends Exception> { static interface MBeanVisitor<M> {
public void visitAttribute(String attributeName, public void visitAttribute(String attributeName,
M getter, M getter,
M setter) throws X; M setter);
public void visitOperation(String operationName, 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 // visit attributes
for (Map.Entry<String, AttrMethods<M>> entry : attrMap.entrySet()) { for (Map.Entry<String, AttrMethods<M>> entry : attrMap.entrySet()) {
String name = entry.getKey(); String name = entry.getKey();
...@@ -108,7 +104,10 @@ class MBeanAnalyzer<M> { ...@@ -108,7 +104,10 @@ class MBeanAnalyzer<M> {
private MBeanAnalyzer(Class<?> mbeanType, private MBeanAnalyzer(Class<?> mbeanType,
MBeanIntrospector<M> introspector) MBeanIntrospector<M> introspector)
throws NotCompliantMBeanException { throws NotCompliantMBeanException {
introspector.checkCompliance(mbeanType); if (!mbeanType.isInterface()) {
throw new NotCompliantMBeanException("Not an interface: " +
mbeanType.getName());
}
try { try {
initMaps(mbeanType, introspector); initMaps(mbeanType, introspector);
...@@ -129,26 +128,18 @@ class MBeanAnalyzer<M> { ...@@ -129,26 +128,18 @@ class MBeanAnalyzer<M> {
for (Method m : methods) { for (Method m : methods) {
final String name = m.getName(); final String name = m.getName();
final int nParams = m.getParameterTypes().length; 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); final M cm = introspector.mFrom(m);
String attrName = ""; String attrName = "";
if (!managedOp) { if (name.startsWith("get"))
if (name.startsWith("get")) attrName = name.substring(3);
attrName = name.substring(3); else if (name.startsWith("is")
else if (name.startsWith("is") && m.getReturnType() == boolean.class)
&& m.getReturnType() == boolean.class) attrName = name.substring(2);
attrName = name.substring(2);
}
if (attrName.length() != 0 && nParams == 0 if (attrName.length() != 0 && nParams == 0
&& m.getReturnType() != void.class && !managedOp) { && m.getReturnType() != void.class) {
// It's a getter // It's a getter
// Check we don't have both isX and getX // Check we don't have both isX and getX
AttrMethods<M> am = attrMap.get(attrName); AttrMethods<M> am = attrMap.get(attrName);
...@@ -165,7 +156,7 @@ class MBeanAnalyzer<M> { ...@@ -165,7 +156,7 @@ class MBeanAnalyzer<M> {
attrMap.put(attrName, am); attrMap.put(attrName, am);
} else if (name.startsWith("set") && name.length() > 3 } else if (name.startsWith("set") && name.length() > 3
&& nParams == 1 && && nParams == 1 &&
m.getReturnType() == void.class && !managedOp) { m.getReturnType() == void.class) {
// It's a setter // It's a setter
attrName = name.substring(3); attrName = name.substring(3);
AttrMethods<M> am = attrMap.get(attrName); AttrMethods<M> am = attrMap.get(attrName);
...@@ -178,9 +169,6 @@ class MBeanAnalyzer<M> { ...@@ -178,9 +169,6 @@ class MBeanAnalyzer<M> {
} }
am.setter = cm; am.setter = cm;
attrMap.put(attrName, am); attrMap.put(attrName, am);
} else if (managedAttr) {
throw new NotCompliantMBeanException("Method " + name +
" has @ManagedAttribute but is not a valid getter or setter");
} else { } else {
// It's an operation // It's an operation
List<M> cms = opMap.get(name); List<M> cms = opMap.get(name);
......
...@@ -613,15 +613,6 @@ public class MBeanInstantiator { ...@@ -613,15 +613,6 @@ public class MBeanInstantiator {
return clr; 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 * Load a class with the specified loader, or with this object
* class loader if the specified loader is null. * class loader if the specified loader is null.
......
...@@ -37,7 +37,7 @@ import javax.management.MBeanServer; ...@@ -37,7 +37,7 @@ import javax.management.MBeanServer;
import javax.management.NotCompliantMBeanException; import javax.management.NotCompliantMBeanException;
import javax.management.ObjectName; import javax.management.ObjectName;
import javax.management.ReflectionException; 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 * Base class for MBeans. There is one instance of this class for
...@@ -121,8 +121,7 @@ import javax.management.openmbean.MXBeanMappingFactory; ...@@ -121,8 +121,7 @@ import javax.management.openmbean.MXBeanMappingFactory;
public abstract class MBeanSupport<M> public abstract class MBeanSupport<M>
implements DynamicMBean2, MBeanRegistration { implements DynamicMBean2, MBeanRegistration {
<T> MBeanSupport(T resource, Class<T> mbeanInterfaceType, <T> MBeanSupport(T resource, Class<T> mbeanInterfaceType)
MXBeanMappingFactory mappingFactory)
throws NotCompliantMBeanException { throws NotCompliantMBeanException {
if (mbeanInterfaceType == null) if (mbeanInterfaceType == null)
throw new NotCompliantMBeanException("Null MBean interface"); throw new NotCompliantMBeanException("Null MBean interface");
...@@ -133,14 +132,13 @@ public abstract class MBeanSupport<M> ...@@ -133,14 +132,13 @@ public abstract class MBeanSupport<M>
throw new NotCompliantMBeanException(msg); throw new NotCompliantMBeanException(msg);
} }
this.resource = resource; this.resource = resource;
MBeanIntrospector<M> introspector = getMBeanIntrospector(mappingFactory); MBeanIntrospector<M> introspector = getMBeanIntrospector();
this.perInterface = introspector.getPerInterface(mbeanInterfaceType); this.perInterface = introspector.getPerInterface(mbeanInterfaceType);
this.mbeanInfo = introspector.getMBeanInfo(resource, perInterface); this.mbeanInfo = introspector.getMBeanInfo(resource, perInterface);
} }
/** Return the appropriate introspector for this type of MBean. */ /** Return the appropriate introspector for this type of MBean. */
abstract MBeanIntrospector<M> abstract MBeanIntrospector<M> getMBeanIntrospector();
getMBeanIntrospector(MXBeanMappingFactory mappingFactory);
/** /**
* Return a cookie for this MBean. This cookie will be passed to * Return a cookie for this MBean. This cookie will be passed to
...@@ -262,14 +260,10 @@ public abstract class MBeanSupport<M> ...@@ -262,14 +260,10 @@ public abstract class MBeanSupport<M>
return resource.getClass().getName(); return resource.getClass().getName();
} }
public final Object getWrappedObject() { public final Object getResource() {
return resource; return resource;
} }
public final ClassLoader getWrappedClassLoader() {
return resource.getClass().getClassLoader();
}
public final Class<?> getMBeanInterface() { public final Class<?> getMBeanInterface() {
return perInterface.getMBeanInterface(); return perInterface.getMBeanInterface();
} }
......
...@@ -28,26 +28,18 @@ package com.sun.jmx.mbeanserver; ...@@ -28,26 +28,18 @@ package com.sun.jmx.mbeanserver;
import com.sun.jmx.mbeanserver.MBeanIntrospector.MBeanInfoMap; import com.sun.jmx.mbeanserver.MBeanIntrospector.MBeanInfoMap;
import com.sun.jmx.mbeanserver.MBeanIntrospector.PerInterfaceMap; import com.sun.jmx.mbeanserver.MBeanIntrospector.PerInterfaceMap;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import java.lang.ref.WeakReference;
import java.lang.reflect.GenericArrayType; import java.lang.reflect.GenericArrayType;
import java.lang.reflect.InvocationTargetException; import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType; import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type; import java.lang.reflect.Type;
import java.util.Map;
import java.util.WeakHashMap;
import javax.management.Description;
import javax.management.Descriptor; import javax.management.Descriptor;
import javax.management.ImmutableDescriptor; import javax.management.ImmutableDescriptor;
import javax.management.IntrospectionException;
import javax.management.JMX;
import javax.management.MBeanAttributeInfo; import javax.management.MBeanAttributeInfo;
import javax.management.MBeanException; import javax.management.MBeanException;
import javax.management.MBeanOperationInfo; import javax.management.MBeanOperationInfo;
import javax.management.MBeanParameterInfo; import javax.management.MBeanParameterInfo;
import javax.management.ManagedOperation;
import javax.management.NotCompliantMBeanException; import javax.management.NotCompliantMBeanException;
import javax.management.openmbean.MXBeanMappingFactory;
import javax.management.openmbean.OpenMBeanAttributeInfoSupport; import javax.management.openmbean.OpenMBeanAttributeInfoSupport;
import javax.management.openmbean.OpenMBeanOperationInfoSupport; import javax.management.openmbean.OpenMBeanOperationInfoSupport;
import javax.management.openmbean.OpenMBeanParameterInfo; import javax.management.openmbean.OpenMBeanParameterInfo;
...@@ -60,36 +52,10 @@ import javax.management.openmbean.OpenType; ...@@ -60,36 +52,10 @@ import javax.management.openmbean.OpenType;
* @since 1.6 * @since 1.6
*/ */
class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> { class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
/* We keep one MXBeanIntrospector per MXBeanMappingFactory, since the results private static final MXBeanIntrospector instance = new MXBeanIntrospector();
* 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>>();
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) { static MXBeanIntrospector getInstance() {
this.mappingFactory = factory; return instance;
} }
@Override @Override
...@@ -115,7 +81,7 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> { ...@@ -115,7 +81,7 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
@Override @Override
ConvertingMethod mFrom(Method m) { ConvertingMethod mFrom(Method m) {
return ConvertingMethod.from(m, mappingFactory); return ConvertingMethod.from(m);
} }
@Override @Override
...@@ -176,17 +142,13 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> { ...@@ -176,17 +142,13 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
@Override @Override
MBeanAttributeInfo getMBeanAttributeInfo(String attributeName, MBeanAttributeInfo getMBeanAttributeInfo(String attributeName,
ConvertingMethod getter, ConvertingMethod setter) ConvertingMethod getter, ConvertingMethod setter) {
throws IntrospectionException {
final boolean isReadable = (getter != null); final boolean isReadable = (getter != null);
final boolean isWritable = (setter != null); final boolean isWritable = (setter != null);
final boolean isIs = isReadable && getName(getter).startsWith("is"); final boolean isIs = isReadable && getName(getter).startsWith("is");
final String description = getAttributeDescription( final String description = attributeName;
attributeName, attributeName,
getter == null ? null : getter.getMethod(),
setter == null ? null : setter.getMethod());
final OpenType<?> openType; final OpenType<?> openType;
final Type originalType; final Type originalType;
...@@ -235,17 +197,13 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> { ...@@ -235,17 +197,13 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
MBeanOperationInfo getMBeanOperationInfo(String operationName, MBeanOperationInfo getMBeanOperationInfo(String operationName,
ConvertingMethod operation) { ConvertingMethod operation) {
final Method method = operation.getMethod(); final Method method = operation.getMethod();
String description = operationName; final String description = operationName;
/* Ideally this would be an empty string, but /* Ideally this would be an empty string, but
OMBOperationInfo constructor forbids that. */ OMBOperationInfo constructor forbids that. Also, we
Description d = method.getAnnotation(Description.class); could consult an annotation to get a useful
if (d != null) description. */
description = d.value();
int impact = MBeanOperationInfo.UNKNOWN; final int impact = MBeanOperationInfo.UNKNOWN;
ManagedOperation annot = method.getAnnotation(ManagedOperation.class);
if (annot != null)
impact = annot.impact().getCode();
final OpenType<?> returnType = operation.getOpenReturnType(); final OpenType<?> returnType = operation.getOpenReturnType();
final Type originalReturnType = operation.getGenericReturnType(); final Type originalReturnType = operation.getGenericReturnType();
...@@ -257,15 +215,8 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> { ...@@ -257,15 +215,8 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
boolean openParameterTypes = true; boolean openParameterTypes = true;
Annotation[][] annots = method.getParameterAnnotations(); Annotation[][] annots = method.getParameterAnnotations();
for (int i = 0; i < paramTypes.length; i++) { for (int i = 0; i < paramTypes.length; i++) {
String paramName = Introspector.nameForParameter(annots[i]); final String paramName = "p" + i;
if (paramName == null) final String paramDescription = paramName;
paramName = "p" + i;
String paramDescription =
Introspector.descriptionForParameter(annots[i]);
if (paramDescription == null)
paramDescription = paramName;
final OpenType<?> openType = paramTypes[i]; final OpenType<?> openType = paramTypes[i];
final Type originalType = originalParamTypes[i]; final Type originalType = originalParamTypes[i];
Descriptor descriptor = Descriptor descriptor =
...@@ -292,7 +243,7 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> { ...@@ -292,7 +243,7 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
Descriptor descriptor = Descriptor descriptor =
typeDescriptor(returnType, originalReturnType); typeDescriptor(returnType, originalReturnType);
descriptor = ImmutableDescriptor.union(descriptor, descriptor = ImmutableDescriptor.union(descriptor,
Introspector.descriptorForElement(method, false)); Introspector.descriptorForElement(method));
final MBeanOperationInfo oi; final MBeanOperationInfo oi;
if (openReturnType && openParameterTypes) { if (openReturnType && openParameterTypes) {
/* If the return value and all the parameters can be faithfully /* If the return value and all the parameters can be faithfully
...@@ -343,17 +294,6 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> { ...@@ -343,17 +294,6 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
return ImmutableDescriptor.EMPTY_DESCRIPTOR; 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, private static Descriptor typeDescriptor(OpenType<?> openType,
Type originalType) { Type originalType) {
return new ImmutableDescriptor( return new ImmutableDescriptor(
...@@ -421,7 +361,5 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> { ...@@ -421,7 +361,5 @@ class MXBeanIntrospector extends MBeanIntrospector<ConvertingMethod> {
private final PerInterfaceMap<ConvertingMethod> private final PerInterfaceMap<ConvertingMethod>
perInterfaceMap = new PerInterfaceMap<ConvertingMethod>(); perInterfaceMap = new PerInterfaceMap<ConvertingMethod>();
private final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap(); private static final MBeanInfoMap mbeanInfoMap = new MBeanInfoMap();
private final MXBeanMappingFactory mappingFactory;
} }
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册