package org.oddjob.jmx.handlers;
import java.util.concurrent.atomic.AtomicReference;
import javax.management.Notification;
import javax.management.NotificationListener;
import org.custommonkey.xmlunit.XMLTestCase;
import org.oddjob.arooa.ArooaParseException;
import org.oddjob.arooa.ConfigurationHandle;
import org.oddjob.arooa.design.DesignInstance;
import org.oddjob.arooa.life.ClassLoaderClassResolver;
import org.oddjob.arooa.parsing.ArooaContext;
import org.oddjob.arooa.parsing.ArooaElement;
import org.oddjob.arooa.parsing.ConfigOwnerEvent;
import org.oddjob.arooa.parsing.ConfigSessionEvent;
import org.oddjob.arooa.parsing.ConfigurationOwner;
import org.oddjob.arooa.parsing.ConfigurationSession;
import org.oddjob.arooa.parsing.CutAndPasteSupport;
import org.oddjob.arooa.parsing.DragContext;
import org.oddjob.arooa.parsing.DragPoint;
import org.oddjob.arooa.parsing.DragTransaction;
import org.oddjob.arooa.parsing.MockConfigurationOwner;
import org.oddjob.arooa.parsing.MockConfigurationSession;
import org.oddjob.arooa.parsing.OwnerStateListener;
import org.oddjob.arooa.parsing.SerializableDesignFactory;
import org.oddjob.arooa.parsing.SessionStateListener;
import org.oddjob.arooa.reflect.ArooaPropertyException;
import org.oddjob.arooa.registry.ChangeHow;
import org.oddjob.arooa.standard.StandardArooaParser;
import org.oddjob.arooa.xml.XMLArooaParser;
import org.oddjob.arooa.xml.XMLConfiguration;
import org.oddjob.jmx.RemoteOperation;
import org.oddjob.jmx.client.ClientHandlerResolver;
import org.oddjob.jmx.client.ClientInterfaceHandlerFactory;
import org.oddjob.jmx.client.MockClientSideToolkit;
import org.oddjob.jmx.server.MockServerSideToolkit;
import org.oddjob.jmx.server.ServerInterfaceHandler;
public class ComponentOwnerHandlerFactoryTest extends XMLTestCase {
private class MySessionLite extends MockConfigurationSession {
Object component;
boolean cut;
int pasteIndex;
String pasteText;
boolean commited;
boolean saved;
@Override
public DragPoint dragPointFor(Object component) {
this.component = component;
return new DragPoint() {
public DragTransaction beginChange(ChangeHow how) {
return new DragTransaction() {
@Override
public void rollback() {
}
@Override
public void commit() {
commited = true;
}
};
}
public boolean supportsCut() {
return true;
}
public boolean supportsPaste() {
return true;
}
public String copy() {
return "apples";
}
public void cut() {
cut = true;
}
public ConfigurationHandle parse(ArooaContext parentContext)
throws ArooaParseException {
throw new RuntimeException("Unexpected.");
}
public void paste(int index, String config)
throws ArooaParseException {
pasteIndex = index;
pasteText = config;
}
};
}
public void save() throws ArooaParseException {
saved = true;
}
@Override
public void addSessionStateListener(SessionStateListener listener) {
}
@Override
public void removeSessionStateListener(SessionStateListener listener) {
}
}
private class OurDesignFactory implements SerializableDesignFactory {
private static final long serialVersionUID = 1L;
@Override
public DesignInstance createDesign(ArooaElement element,
ArooaContext parentContext) throws ArooaPropertyException {
throw new RuntimeException("Unexpected!");
}
}
private class MyComponentOwner extends MockConfigurationOwner {
MySessionLite sess = new MySessionLite();
public ConfigurationSession provideConfigurationSession() {
return sess;
}
@Override
public void addOwnerStateListener(OwnerStateListener listener) {
}
@Override
public void removeOwnerStateListener(OwnerStateListener listener) {
}
@Override
public ArooaElement rootElement() {
return new ArooaElement("test");
}
@Override
public SerializableDesignFactory rootDesignFactory() {
return new OurDesignFactory();
}
}
private class OurServerSideToolkit extends MockServerSideToolkit {
}
private class OurClientToolkit extends MockClientSideToolkit {
ServerInterfaceHandler handler;
@SuppressWarnings("unchecked")
@Override
public <T> T invoke(RemoteOperation<T> remoteOperation, Object... args)
throws Throwable {
return (T) handler.invoke(
remoteOperation,
args);
}
}
public void testBasicInfo() {
ComponentOwnerHandlerFactory test = new ComponentOwnerHandlerFactory();
MyComponentOwner compO = new MyComponentOwner();
ServerInterfaceHandler serverHandler = test.createServerHandler(
compO, new OurServerSideToolkit());
OurClientToolkit clientToolkit = new OurClientToolkit();
clientToolkit.handler = serverHandler;
ClientHandlerResolver<ConfigurationOwner> clientResolver =
test.clientHandlerFactory();
ClientInterfaceHandlerFactory<ConfigurationOwner> cihf =
clientResolver.resolve(new ClassLoaderClassResolver(
getClass().getClassLoader()));
ConfigurationOwner clientHandler = cihf.createClientHandler(
new MockConfigurationOwner(), clientToolkit);
assertEquals(new ArooaElement("test"),
clientHandler.rootElement());
assertEquals(OurDesignFactory.class,
clientHandler.rootDesignFactory().getClass());
}
public void testDragPointOperations() throws ArooaParseException {
ComponentOwnerHandlerFactory test = new ComponentOwnerHandlerFactory();
MyComponentOwner compO = new MyComponentOwner();
ServerInterfaceHandler serverHandler = test.createServerHandler(
compO, new OurServerSideToolkit());
OurClientToolkit clientToolkit = new OurClientToolkit();
clientToolkit.handler = serverHandler;
ConfigurationOwner clientHandler =
new ComponentOwnerHandlerFactory.ClientConfigurationOwnerHandlerFactory(
).createClientHandler(new MockConfigurationOwner(), clientToolkit);
Object ourComponent = new Object();
DragPoint local = clientHandler.provideConfigurationSession().dragPointFor(
ourComponent);
assertTrue(local.supportsCut());
assertTrue(local.supportsPaste());
assertSame(ourComponent, compO.sess.component);
DragTransaction trn = local.beginChange(ChangeHow.FRESH);
local.cut();
trn.commit();
assertTrue(compO.sess.commited);
assertTrue(compO.sess.cut);
assertEquals("apples", local.copy());
local.paste(2, "oranges");
assertEquals(2, compO.sess.pasteIndex);
assertEquals("oranges", compO.sess.pasteText);
clientHandler.provideConfigurationSession().save();
assertTrue(compO.sess.saved);
}
private class OurComponentOwner2 extends MockConfigurationOwner {
DragPoint drag;
ConfigurationHandle handle;
public ConfigurationSession provideConfigurationSession() {
return new MockConfigurationSession() {
@Override
public DragPoint dragPointFor(Object component) {
return drag;
}
@Override
public void save() throws ArooaParseException {
handle.save();
}
@Override
public void addSessionStateListener(
SessionStateListener listener) {
}
@Override
public void removeSessionStateListener(
SessionStateListener listener) {
}
};
}
@Override
public void addOwnerStateListener(OwnerStateListener listener) {
}
@Override
public void removeOwnerStateListener(OwnerStateListener listener) {
}
@Override
public ArooaElement rootElement() {
return new ArooaElement("test");
}
@Override
public SerializableDesignFactory rootDesignFactory() {
return new OurDesignFactory();
}
}
public void testEditOperations() throws Exception {
Object root = new Object();
XMLConfiguration config = new XMLConfiguration("TEST",
"<class id='apples'/>");
final AtomicReference<String > savedXML = new AtomicReference<String>();
config.setSaveHandler(new XMLConfiguration.SaveHandler() {
@Override
public void acceptXML(String xml) {
savedXML.set(xml);
}
});
StandardArooaParser parser = new StandardArooaParser(root);
final ConfigurationHandle handle = parser.parse(config);
DragContext drag = new DragContext(handle.getDocumentContext());
ComponentOwnerHandlerFactory test = new ComponentOwnerHandlerFactory();
OurComponentOwner2 compO = new OurComponentOwner2();
compO.drag = drag;
compO.handle = handle;
ServerInterfaceHandler serverHandler = test.createServerHandler(
compO, new OurServerSideToolkit());
OurClientToolkit clientToolkit = new OurClientToolkit();
clientToolkit.handler = serverHandler;
ConfigurationOwner clientHandler =
new ComponentOwnerHandlerFactory.ClientConfigurationOwnerHandlerFactory(
).createClientHandler(new MockConfigurationOwner(), clientToolkit);
DragPoint local = clientHandler.provideConfigurationSession().dragPointFor(root);
XMLArooaParser parser2 = new XMLArooaParser();
ConfigurationHandle handle2 = parser2.parse(local);
ArooaContext context = handle2.getDocumentContext();
XMLConfiguration replacement = new XMLConfiguration("TEST",
"<class id='oranges'/>");
CutAndPasteSupport.replace(context.getParent(),
context, replacement);
handle2.save();
clientHandler.provideConfigurationSession().save();
String expected = "<class id=\"oranges\"/>" +
System.getProperty("line.separator");
assertXMLEqual(expected,
savedXML.get());
}
private class NullConfigurationOwner extends MockConfigurationOwner {
public ConfigurationSession provideConfigurationSession() {
return null;
}
@Override
public void addOwnerStateListener(OwnerStateListener listener) {
}
@Override
public void removeOwnerStateListener(OwnerStateListener listener) {
}
@Override
public ArooaElement rootElement() {
return new ArooaElement("test");
}
@Override
public SerializableDesignFactory rootDesignFactory() {
return new OurDesignFactory();
}
}
public void testNullConfiguration() {
ComponentOwnerHandlerFactory test = new ComponentOwnerHandlerFactory();
ServerInterfaceHandler serverHandler = test.createServerHandler(
new NullConfigurationOwner(), new OurServerSideToolkit());
OurClientToolkit clientToolkit = new OurClientToolkit();
clientToolkit.handler = serverHandler;
ConfigurationOwner clientHandler =
new ComponentOwnerHandlerFactory.ClientConfigurationOwnerHandlerFactory(
).createClientHandler(new MockConfigurationOwner(), clientToolkit);
ConfigurationSession configurationSession = clientHandler.provideConfigurationSession();
assertNull(configurationSession);
}
private class NullDropPointOwner extends MockConfigurationOwner {
public ConfigurationSession provideConfigurationSession() {
return new MockConfigurationSession() {
public DragPoint dragPointFor(Object component) {
return null;
}
@Override
public void addSessionStateListener(
SessionStateListener listener) {
}
@Override
public void removeSessionStateListener(
SessionStateListener listener) {
}
};
}
@Override
public void addOwnerStateListener(OwnerStateListener listener) {
}
@Override
public void removeOwnerStateListener(OwnerStateListener listener) {
}
@Override
public ArooaElement rootElement() {
return new ArooaElement("test");
}
@Override
public SerializableDesignFactory rootDesignFactory() {
return new OurDesignFactory();
}
}
public void testNullDropPointConfiguration() {
ComponentOwnerHandlerFactory test = new ComponentOwnerHandlerFactory();
ServerInterfaceHandler serverHandler = test.createServerHandler(
new NullDropPointOwner(), new OurServerSideToolkit());
OurClientToolkit clientToolkit = new OurClientToolkit();
clientToolkit.handler = serverHandler;
ConfigurationOwner clientHandler =
new ComponentOwnerHandlerFactory.ClientConfigurationOwnerHandlerFactory(
).createClientHandler(new MockConfigurationOwner(), clientToolkit);
ConfigurationSession configurationSession = clientHandler.provideConfigurationSession();
assertNotNull(configurationSession);
DragPoint dragPoint = configurationSession.dragPointFor(clientHandler);
assertNull(dragPoint);
}
/////////////////////
// Modified Stuff
private class ModifiedNotifySession extends MockConfigurationSession {
SessionStateListener listener;
@Override
public void addSessionStateListener(SessionStateListener listener) {
assertNull(this.listener);
this.listener = listener;
}
@Override
public void removeSessionStateListener(SessionStateListener listener) {
assertEquals(this.listener, listener);
this.listener = null;
}
void modified() {
this.listener.sessionModifed(new ConfigSessionEvent(this));
}
void saved() {
this.listener.sessionSaved(new ConfigSessionEvent(this));
}
}
private class ModifiedOwner extends MockConfigurationOwner {
final ModifiedNotifySession session = new ModifiedNotifySession();
public ConfigurationSession provideConfigurationSession() {
return session;
}
@Override
public void addOwnerStateListener(OwnerStateListener listener) {
}
@Override
public void removeOwnerStateListener(OwnerStateListener listener) {
}
@Override
public ArooaElement rootElement() {
return new ArooaElement("test");
}
@Override
public SerializableDesignFactory rootDesignFactory() {
return new OurDesignFactory();
}
}
private class SessionResultListener implements SessionStateListener {
ConfigSessionEvent event;
boolean modified;
public void sessionModifed(ConfigSessionEvent event) {
this.event = event;
modified = true;
}
public void sessionSaved(ConfigSessionEvent event) {
this.event = event;
modified = false;
}
}
private class ModifiedClientToolkit extends OurClientToolkit {
ModifiedServerSideToolkit serverToolkit;
@Override
public void registerNotificationListener(String eventType,
NotificationListener notificationListener) {
assertEquals(ComponentOwnerHandlerFactory.MODIFIED_NOTIF_TYPE, eventType);
assertNull(serverToolkit.listener);
serverToolkit.listener = notificationListener;
}
@Override
public void removeNotificationListener(String eventType,
NotificationListener notificationListener) {
assertEquals(serverToolkit.listener, notificationListener);
serverToolkit.listener = null;
}
}
private class ModifiedServerSideToolkit extends MockServerSideToolkit {
NotificationListener listener;
@Override
public Notification createNotification(String type) {
assertEquals(ComponentOwnerHandlerFactory.MODIFIED_NOTIF_TYPE, type);
return new Notification(type, this, 0);
}
@Override
public void sendNotification(Notification notification) {
if (listener != null) {
listener.handleNotification(notification, null);
}
}
@Override
public void runSynchronized(Runnable runnable) {
runnable.run();
}
}
public void testSessionStateNotification() {
ComponentOwnerHandlerFactory test = new ComponentOwnerHandlerFactory();
ModifiedOwner owner = new ModifiedOwner();
ModifiedServerSideToolkit serverToolkit = new ModifiedServerSideToolkit();
ServerInterfaceHandler serverHandler = test.createServerHandler(
owner, serverToolkit);
ModifiedClientToolkit clientToolkit = new ModifiedClientToolkit();
clientToolkit.handler = serverHandler;
clientToolkit.serverToolkit = serverToolkit;
ConfigurationOwner clientHandler =
new ComponentOwnerHandlerFactory.ClientConfigurationOwnerHandlerFactory(
).createClientHandler(new MockConfigurationOwner(), clientToolkit);
SessionResultListener results = new SessionResultListener();
clientHandler.provideConfigurationSession(
).addSessionStateListener(results);
assertEquals(false, results.modified);
assertNull(results.event);
owner.session.modified();
assertEquals(true, results.modified);
assertNotNull(results.event);
owner.session.saved();
assertEquals(false, results.modified);
assertNotNull(results.event);
clientHandler.provideConfigurationSession(
).removeSessionStateListener(results);
owner.session.modified();
assertNotNull(results.event);
assertEquals(false, results.modified);
}
private class NotifyingOwner extends MockConfigurationOwner {
OwnerStateListener listener;
ConfigurationSession session;
public ConfigurationSession provideConfigurationSession() {
return session;
}
public void setSession(ConfigurationSession session) {
assertNotNull(session);
this.session = session;
this.listener.sessionChanged(new ConfigOwnerEvent(this,
ConfigOwnerEvent.Change.SESSION_CREATED));
}
@Override
public void addOwnerStateListener(OwnerStateListener listener) {
assertNull(this.listener);
this.listener = listener;
}
@Override
public void removeOwnerStateListener(OwnerStateListener listener) {
assertEquals(this.listener, listener);
this.listener = null;
}
@Override
public ArooaElement rootElement() {
return new ArooaElement("test");
}
@Override
public SerializableDesignFactory rootDesignFactory() {
return new OurDesignFactory();
}
}
private class ResultListener implements OwnerStateListener {
ConfigOwnerEvent event;
int count;
public void sessionChanged(ConfigOwnerEvent event) {
this.event = event;
++count;
}
}
private class NotifyClientToolkit extends OurClientToolkit {
NotifyServerSideToolkit serverToolkit;
@Override
public void registerNotificationListener(String eventType,
NotificationListener notificationListener) {
assertEquals(ComponentOwnerHandlerFactory.CHANGE_NOTIF_TYPE, eventType);
assertNull(serverToolkit.listener);
serverToolkit.listener = notificationListener;
}
@Override
public void removeNotificationListener(String eventType,
NotificationListener notificationListener) {
assertEquals(serverToolkit.listener, notificationListener);
serverToolkit.listener = null;
}
}
private class NotifyServerSideToolkit extends MockServerSideToolkit {
NotificationListener listener;
@Override
public Notification createNotification(String type) {
assertEquals(ComponentOwnerHandlerFactory.CHANGE_NOTIF_TYPE, type);
return new Notification(type, this, 0);
}
@Override
public void sendNotification(Notification notification) {
if (listener != null) {
listener.handleNotification(notification, null);
}
}
@Override
public void runSynchronized(Runnable runnable) {
runnable.run();
}
}
public void testSessionChangeNotification() {
ComponentOwnerHandlerFactory test = new ComponentOwnerHandlerFactory();
NotifyingOwner owner = new NotifyingOwner();
NotifyServerSideToolkit serverToolkit = new NotifyServerSideToolkit();
ServerInterfaceHandler serverHandler = test.createServerHandler(
owner, serverToolkit);
NotifyClientToolkit clientToolkit = new NotifyClientToolkit();
clientToolkit.handler = serverHandler;
clientToolkit.serverToolkit = serverToolkit;
ConfigurationOwner clientProxy = new MockConfigurationOwner();
ConfigurationOwner clientHandler =
new ComponentOwnerHandlerFactory.ClientConfigurationOwnerHandlerFactory(
).createClientHandler(clientProxy, clientToolkit);
ResultListener results = new ResultListener();
clientHandler.addOwnerStateListener(results);
assertEquals(0, results.count);
ConfigurationSession clientSession = clientHandler.provideConfigurationSession();
assertNull(clientSession);
owner.setSession(new ModifiedNotifySession());
assertEquals(clientProxy, results.event.getSource());
assertEquals(1, results.count);
clientSession = clientHandler.provideConfigurationSession();
assertNotNull(clientSession);
clientHandler.removeOwnerStateListener(results);
owner.setSession(new ModifiedNotifySession());
assertEquals(1, results.count);
}
}