6450834: RFE: allow StandardMBean to call MBeanRegistration methods on its wrapped resource
authorjfdenise
Tue, 09 Dec 2008 16:14:53 +0100
changeset 1701 f5cedaa459bf
parent 1700 4506662fb2ee
child 1702 50e12093123c
6450834: RFE: allow StandardMBean to call MBeanRegistration methods on its wrapped resource 6373143: MonitorNotification should have a public constructor Reviewed-by: emcmanus
jdk/src/share/classes/javax/management/StandardMBean.java
jdk/src/share/classes/javax/management/monitor/MonitorNotification.java
jdk/test/javax/management/monitor/InstantiateMonitorNotificationTest.java
jdk/test/javax/management/standardmbean/RegistrationTest.java
--- a/jdk/src/share/classes/javax/management/StandardMBean.java	Tue Dec 09 15:57:09 2008 +0100
+++ b/jdk/src/share/classes/javax/management/StandardMBean.java	Tue Dec 09 16:14:53 2008 +0100
@@ -135,6 +135,7 @@
         private static final long serialVersionUID = 5107355471177517164L;
 
         private boolean wrappedVisible;
+        private boolean forwardRegistration;
 
         /**
          * <p>Construct an {@code Options} object where all options have
@@ -177,15 +178,56 @@
             this.wrappedVisible = visible;
         }
 
-        // Canonical objects for each of (MXBean,!MXBean) x (WVisible,!WVisible)
+        /**
+         * <p>Defines whether the {@link MBeanRegistration MBeanRegistration}
+         * callbacks are forwarded to the wrapped object.</p>
+         *
+         * <p>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.</p>
+         *
+         * @return true if the <code>MBeanRegistration</code> callbacks
+         * are forwarded to the wrapped object.
+         */
+        public boolean isMBeanRegistrationForwarded() {
+            return this.forwardRegistration;
+        }
+
+        /**
+         * <p>Set the
+         * {@link #isMBeanRegistrationForwarded MBeanRegistrationForwarded}
+         * option to the given value.</p>
+         * @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 @@
         @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 @@
      *
      * @exception IllegalArgumentException if the given
      * <var>implementation</var> is null.
-     *
+     * @exception IllegalStateException if the
+     * {@link Options#isMBeanRegistrationForwarded MBeanRegistrationForwarded}
+     * option is true.
      * @exception NotCompliantMBeanException if the given
      * <var>implementation</var> does not implement the
      * Standard MBean (or MXBean) interface that was
@@ -490,6 +535,12 @@
 
         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 @@
      * registered in the MBean server.</p>
      *
      * <p>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.</p>
+     * 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.</p>
      *
      * <p>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 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 @@
      * <p>Allows the MBean to perform any operations needed after having been
      * registered in the MBean server or after the registration has failed.</p>
      *
-     * <p>The default implementation of this method does nothing for
+     * <p>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.</p>
      *
@@ -1338,16 +1402,24 @@
     public void postRegister(Boolean registrationDone) {
         if (!registrationDone)
             mbean.unregister();
+        if(shouldForwardMBeanRegistration())
+            ((MBeanRegistration)getImplementation()).
+                    postRegister(registrationDone);
     }
 
     /**
      * <p>Allows the MBean to perform any operations it needs before
      * being unregistered by the MBean server.</p>
      *
-     * <p>The default implementation of this method does nothing.</p>
+     * <p>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.
+     * </p>
      *
      * <p>It is good practice for a subclass that overrides this method
-     * to call the overridden method via {@code super.preDeegister(...)}.</p>
+     * to call the overridden method via {@code super.preDeregister(...)}.</p>
      *
      * @throws Exception no checked exceptions are throw by this method
      * but {@code Exception} is declared so that subclasses can override
@@ -1356,13 +1428,19 @@
      * @since 1.6
      */
     public void preDeregister() throws Exception {
+        if(shouldForwardMBeanRegistration())
+            ((MBeanRegistration)getImplementation()).preDeregister();
     }
 
     /**
      * <p>Allows the MBean to perform any operations needed after having been
      * unregistered in the MBean server.</p>
      *
-     * <p>The default implementation of this method does nothing for
+     * <p>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.</p>
      *
@@ -1375,8 +1453,15 @@
      */
     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
     //
--- a/jdk/src/share/classes/javax/management/monitor/MonitorNotification.java	Tue Dec 09 15:57:09 2008 +0100
+++ b/jdk/src/share/classes/javax/management/monitor/MonitorNotification.java	Tue Dec 09 16:14:53 2008 +0100
@@ -201,7 +201,7 @@
      * @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);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/monitor/InstantiateMonitorNotificationTest.java	Tue Dec 09 16:14:53 2008 +0100
@@ -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");
+    }
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/standardmbean/RegistrationTest.java	Tue Dec 09 16:14:53 2008 +0100
@@ -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");
+    }
+}