jdk/test/javax/management/remote/mandatory/connectorServer/ForwarderChainTest.java
changeset 1004 5ba8217eb504
child 1570 4165709c91e3
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/javax/management/remote/mandatory/connectorServer/ForwarderChainTest.java	Thu Jul 31 15:31:13 2008 +0200
@@ -0,0 +1,274 @@
+/*
+ * 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.
+ */
+
+import java.util.NoSuchElementException;
+import java.util.Random;
+import javax.management.MBeanServer;
+import javax.management.MBeanServerConnection;
+import javax.management.MBeanServerFactory;
+import javax.management.remote.IdentityMBeanServerForwarder;
+import javax.management.remote.JMXConnector;
+import javax.management.remote.JMXConnectorFactory;
+import javax.management.remote.JMXConnectorServer;
+import javax.management.remote.JMXServiceURL;
+import javax.management.remote.MBeanServerForwarder;
+
+/*
+ * @test
+ * @bug 6218920
+ * @summary Tests manipulation of MBeanServerForwarder chains.
+ * @author Eamonn McManus
+ */
+import javax.management.remote.rmi.RMIConnectorServer;
+
+public class ForwarderChainTest {
+    private static final TestMBeanServerForwarder[] forwarders =
+            new TestMBeanServerForwarder[10];
+    static {
+        for (int i = 0; i < forwarders.length; i++)
+            forwarders[i] = new TestMBeanServerForwarder(i);
+    }
+
+    private static class TestMBeanServerForwarder
+            extends IdentityMBeanServerForwarder {
+        private final int index;
+        volatile int defaultDomainCount;
+
+        TestMBeanServerForwarder(int index) {
+            this.index = index;
+        }
+
+        @Override
+        public String getDefaultDomain() {
+            defaultDomainCount++;
+            return super.getDefaultDomain();
+        }
+
+        @Override
+        public String toString() {
+            return "forwarders[" + index + "]";
+        }
+    }
+
+    private static String failure;
+
+    public static void main(String[] args) throws Exception {
+
+        System.out.println("===Test with newly created, unattached server===");
+
+        JMXServiceURL url = new JMXServiceURL("service:jmx:rmi:///");
+        JMXConnectorServer cs = new RMIConnectorServer(url, null);
+        test(cs, null);
+
+        System.out.println("===Test with server attached to MBS===");
+        MBeanServer mbs = MBeanServerFactory.newMBeanServer();
+        cs = new RMIConnectorServer(url, null, mbs);
+        test(cs, mbs);
+
+        System.out.println("===Remove any leftover forwarders===");
+        while (cs.getSystemMBeanServer() instanceof MBeanServerForwarder) {
+            MBeanServerForwarder mbsf =
+                    (MBeanServerForwarder) cs.getSystemMBeanServer();
+            cs.removeMBeanServerForwarder(mbsf);
+        }
+        expectChain(cs, "U", mbs);
+
+        System.out.println("===Ensure forwarders are called===");
+        cs.setMBeanServerForwarder(forwarders[0]);
+        cs.setSystemMBeanServerForwarder(forwarders[1]);
+        expectChain(cs, "1U0", mbs);
+        cs.start();
+        if (forwarders[0].defaultDomainCount != 0 ||
+                forwarders[1].defaultDomainCount != 0) {
+            fail("defaultDomainCount not zero");
+        }
+        JMXServiceURL addr = cs.getAddress();
+        JMXConnector cc = JMXConnectorFactory.connect(addr);
+        MBeanServerConnection mbsc = cc.getMBeanServerConnection();
+        mbsc.getDefaultDomain();
+        cc.close();
+        cs.stop();
+        for (boolean system : new boolean[] {false, true}) {
+            TestMBeanServerForwarder mbsf = system ? forwarders[1] : forwarders[0];
+            if (mbsf.defaultDomainCount != 1) {
+                fail((system ? "System" : "User") + " forwarder called " +
+                        mbsf.defaultDomainCount + " times");
+            }
+        }
+
+        if (failure == null)
+            System.out.println("TEST PASSED");
+        else
+            throw new Exception("TEST FAILED: " + failure);
+    }
+
+    private static void test(JMXConnectorServer cs, MBeanServer end) {
+        // A newly-created connector server might have system forwarders,
+        // so get rid of those.
+        while (cs.getSystemMBeanServer() != cs.getMBeanServer())
+            cs.removeMBeanServerForwarder((MBeanServerForwarder) cs.getSystemMBeanServer());
+
+        expectChain(cs, "U", end);
+
+        System.out.println("Add a user forwarder");
+        cs.setMBeanServerForwarder(forwarders[0]);
+        expectChain(cs, "U0", end);
+
+        System.out.println("Add another user forwarder");
+        cs.setMBeanServerForwarder(forwarders[1]);
+        expectChain(cs, "U10", end);
+
+        System.out.println("Add a system forwarder");
+        cs.setSystemMBeanServerForwarder(forwarders[2]);
+        expectChain(cs, "2U10", end);
+
+        System.out.println("Add another user forwarder");
+        cs.setMBeanServerForwarder(forwarders[3]);
+        expectChain(cs, "2U310", end);
+
+        System.out.println("Add another system forwarder");
+        cs.setSystemMBeanServerForwarder(forwarders[4]);
+        expectChain(cs, "42U310", end);
+
+        System.out.println("Remove the first user forwarder");
+        cs.removeMBeanServerForwarder(forwarders[3]);
+        expectChain(cs, "42U10", end);
+
+        System.out.println("Remove the last user forwarder");
+        cs.removeMBeanServerForwarder(forwarders[0]);
+        expectChain(cs, "42U1", end);
+
+        System.out.println("Remove the first system forwarder");
+        cs.removeMBeanServerForwarder(forwarders[4]);
+        expectChain(cs, "2U1", end);
+
+        System.out.println("Remove the last system forwarder");
+        cs.removeMBeanServerForwarder(forwarders[2]);
+        expectChain(cs, "U1", end);
+
+        System.out.println("Remove the last forwarder");
+        cs.removeMBeanServerForwarder(forwarders[1]);
+        expectChain(cs, "U", end);
+
+        System.out.println("---Doing random manipulations---");
+        // In this loop we pick one of the forwarders at random each time.
+        // If it is already in the chain, then we remove it.  If it is not
+        // in the chain, then we do one of three things: try to remove it
+        // (expecting an exception); add it to the user chain; or add it
+        // to the system chain.
+        // A subtle point is that if there is no MBeanServer then
+        // cs.setMBeanServerForwarder(mbsf) does not change mbsf.getMBeanServer().
+        // Since we're recycling a random forwarder[i], we explicitly
+        // call mbsf.setMBeanServer(null) in this case.
+        String chain = "U";
+        Random r = new Random();
+        for (int i = 0; i < 50; i++) {
+            int fwdi = r.nextInt(10);
+            MBeanServerForwarder mbsf = forwarders[fwdi];
+            char c = (char) ('0' + fwdi);
+            int ci = chain.indexOf(c);
+            if (ci >= 0) {
+                System.out.println("Remove " + c);
+                cs.removeMBeanServerForwarder(mbsf);
+                chain = chain.substring(0, ci) + chain.substring(ci + 1);
+            } else {
+                switch (r.nextInt(3)) {
+                    case 0: { // try to remove it
+                        try {
+                            System.out.println("Try to remove absent " + c);
+                            cs.removeMBeanServerForwarder(mbsf);
+                            fail("Remove succeeded but should not have");
+                            return;
+                        } catch (NoSuchElementException e) {
+                        }
+                        break;
+                    }
+                    case 1: { // add it to the user chain
+                        System.out.println("Add " + c + " to user chain");
+                        if (cs.getMBeanServer() == null)
+                            mbsf.setMBeanServer(null);
+                        cs.setMBeanServerForwarder(mbsf);
+                        int postu = chain.indexOf('U') + 1;
+                        chain = chain.substring(0, postu) + c +
+                                chain.substring(postu);
+                        break;
+                    }
+                    case 2: { // add it to the system chain
+                        System.out.println("Add " + c + " to system chain");
+                        if (cs.getSystemMBeanServer() == null)
+                            mbsf.setMBeanServer(null);
+                        cs.setSystemMBeanServerForwarder(mbsf);
+                        chain = c + chain;
+                        break;
+                    }
+                }
+            }
+            expectChain(cs, chain, end);
+        }
+    }
+
+    /*
+     * Check that the forwarder chain has the expected contents.  The forwarders
+     * are encoded as a string.  For example, "12U34" means that the system
+     * chain contains forwarders[1] followed by forwarders[2], and the user
+     * chain contains forwarders[3] followed by forwarders[4].  Since the
+     * user chain is attached to the end of the system chain, another way to
+     * look at this is that the U marks the transition from one to the other.
+     *
+     * After traversing the chains, we should be pointing at "end".
+     */
+    private static void expectChain(
+            JMXConnectorServer cs, String chain, MBeanServer end) {
+        System.out.println("...expected chain: " + chain);
+        MBeanServer curr = cs.getSystemMBeanServer();
+        int i = 0;
+        while (i < chain.length()) {
+            char c = chain.charAt(i);
+            if (c == 'U') {
+                if (cs.getMBeanServer() != curr) {
+                    fail("User chain should have started here: " + curr);
+                    return;
+                }
+            } else {
+                int fwdi = c - '0';
+                MBeanServerForwarder forwarder = forwarders[fwdi];
+                if (curr != forwarder) {
+                    fail("Expected forwarder " + c + " here: " + curr);
+                    return;
+                }
+                curr = ((MBeanServerForwarder) curr).getMBeanServer();
+            }
+            i++;
+        }
+        if (curr != end) {
+            fail("End of chain is " + curr + ", should be " + end);
+            return;
+        }
+        System.out.println("...OK");
+    }
+
+    private static void fail(String msg) {
+        System.out.println("FAILED: " + msg);
+        failure = msg;
+    }
+}