From ececf2c7764535b253c8078829596aa58790005b Mon Sep 17 00:00:00 2001 From: jfdenise Date: Tue, 9 Dec 2008 16:14:53 +0100 Subject: [PATCH] 6450834: RFE: allow StandardMBean to call MBeanRegistration methods on its wrapped resource 6373143: MonitorNotification should have a public constructor Reviewed-by: emcmanus --- .../javax/management/StandardMBean.java | 107 ++++++++++++++++-- .../monitor/MonitorNotification.java | 2 +- .../InstantiateMonitorNotificationTest.java | 52 +++++++++ .../standardmbean/RegistrationTest.java | 91 +++++++++++++++ 4 files changed, 240 insertions(+), 12 deletions(-) create mode 100644 test/javax/management/monitor/InstantiateMonitorNotificationTest.java create mode 100644 test/javax/management/standardmbean/RegistrationTest.java diff --git a/src/share/classes/javax/management/StandardMBean.java b/src/share/classes/javax/management/StandardMBean.java index 45badeac6..f3edc95d7 100644 --- a/src/share/classes/javax/management/StandardMBean.java +++ b/src/share/classes/javax/management/StandardMBean.java @@ -135,6 +135,7 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { private static final long serialVersionUID = 5107355471177517164L; private boolean wrappedVisible; + private boolean forwardRegistration; /** *

Construct an {@code Options} object where all options have @@ -177,15 +178,56 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { this.wrappedVisible = visible; } - // Canonical objects for each of (MXBean,!MXBean) x (WVisible,!WVisible) + /** + *

Defines whether the {@link MBeanRegistration MBeanRegistration} + * callbacks are forwarded to the wrapped object.

+ * + *

If this option is true, then + * {@link #preRegister(MBeanServer, ObjectName) preRegister}, + * {@link #postRegister(Boolean) postRegister}, + * {@link #preDeregister preDeregister} and + * {@link #postDeregister postDeregister} methods are forwarded + * to the wrapped object, in addition to the behaviour specified + * for the StandardMBean instance itself. + * The default value is false for compatibility reasons, but true + * is a better value for most new code.

+ * + * @return true if the MBeanRegistration callbacks + * are forwarded to the wrapped object. + */ + public boolean isMBeanRegistrationForwarded() { + return this.forwardRegistration; + } + + /** + *

Set the + * {@link #isMBeanRegistrationForwarded MBeanRegistrationForwarded} + * option to the given value.

+ * @param forward the new value. + */ + public void setMBeanRegistrationForwarded(boolean forward) { + this.forwardRegistration = forward; + } + + // Canonical objects for each of + // (MXBean,!MXBean) x (WVisible,!WVisible) x (Forward,!Forward) private static final Options[] CANONICALS = { new Options(), new Options(), new Options(), new Options(), + new Options(), new Options(), new Options(), new Options(), }; static { CANONICALS[1].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT); CANONICALS[2].setWrappedObjectVisible(true); CANONICALS[3].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT); CANONICALS[3].setWrappedObjectVisible(true); + CANONICALS[4].setMBeanRegistrationForwarded(true); + CANONICALS[5].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT); + CANONICALS[5].setMBeanRegistrationForwarded(true); + CANONICALS[6].setWrappedObjectVisible(true); + CANONICALS[6].setMBeanRegistrationForwarded(true); + CANONICALS[7].setMXBeanMappingFactory(MXBeanMappingFactory.DEFAULT); + CANONICALS[7].setWrappedObjectVisible(true); + CANONICALS[7].setMBeanRegistrationForwarded(true); } @Override MBeanOptions[] canonicals() { @@ -195,7 +237,8 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { @Override boolean same(MBeanOptions opts) { return (super.same(opts) && opts instanceof Options && - ((Options) opts).wrappedVisible == wrappedVisible); + ((Options) opts).wrappedVisible == wrappedVisible && + ((Options) opts).forwardRegistration ==forwardRegistration); } } @@ -477,7 +520,9 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { * * @exception IllegalArgumentException if the given * implementation is null. - * + * @exception IllegalStateException if the + * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded} + * option is true. * @exception NotCompliantMBeanException if the given * implementation does not implement the * Standard MBean (or MXBean) interface that was @@ -490,6 +535,12 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { if (implementation == null) throw new IllegalArgumentException("implementation is null"); + + if(options instanceof Options && + ((Options) options).isMBeanRegistrationForwarded()) + throw new IllegalStateException("Implementation can't be changed " + + "because MBeanRegistrationForwarded option is true"); + setImplementation2(implementation); } @@ -1273,10 +1324,14 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { * registered in the MBean server.

* *

The default implementation of this method returns the {@code name} - * parameter. It does nothing else for - * Standard MBeans. For MXBeans, it records the {@code MBeanServer} - * and {@code ObjectName} parameters so they can be used to translate - * inter-MXBean references.

+ * parameter. If the + * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded} + * option is set to true, then this method is forwarded to the object + * returned by the {@link #getImplementation getImplementation()} method. + * The name returned by this call is then returned by this method. + * It does nothing else for Standard MBeans. For MXBeans, it records + * the {@code MBeanServer} and {@code ObjectName} parameters so they can + * be used to translate inter-MXBean references.

* *

It is good practice for a subclass that overrides this method * to call the overridden method via {@code super.preRegister(...)}. @@ -1311,6 +1366,11 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { */ public ObjectName preRegister(MBeanServer server, ObjectName name) throws Exception { + // Forward preRegister before to call register and + // inject parameters. + if(shouldForwardMBeanRegistration()) + name = ((MBeanRegistration)getImplementation()). + preRegister(server, name); mbean.register(server, name); MBeanInjector.inject(mbean.getWrappedObject(), server, name); return name; @@ -1320,7 +1380,11 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { *

Allows the MBean to perform any operations needed after having been * registered in the MBean server or after the registration has failed.

* - *

The default implementation of this method does nothing for + *

If the + * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded} + * option is set to true, then this method is forwarded to the object + * returned by the {@link #getImplementation getImplementation()} method. + * The default implementation of this method does nothing else for * Standard MBeans. For MXBeans, it undoes any work done by * {@link #preRegister preRegister} if registration fails.

* @@ -1338,16 +1402,24 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { public void postRegister(Boolean registrationDone) { if (!registrationDone) mbean.unregister(); + if(shouldForwardMBeanRegistration()) + ((MBeanRegistration)getImplementation()). + postRegister(registrationDone); } /** *

Allows the MBean to perform any operations it needs before * being unregistered by the MBean server.

* - *

The default implementation of this method does nothing.

+ *

If the + * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded} + * option is set to true, then this method is forwarded to the object + * returned by the {@link #getImplementation getImplementation()} method. + * Other than that, the default implementation of this method does nothing. + *

* *

It is good practice for a subclass that overrides this method - * to call the overridden method via {@code super.preDeegister(...)}.

+ * to call the overridden method via {@code super.preDeregister(...)}.

* * @throws Exception no checked exceptions are throw by this method * but {@code Exception} is declared so that subclasses can override @@ -1356,13 +1428,19 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { * @since 1.6 */ public void preDeregister() throws Exception { + if(shouldForwardMBeanRegistration()) + ((MBeanRegistration)getImplementation()).preDeregister(); } /** *

Allows the MBean to perform any operations needed after having been * unregistered in the MBean server.

* - *

The default implementation of this method does nothing for + *

If the + * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded} + * option is set to true, then this method is forwarded to the object + * returned by the {@link #getImplementation getImplementation()} method. + * The default implementation of this method does nothing else for * Standard MBeans. For MXBeans, it removes any information that * was recorded by the {@link #preRegister preRegister} method.

* @@ -1375,8 +1453,15 @@ public class StandardMBean implements DynamicWrapperMBean, MBeanRegistration { */ public void postDeregister() { mbean.unregister(); + if(shouldForwardMBeanRegistration()) + ((MBeanRegistration)getImplementation()).postDeregister(); } + private boolean shouldForwardMBeanRegistration() { + return (getImplementation() instanceof MBeanRegistration) && + (options instanceof Options && + ((Options) options).isMBeanRegistrationForwarded()); + } // // MBeanInfo immutability // diff --git a/src/share/classes/javax/management/monitor/MonitorNotification.java b/src/share/classes/javax/management/monitor/MonitorNotification.java index 744d7434f..f0d65c6da 100644 --- a/src/share/classes/javax/management/monitor/MonitorNotification.java +++ b/src/share/classes/javax/management/monitor/MonitorNotification.java @@ -201,7 +201,7 @@ public class MonitorNotification extends javax.management.Notification { * @param derGauge The derived gauge. * @param trigger The threshold/string (depending on the monitor type) that triggered the notification. */ - MonitorNotification(String type, Object source, long sequenceNumber, long timeStamp, String msg, + public MonitorNotification(String type, Object source, long sequenceNumber, long timeStamp, String msg, ObjectName obsObj, String obsAtt, Object derGauge, Object trigger) { super(type, source, sequenceNumber, timeStamp, msg); diff --git a/test/javax/management/monitor/InstantiateMonitorNotificationTest.java b/test/javax/management/monitor/InstantiateMonitorNotificationTest.java new file mode 100644 index 000000000..ae16858d2 --- /dev/null +++ b/test/javax/management/monitor/InstantiateMonitorNotificationTest.java @@ -0,0 +1,52 @@ + +import javax.management.ObjectName; +import javax.management.monitor.MonitorNotification; + +/* + * 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. + * + * 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. + */ + +/* + * @test + * @bug 6373143 + * @summary Test MonitorNotification public constructor + * @author JFDenise + * @run clean InstantiateMonitorNotificationTest + * @run build InstantiateMonitorNotificationTest + * @run main InstantiateMonitorNotificationTest + */ + +public class InstantiateMonitorNotificationTest { + + public static void main(String[] args) throws Exception { + MonitorNotification notif = new MonitorNotification("com.foo.test", + ObjectName.valueOf(":type=Monitor"), + 999, + 999, + "A message", + ObjectName.valueOf(":type=Observed"), + "MyAttribute", + Integer.valueOf(14), + Integer.valueOf(15)); + System.out.println("Test passed"); + } +} diff --git a/test/javax/management/standardmbean/RegistrationTest.java b/test/javax/management/standardmbean/RegistrationTest.java new file mode 100644 index 000000000..9ca0c464f --- /dev/null +++ b/test/javax/management/standardmbean/RegistrationTest.java @@ -0,0 +1,91 @@ +/* + * 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. + * + * 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. + */ + +/* + * @test + * @bug 6450834 + * @summary Forward MBeanRegistration calls + * @author JF Denise + * @run main RegistrationTest + */ + +import java.io.Serializable; +import java.lang.management.ManagementFactory; +import javax.management.*; + +public class RegistrationTest { + static boolean preRegisterCalled; + static boolean postRegisterCalled; + static boolean preDeregisterCalled; + static boolean postDeregisterCalled; + + static void checkResult(boolean expected) throws Exception { + if((preRegisterCalled != expected || + postRegisterCalled != expected || + preDeregisterCalled != expected || + postDeregisterCalled != expected)) + throw new Exception("Mismatch preRegisterCalled = " + + preRegisterCalled + ", postRegisterCalled = " + + postRegisterCalled + ", preDeregisterCalled = " + + preDeregisterCalled + ", postDeregisterCalled = " + + postDeregisterCalled); + } + static class Wrapped implements MBeanRegistration,Serializable { + + public ObjectName preRegister(MBeanServer server, ObjectName name) + throws Exception { + preRegisterCalled = true; + return name; + } + + public void postRegister(Boolean registrationDone) { + postRegisterCalled = true; + } + + public void preDeregister() throws Exception { + preDeregisterCalled = true; + } + + public void postDeregister() { + postDeregisterCalled = true; + } + + } + + public static void main(String[] args) throws Exception { + StandardMBean std = new StandardMBean(new Wrapped(), + Serializable.class); + ObjectName name = ObjectName.valueOf(":type=Test"); + ManagementFactory.getPlatformMBeanServer().registerMBean(std,name); + ManagementFactory.getPlatformMBeanServer().unregisterMBean(name); + checkResult(false); + StandardMBean.Options opt = new StandardMBean.Options(); + opt.setMBeanRegistrationForwarded(true); + std = new StandardMBean(new Wrapped(), + Serializable.class, opt ); + ManagementFactory.getPlatformMBeanServer().registerMBean(std,name); + ManagementFactory.getPlatformMBeanServer().unregisterMBean(name); + checkResult(true); + System.out.println("Test OK"); + } +} -- GitLab