/*
* Copyright (C) The MX4J Contributors.
* All rights reserved.
*
* This software is distributed under the terms of the MX4J License version 1.0.
* See the terms of the MX4J License in the documentation provided with this software.
*/
package test.javax.management;
import java.io.IOException;
import java.lang.reflect.UndeclaredThrowableException;
import javax.management.InstanceNotFoundException;
import javax.management.ListenerNotFoundException;
import javax.management.MBeanException;
import javax.management.MBeanNotificationInfo;
import javax.management.MBeanServer;
import javax.management.MBeanServerConnection;
import javax.management.MBeanServerInvocationHandler;
import javax.management.Notification;
import javax.management.NotificationBroadcaster;
import javax.management.NotificationBroadcasterSupport;
import javax.management.NotificationEmitter;
import javax.management.NotificationFilter;
import javax.management.NotificationListener;
import javax.management.ObjectName;
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 javax.naming.NamingException;
import test.MX4JTestCase;
/**
* @version $Revision: 1.8 $
*/
public class MBeanServerInvocationHandlerTest extends MX4JTestCase
{
public MBeanServerInvocationHandlerTest(String s)
{
super(s);
}
public void testBadArguments() throws Exception
{
MBeanServer server = newMBeanServer();
ObjectName name = new ObjectName("domain:key=value");
try
{
MBeanServerInvocationHandler.newProxyInstance(null, name, LocalServiceMBean.class, false);
fail("MBeanServerConnection cannot be null");
}
catch (IllegalArgumentException x)
{
}
try
{
MBeanServerInvocationHandler.newProxyInstance(server, null, LocalServiceMBean.class, false);
fail("ObjectName cannot be null");
}
catch (IllegalArgumentException x)
{
}
try
{
MBeanServerInvocationHandler.newProxyInstance(server, name, null, false);
fail("Class cannot be null");
}
catch (IllegalArgumentException x)
{
}
try
{
MBeanServerInvocationHandler.newProxyInstance(server, name, LocalService.class, false);
fail("Class must be an interface");
}
catch (IllegalArgumentException x)
{
}
}
public void testMBeanNotAnEmitter() throws Exception
{
MBeanServer server = newMBeanServer();
ObjectName name = new ObjectName("domain:key=value");
LocalService mbean = new LocalService();
server.registerMBean(mbean, name);
NotificationEmitter emitter = (NotificationEmitter)MBeanServerInvocationHandler.newProxyInstance(server, name, LocalServiceMBean.class, true);
try
{
emitter.addNotificationListener(new TestListener(), null, null);
fail("The MBean is not a NotificationEmitter");
}
catch (IllegalArgumentException x)
{
}
}
public void testDeregisteredMBean() throws Exception
{
MBeanServer server = newMBeanServer();
ObjectName name = new ObjectName("domain:key=value");
LocalService mbean = new LocalService();
server.registerMBean(mbean, name);
// Check what the proxy throws if the ObjectName is removed from the server
LocalServiceMBean proxy = (LocalServiceMBean)MBeanServerInvocationHandler.newProxyInstance(server, name, LocalServiceMBean.class, false);
server.unregisterMBean(name);
try
{
proxy.throwCheckedException();
fail();
}
catch (NamingException x)
{
fail("Expecting an InstanceNotFoundException");
}
catch (UndeclaredThrowableException x)
{
Throwable xx = x.getUndeclaredThrowable();
if (!(xx instanceof InstanceNotFoundException))
fail("Expecting an InstanceNotFoundException");
}
}
public void testCheckedException() throws Exception
{
MBeanServer server = newMBeanServer();
ObjectName name = new ObjectName("domain:key=value");
LocalService mbean = new LocalService();
server.registerMBean(mbean, name);
LocalServiceMBean proxy = (LocalServiceMBean)MBeanServerInvocationHandler.newProxyInstance(server, name, LocalServiceMBean.class, false);
try
{
proxy.throwCheckedException();
fail();
}
catch (NamingException x)
{
}
}
public void testMBeanException() throws Exception
{
MBeanServer server = newMBeanServer();
ObjectName name = new ObjectName("domain:key=value");
LocalService mbean = new LocalService();
server.registerMBean(mbean, name);
LocalServiceMBean proxy = (LocalServiceMBean)MBeanServerInvocationHandler.newProxyInstance(server, name, LocalServiceMBean.class, false);
try
{
proxy.throwMBeanException();
fail();
}
catch (MBeanException x)
{
}
}
public void testRuntimeException() throws Exception
{
MBeanServer server = newMBeanServer();
ObjectName name = new ObjectName("domain:key=value");
LocalService mbean = new LocalService();
server.registerMBean(mbean, name);
LocalServiceMBean proxy = (LocalServiceMBean)MBeanServerInvocationHandler.newProxyInstance(server, name, LocalServiceMBean.class, false);
try
{
proxy.throwNullPointerException();
fail();
}
catch (NullPointerException x)
{
}
}
public void testError() throws Exception
{
MBeanServer server = newMBeanServer();
ObjectName name = new ObjectName("domain:key=value");
LocalService mbean = new LocalService();
server.registerMBean(mbean, name);
LocalServiceMBean proxy = (LocalServiceMBean)MBeanServerInvocationHandler.newProxyInstance(server, name, LocalServiceMBean.class, false);
try
{
proxy.throwError();
fail();
}
catch (Error x)
{
}
}
public void testNotificationBroadcasterProxy() throws Exception
{
MBeanServer server = newMBeanServer();
ObjectName name = new ObjectName("domain:key=value");
LocalBroadcasterService mbean = new LocalBroadcasterService();
server.registerMBean(mbean, name);
// The returned interface should be NotificationEmitter, even though the MBean only implements NotificationBroadcaster
NotificationEmitter proxy = (NotificationEmitter)MBeanServerInvocationHandler.newProxyInstance(server, name, NotificationBroadcaster.class, true);
assertNotNull(proxy);
}
public void testAddNotificationListener() throws Exception
{
MBeanServer server = newMBeanServer();
ObjectName name = new ObjectName("domain:key=value");
LocalEmitterService mbean = new LocalEmitterService();
server.registerMBean(mbean, name);
NotificationEmitter proxy = (NotificationEmitter)MBeanServerInvocationHandler.newProxyInstance(server, name, NotificationEmitter.class, true);
TestListener listener = new TestListener();
proxy.addNotificationListener(listener, null, null);
mbean.test();
if (!listener.received) fail();
}
public void testGetNotificationInfo() throws Exception
{
MBeanServer server = newMBeanServer();
ObjectName name = new ObjectName("domain:key=value");
LocalEmitterService mbean = new LocalEmitterService();
server.registerMBean(mbean, name);
NotificationEmitter proxy = (NotificationEmitter)MBeanServerInvocationHandler.newProxyInstance(server, name, NotificationEmitter.class, true);
MBeanNotificationInfo[] infos = proxy.getNotificationInfo();
if (!infos[0].getDescription().equals(LocalEmitterService.DESC)) fail();
}
public void testSimpleRemoveNotificationListener() throws Exception
{
MBeanServer server = newMBeanServer();
ObjectName name = new ObjectName("domain:key=value");
LocalEmitterService mbean = new LocalEmitterService();
server.registerMBean(mbean, name);
NotificationEmitter proxy = (NotificationEmitter)MBeanServerInvocationHandler.newProxyInstance(server, name, NotificationEmitter.class, true);
TestListener listener = new TestListener();
proxy.addNotificationListener(listener, null, null);
proxy.removeNotificationListener(listener);
mbean.test();
if (listener.received) fail();
}
public void testRemoveNotificationListener() throws Exception
{
MBeanServer server = newMBeanServer();
ObjectName name = new ObjectName("domain:key=value");
LocalEmitterService mbean = new LocalEmitterService();
server.registerMBean(mbean, name);
NotificationEmitter proxy = (NotificationEmitter)MBeanServerInvocationHandler.newProxyInstance(server, name, NotificationEmitter.class, true);
TestListener listener = new TestListener();
TestFilter filter = new TestFilter();
Object handback = new Object();
proxy.addNotificationListener(listener, filter, handback);
proxy.removeNotificationListener(listener, filter, handback);
mbean.test();
if (listener.received) fail();
}
public void testRemoveMultiNotificationListener() throws Exception
{
MBeanServer server = newMBeanServer();
ObjectName name = new ObjectName("domain:key=value");
LocalEmitterService mbean = new LocalEmitterService();
server.registerMBean(mbean, name);
NotificationEmitter proxy = (NotificationEmitter)MBeanServerInvocationHandler.newProxyInstance(server, name, NotificationEmitter.class, true);
TestListener listener1 = new TestListener();
TestFilter filter = new TestFilter();
Object handback = new Object();
proxy.addNotificationListener(listener1, filter, handback);
TestListener listener2 = new TestListener();
proxy.addNotificationListener(listener2, null, null);
mbean.test();
if (!listener1.received) fail();
if (!listener2.received) fail();
try
{
proxy.removeNotificationListener(listener2, filter, handback);
fail("Listener is not registered");
}
catch (ListenerNotFoundException x)
{
}
proxy.removeNotificationListener(listener2, null, null);
listener1.received = false;
listener2.received = false;
mbean.test();
if (!listener1.received) fail();
if (listener2.received) fail();
}
public void testRemoteExceptionWithRemoteInterface() throws Exception
{
MBeanServer server = newMBeanServer();
ObjectName name = new ObjectName("domain:key=value");
LocalService mbean = new LocalService();
server.registerMBean(mbean, name);
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://localhost");
JMXConnectorServer cntorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server);
cntorServer.start();
JMXConnector cntor = JMXConnectorFactory.connect(cntorServer.getAddress());
MBeanServerConnection mbsc = cntor.getMBeanServerConnection();
RemoteService remoteMBean = (RemoteService)MBeanServerInvocationHandler.newProxyInstance(mbsc, name, RemoteService.class, false);
// Close everything to get IOException
cntor.close();
cntorServer.stop();
try
{
remoteMBean.throwCheckedException();
fail("Must not be able to connect");
}
catch (IOException x)
{
}
}
public void testRemoteExceptionWithLocalInterface() throws Exception
{
MBeanServer server = newMBeanServer();
ObjectName name = new ObjectName("domain:key=value");
LocalService mbean = new LocalService();
server.registerMBean(mbean, name);
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://localhost");
JMXConnectorServer cntorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server);
cntorServer.start();
JMXConnector cntor = JMXConnectorFactory.connect(cntorServer.getAddress());
MBeanServerConnection mbsc = cntor.getMBeanServerConnection();
LocalServiceMBean remoteMBean = (LocalServiceMBean)MBeanServerInvocationHandler.newProxyInstance(mbsc, name, LocalServiceMBean.class, false);
// Close everything to get IOException
cntor.close();
cntorServer.stop();
// Now try the local interface
try
{
remoteMBean.throwCheckedException();
fail("Must not be able to connect");
}
catch (UndeclaredThrowableException x)
{
Throwable xx = x.getUndeclaredThrowable();
if (!(xx instanceof IOException)) fail();
}
}
public void testRemoteCheckedException() throws Exception
{
MBeanServer server = newMBeanServer();
ObjectName name = new ObjectName("domain:key=value");
LocalService mbean = new LocalService();
server.registerMBean(mbean, name);
JMXServiceURL url = new JMXServiceURL("service:jmx:rmi://localhost");
JMXConnectorServer cntorServer = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server);
cntorServer.start();
JMXConnector cntor = JMXConnectorFactory.connect(cntorServer.getAddress());
MBeanServerConnection mbsc = cntor.getMBeanServerConnection();
LocalServiceMBean remoteMBean = (LocalServiceMBean)MBeanServerInvocationHandler.newProxyInstance(mbsc, name, LocalServiceMBean.class, false);
try
{
remoteMBean.throwCheckedException();
fail();
}
catch (NamingException x)
{
}
}
public interface LocalServiceMBean
{
public void throwCheckedException() throws NamingException;
public void throwMBeanException() throws MBeanException;
public void throwNullPointerException();
public void throwError();
}
public interface RemoteService
{
public void throwCheckedException() throws NamingException, IOException;
public void throwMBeanException() throws MBeanException, IOException;
public void throwNullPointerException() throws IOException;
public void throwError() throws IOException;
}
public class LocalService implements LocalServiceMBean
{
public void throwCheckedException() throws NamingException
{
throw new NamingException();
}
public void throwMBeanException() throws MBeanException
{
throw new MBeanException(new Exception());
}
public void throwNullPointerException()
{
throw new NullPointerException();
}
public void throwError()
{
throw new Error();
}
}
public class LocalBroadcasterService extends LocalService implements NotificationBroadcaster
{
private NotificationBroadcasterSupport support = new NotificationBroadcasterSupport();
static final String TYPE = "test.notification";
static final String DESC = "Test Notification";
private long sequence;
/**
* @see javax.management.NotificationBroadcaster#addNotificationListener(NotificationListener, NotificationFilter, Object)
*/
public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback)
throws IllegalArgumentException
{
support.addNotificationListener(listener, filter, handback);
}
/**
* @see javax.management.NotificationBroadcaster#getNotificationInfo()
*/
public MBeanNotificationInfo[] getNotificationInfo()
{
return new MBeanNotificationInfo[]{
new MBeanNotificationInfo(new String[]{TYPE}, Notification.class.getName(), DESC),
};
}
/**
* @see javax.management.NotificationBroadcaster#removeNotificationListener(NotificationListener)
*/
public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException
{
support.removeNotificationListener(listener);
}
public void test()
{
Notification notification = new Notification(TYPE, this, ++sequence, System.currentTimeMillis(), DESC);
support.sendNotification(notification);
}
}
public class LocalEmitterService extends LocalService implements NotificationEmitter
{
private NotificationBroadcasterSupport support = new NotificationBroadcasterSupport();
static final String TYPE = "test.notification";
static final String DESC = "Test Notification";
private long sequence;
public void addNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback)
throws IllegalArgumentException
{
support.addNotificationListener(listener, filter, handback);
}
public MBeanNotificationInfo[] getNotificationInfo()
{
return new MBeanNotificationInfo[]{
new MBeanNotificationInfo(new String[]{TYPE}, Notification.class.getName(), DESC),
};
}
public void removeNotificationListener(NotificationListener listener) throws ListenerNotFoundException
{
support.removeNotificationListener(listener);
}
public void removeNotificationListener(NotificationListener listener, NotificationFilter filter, Object handback) throws ListenerNotFoundException
{
support.removeNotificationListener(listener, filter, handback);
}
public void test()
{
Notification notification = new Notification(TYPE, this, ++sequence, System.currentTimeMillis(), DESC);
support.sendNotification(notification);
}
}
public class TestListener implements NotificationListener
{
boolean received = false;
public void handleNotification(Notification notification, Object handback)
{
received = true;
}
}
public class TestFilter implements NotificationFilter
{
public boolean isNotificationEnabled(Notification notification)
{
return notification.getType().equals(LocalEmitterService.TYPE);
}
}
}