package org.oddjob.jmx;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.management.Attribute;
import javax.management.AttributeList;
import javax.management.AttributeNotFoundException;
import javax.management.DynamicMBean;
import javax.management.InvalidAttributeValueException;
import javax.management.MBeanAttributeInfo;
import javax.management.MBeanConstructorInfo;
import javax.management.MBeanException;
import javax.management.MBeanInfo;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanOperationInfo;
import javax.management.MBeanServer;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerFactory;
import javax.management.Notification;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import javax.management.ReflectionException;
import javax.management.remote.JMXConnector;
import javax.management.remote.JMXConnectorFactory;
import javax.management.remote.JMXConnectorServer;
import javax.management.remote.JMXConnectorServerFactory;
import javax.management.remote.JMXServiceURL;
import org.apache.log4j.Logger;
import junit.framework.TestCase;
public class JMXAssumptionsTest extends TestCase {
private static final Logger logger = Logger.getLogger(JMXAssumptionsTest.class);
public class OurMBean extends NotificationBroadcasterSupport implements
DynamicMBean {
@Override
public Object getAttribute(String attribute)
throws AttributeNotFoundException, MBeanException,
ReflectionException {
throw new RuntimeException("Unexpected");
}
@Override
public AttributeList getAttributes(String[] attributes) {
throw new RuntimeException("Unexpected");
}
@Override
public MBeanInfo getMBeanInfo() {
return new MBeanInfo(OurMBean.class.getName(),
"Test",
new MBeanAttributeInfo[0],
new MBeanConstructorInfo[0],
new MBeanOperationInfo[0],
new MBeanNotificationInfo[] {
new MBeanNotificationInfo(new String[] { "test1" },
Notification.class.getName(), "Test 1"),
new MBeanNotificationInfo(new String[] { "test2" },
Notification.class.getName(), "Test 2") });
}
@Override
public Object invoke(String actionName, Object[] params,
String[] signature) throws MBeanException, ReflectionException {
throw new RuntimeException("Unexpected");
}
@Override
public void setAttribute(Attribute attribute)
throws AttributeNotFoundException,
InvalidAttributeValueException, MBeanException,
ReflectionException {
throw new RuntimeException("Unexpected");
}
@Override
public AttributeList setAttributes(AttributeList attributes) {
throw new RuntimeException("Unexpected");
}
}
class OurListener implements NotificationListener {
Set<Thread> threads = new HashSet<Thread>();
AtomicInteger count = new AtomicInteger();
long last = -1;
boolean badSequence;
@Override
public void handleNotification(Notification notification,
Object handback) {
synchronized (threads) {
threads.add(Thread.currentThread());
}
logger.debug("Recevied notification " + notification.getSequenceNumber());
if (notification.getSequenceNumber() != last + 1) {
badSequence = true;
}
++last;
count.incrementAndGet();
}
public int getNumThreades() {
synchronized (threads) {
return threads.size();
}
}
}
public void testStructuralNotificaitonAssumptions() throws Exception {
JMXServiceURL address = new JMXServiceURL("service:jmx:rmi://");
MBeanServer server = MBeanServerFactory.createMBeanServer();
JMXConnectorServer cntorServer = JMXConnectorServerFactory.newJMXConnectorServer(
address, null, server);
cntorServer.start();
final OurMBean ourMBean = new OurMBean();
ObjectName name = new ObjectName("test", "test", "test");
server.registerMBean(ourMBean, name);
JMXConnector cntor = JMXConnectorFactory.connect(
cntorServer.getAddress());
MBeanServerConnection mbsc = cntor.getMBeanServerConnection();
OurListener listener = new OurListener();
mbsc.addNotificationListener(name, listener, null, null);
ExecutorService executorService = Executors.newFixedThreadPool(5);
for (int i = 0; i < 100; ++i) {
final Notification n1 = new Notification("test1", name, i);
final Notification n2 = new Notification("test2", name, i);
Runnable r1 = new Runnable() {
@Override
public void run() {
ourMBean.sendNotification(n1);
}
};
Runnable r2 = new Runnable() {
@Override
public void run() {
ourMBean.sendNotification(n2);
}
};
executorService.submit(r1);
executorService.submit(r2);
}
executorService.shutdown();
assertTrue(executorService.awaitTermination(
1000, TimeUnit.HOURS));
while (listener.count.get() < 200) {
synchronized (this) {
wait(500);
}
}
assertEquals(1, listener.getNumThreades());
cntor.close();
cntorServer.stop();
}
}