/*
* (c) Rob Gordon 2005.
*/
package org.oddjob.jmx.server;
import java.util.ArrayList;
import java.util.List;
import javax.management.JMException;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.Notification;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import junit.framework.TestCase;
import org.apache.commons.beanutils.DynaClass;
import org.apache.commons.beanutils.DynaProperty;
import org.apache.log4j.Level;
import org.apache.log4j.Logger;
import org.oddjob.MockStateful;
import org.oddjob.Structural;
import org.oddjob.arooa.ArooaSession;
import org.oddjob.arooa.registry.MockBeanRegistry;
import org.oddjob.arooa.registry.ServerId;
import org.oddjob.arooa.standard.StandardArooaSession;
import org.oddjob.jmx.SharedConstants;
import org.oddjob.jmx.handlers.StatefulHandlerFactory;
import org.oddjob.jmx.handlers.StructuralHandlerFactory;
import org.oddjob.logging.LogEnabled;
import org.oddjob.logging.LogEvent;
import org.oddjob.state.JobState;
import org.oddjob.state.StateEvent;
import org.oddjob.state.StateListener;
import org.oddjob.structural.StructuralEvent;
import org.oddjob.structural.StructuralListener;
import org.oddjob.tools.OddjobTestHelper;
import org.oddjob.util.MockThreadManager;
/**
* Tests for an OddjobMBeanTest.
*/
public class OddjobMBeanTest extends TestCase {
private static final Logger logger = Logger.getLogger(OddjobMBeanTest.class);
private ServerModel sm;
private int unique;
private class OurHierarchicalRegistry extends MockBeanRegistry {
@Override
public String getIdFor(Object component) {
assertNotNull(component);
return "x" + unique++;
}
}
public void setUp() {
logger.debug("==================== Running " + getName() + " =====================");
ServerInterfaceManagerFactoryImpl imf =
new ServerInterfaceManagerFactoryImpl();
imf.addServerHandlerFactories(
new ResourceFactoryProvider(
new StandardArooaSession()).getHandlerFactories());
sm = new ServerModelImpl(
new ServerId("//test"),
new MockThreadManager(),
imf);
}
private class OurServerSession extends MockServerSession {
ArooaSession session = new StandardArooaSession();
@Override
public ArooaSession getArooaSession() {
return session;
}
}
/**
* Test creating and registering an OddjobMBean.
*/
public void testRegister()
throws Exception {
Runnable myJob = new Runnable() {
public void run() {
}
};
ServerContext serverContext = new ServerContextImpl(
myJob, sm, new OurHierarchicalRegistry());
OddjobMBean ojmb = new OddjobMBean(
myJob, OddjobMBeanFactory.objectName(0),
new OurServerSession(),
serverContext);
ObjectName on = new ObjectName("Oddjob:name=whatever");
MBeanServer mbs = MBeanServerFactory.createMBeanServer();
mbs.registerMBean(ojmb, on);
assertTrue(mbs.isRegistered(on));
mbs.unregisterMBean(on);
}
/**
* Test notifying job state to a NotificationListener.
*/
public void testNotifyState()
throws Exception {
/** Fixture Stateful */
class MyStateful extends MockStateful {
StateListener jsl;
public void addStateListener(StateListener listener) {
jsl = listener;
listener.jobStateChange(new StateEvent(this, JobState.READY, null));
}
public void removeStateListener(StateListener listener) {
}
public void foo() {
jsl.jobStateChange(new StateEvent(this, JobState.COMPLETE, null));
}
};
MyStateful myJob = new MyStateful();
MyNotLis myNotLis = new MyNotLis();
ServerContext serverContext = new ServerContextImpl(
myJob, sm, new OurHierarchicalRegistry());
// create and register MBean.
OddjobMBean ojmb = new OddjobMBean(
myJob, OddjobMBeanFactory.objectName(0),
new OurServerSession(),
serverContext);
ObjectName on = OddjobMBeanFactory.objectName(0);
MBeanServer mbs = MBeanServerFactory.createMBeanServer();
mbs.registerMBean(ojmb, on);
// add notification listener.
mbs.addNotificationListener(on, myNotLis, null, null);
// check null state to begin with
assertEquals("number", 0, myNotLis.getNum());
// change state.
myJob.foo();
//check state
assertEquals("number", 1, myNotLis.getNum());
assertEquals("source", on, myNotLis.getNotification(0).getSource());
assertEquals("type", StatefulHandlerFactory.STATE_CHANGE_NOTIF_TYPE,
myNotLis.getNotification(0).getType());
mbs.unregisterMBean(on);
}
/**
* Test notification of structural change.
*/
public void testNotifyStructure()
throws JMException {
final Object myChild = new Object() {
public String toString() {
return "my child";
}
};
class MyStructural implements Structural {
StructuralListener jsl;
boolean foo = false;
public void addStructuralListener(StructuralListener listener) {
jsl = listener;
}
public void removeStructuralListener(StructuralListener listener) {
}
public void foo() {
if (foo) {
jsl.childRemoved(new StructuralEvent(this, myChild, 0));
}
else {
jsl.childAdded(new StructuralEvent(this, myChild, 0));
}
foo = !foo;
}
};
MyStructural myJob = new MyStructural();
MyNotLis myNotLis = new MyNotLis();
MBeanServer mbs = MBeanServerFactory.createMBeanServer();
OddjobMBeanFactory f = new OddjobMBeanFactory(mbs,
new StandardArooaSession());
ServerContext serverContext = new ServerContextImpl(
myJob, sm, new OurHierarchicalRegistry());
ObjectName on = f.createMBeanFor(myJob, serverContext);
mbs.addNotificationListener(on, myNotLis, null, null);
Notification[] notifications =
(Notification[]) mbs.invoke(on, "structuralSynchronize",
new Object[0], new String[0]);
assertEquals(1, notifications.length);
myJob.foo();
assertEquals("notifications", 1, myNotLis.getNum());
assertEquals("source", on, myNotLis.getNotification(0).getSource());
assertEquals("type", StructuralHandlerFactory.STRUCTURAL_NOTIF_TYPE,
myNotLis.getNotification(0).getType());
myJob.foo();
assertEquals("notifications", 2, myNotLis.getNum());
assertEquals("source", on, myNotLis.getNotification(1).getSource());
assertEquals("type", StructuralHandlerFactory.STRUCTURAL_NOTIF_TYPE,
myNotLis.getNotification(1).getType());
mbs.unregisterMBean(on);
}
public static class MyBean {
public String getFruit() { return "apple"; }
}
/**
* Test DynaClass of a RemoteBean.
*
* @throws Exception
*/
public void testGetDynaClass() throws Exception {
MyBean sampleBean = new MyBean();
ServerContext serverContext = new ServerContextImpl(
sampleBean, sm, new OurHierarchicalRegistry());
OddjobMBean test = new OddjobMBean(
sampleBean, OddjobMBeanFactory.objectName(0),
new OurServerSession(),
serverContext);
DynaClass dc = (DynaClass) test.invoke(
"getDynaClass", new Object[] {}, new String[] {});
assertNotNull(dc);
DynaProperty dp = dc.getDynaProperty("fruit");
assertEquals(String.class, dp.getType());
}
public static class LoggingBean implements LogEnabled {
public String loggerName() {
return "org.oddjob.test.LoggingBean";
}
}
/**
* Test retrieving log events
*
*/
public void testLogging() throws Exception {
LoggingBean bean = new LoggingBean();
((ServerModelImpl) sm).setLogFormat("%m");
ServerContext serverContext = new ServerContextImpl(
bean, sm, new OurHierarchicalRegistry());
OddjobMBean ojmb = new OddjobMBean(
bean, OddjobMBeanFactory.objectName(0),
new OurServerSession(),
serverContext);
Logger testLogger = Logger.getLogger(bean.loggerName());
testLogger.setLevel(Level.DEBUG);
testLogger.info("Test");
LogEvent[] events = (LogEvent[]) ojmb.invoke(SharedConstants.RETRIEVE_LOG_EVENTS_METHOD,
new Object[] {
new Long(-1),
new Integer(10) },
new String[] {
Long.TYPE.getName(), Integer.TYPE.getName() });
assertEquals("num events", 1, events.length);
assertEquals("event 0", "Test", events[0].getMessage());
}
}
/** Fixture listener. */
class MyNotLis implements NotificationListener {
private static final Logger logger = Logger.getLogger(MyNotLis.class);
private class Pair {
private final Notification notification;
private final Object handback;
Pair(Notification notification, Object handback) {
this.notification = notification;
this.handback = handback;
}
}
private final List<Pair> notifications = new ArrayList<Pair>();
public void handleNotification(Notification arg0, Object arg1) {
// check notifications serializable.
try {
if (! (arg0.getSource() instanceof ObjectName)) {
throw new ClassCastException("Doh!");
}
Notification copy = OddjobTestHelper.copy(arg0);
if (! (copy.getSource() instanceof ObjectName)) {
throw new ClassCastException("Doh!");
}
} catch (Exception e) {
logger.error("Notification Listener failed.", e);
throw new RuntimeException(e);
}
Pair p = new Pair(arg0, arg1);
notifications.add(p);
}
int getNum() {
return notifications.size();
}
Notification getNotification(int i) {
Pair p = (Pair) notifications.get(i);
return p.notification;
}
Object getHandback(int i) {
Pair p = (Pair) notifications.get(i);
return p.handback;
}
};