blob: b6c6d87926fade5670fce3242a6994b442c77d7d [file] [log] [blame]
/*
* 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;
}
}