package org.jboss.cache.mgmt;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
import org.jboss.cache.Fqn;
import org.jboss.cache.PropertyConfigurator;
import org.jboss.cache.TreeCache;
import org.jboss.cache.TreeCacheListener;
import org.jboss.cache.interceptors.CacheMgmtInterceptor;
import org.jboss.cache.loader.CacheLoader;
import org.jboss.cache.xml.XmlHelper;
import org.w3c.dom.Element;
import org.jgroups.View;
import javax.management.MBeanServer;
import javax.management.MBeanServerFactory;
import javax.management.Notification;
import javax.management.NotificationListener;
import javax.management.ObjectName;
import java.util.HashMap;
import java.util.List;
import java.util.ArrayList;
/**
* Functional tests for CacheMgmtInterceptor broadcast of cache event notifications
* @author Jerry Gauthier
* @version $Id: NotificationTest.java 2068 2006-06-15 23:33:56Z msurtani $
*/
public class NotificationTest extends TestCase
{
private static final String MGMT_SERVICE = ",treecache-interceptor=CacheMgmtInterceptor";
private static final String CLUSTER_NAME = "NotificationTestCluster";
private static final String CAPITAL = "capital";
private static final String CURRENCY = "currency";
private static final String POPULATION = "population";
private static final String EUROPE_NODE = "Europe";
private boolean m_cacheStarted = false;
private boolean m_cacheStopped = false;
private boolean m_nodeCreated = false;
private boolean m_nodeEvicted = false;
private boolean m_nodeLoaded = false;
private boolean m_nodeModified = false;
private boolean m_nodeRemoved = false;
private boolean m_nodeVisited = false;
private boolean m_viewChange = false;
private boolean m_nodeActivatePre = false;
private boolean m_nodeActivatePost = false;
private boolean m_nodeEvictPre = false;
private boolean m_nodeEvictPost = false;
private boolean m_nodeModifyPre = false;
private boolean m_nodeModifyPost = false;
private boolean m_nodePassivatePre = false;
private boolean m_nodePassivatePost = false;
private boolean m_nodeRemovePre = false;
private boolean m_nodeRemovePost = false;
private MBeanServer m_server;
TreeCache cache = null;
boolean optimistic = false;
protected void setUp() throws Exception
{
super.setUp();
m_server = MBeanServerFactory.createMBeanServer();
cache = createCache(CLUSTER_NAME);
}
protected void tearDown() throws Exception
{
super.tearDown();
if(cache != null)
{
// stop the cache before the listener is unregistered
//cache1.stopService();
cache.destroyService();
cache = null;
}
}
public void testNotifications() throws Exception
{
assertNotNull("MBeanServer is null.", m_server);
assertNotNull("Cache is null.", cache);
MyListener listener = new MyListener();
ObjectName mgmt = new ObjectName(cache.getServiceName()+MGMT_SERVICE);
m_server.addNotificationListener(mgmt, listener, null, null);
// start the cache after registering listener - this will trigger CacheStarted
// since cache is defined with cluster, thiswill also trigger ViewChange
cache.startService();
// add a node - this will trigger NodeCreated, NodeModify(pre/post) and NodeModified
HashMap albania = new HashMap(4);
albania.put(CAPITAL, "Tirana");
albania.put(CURRENCY, "Lek");
cache.put("Europe/Albania", albania);
// modify a node - this will trigger NodeModified and NodeModify(pre/post)
cache.put("Europe/Albania", POPULATION, new Integer(3563112));
// retrieve an attribute - this will trigger NodeVisited
Fqn key = Fqn.fromString("Europe/Albania");
assertNotNull("Retrieval error: expected to retrieve " + CURRENCY + " for " + key, cache.get(key, CURRENCY));
// evict the node - this will trigger NodePassivate, NodeEvicted and NodeEvict(pre/post)
cache.evict(key);
// retrieve the attribute again - this will trigger NodeVisited and NodeActivate
assertNotNull("Retrieval error: expected to retrieve " + CURRENCY + " for " + key, cache.get(key, CURRENCY));
// remove the node - this will trigger NodeRemoved and NodeRemove(pre/post)
cache.remove(key);
// clean up before stopping the cache
CacheLoader cl = cache.getCacheLoader();
cl.remove(Fqn.fromString(EUROPE_NODE));
// stop the cache
cache.stopService();
m_server.removeNotificationListener(mgmt, listener);
// run the tests
assertTrue("Expected CacheStarted notification", m_cacheStarted);
assertTrue("Expected CacheStopped notification", m_cacheStopped);
assertTrue("Expected NodeCreated notification", m_nodeCreated);
assertTrue("Expected NodeEvicted notification", m_nodeEvicted);
assertTrue("Expected NodeLoaded notification", m_nodeLoaded);
assertTrue("Expected NodeModified notification", m_nodeModified);
assertTrue("Expected NodeRemoved notification", m_nodeRemoved);
assertTrue("Expected NodeVisited notification", m_nodeVisited);
// currently only pre=false notifications are emitted by ActivationInterceptor
//assertTrue("Expected NodeActivate pre=true notification", m_nodeActivatePre);
assertTrue("Expected NodeActivate pre=false notification", m_nodeActivatePost);
assertTrue("Expected NodeEvict pre=true notification", m_nodeEvictPre);
assertTrue("Expected NodeEvict pre=false notification", m_nodeEvictPost);
assertTrue("Expected NodeModify pre=true notification", m_nodeModifyPre);
assertTrue("Expected NodeModify pre=false notification", m_nodeModifyPost);
assertTrue("Expected NodePassivate pre=true notification", m_nodePassivatePre);
// currently only pre=true notifications are emitted by PassivationInterceptor
//assertTrue("Expected NodePassivate pre=false notification", m_nodePassivatePost);
assertTrue("Expected NodeRemove pre=true notification", m_nodeRemovePre);
assertTrue("Expected NodeRemove pre=false notification", m_nodeRemovePost);
assertTrue("Expected NodeEvict pre=true notification", m_nodeEvictPre);
assertTrue("Expected ViewChange notification", m_viewChange);
}
public void testModifyNotification() throws Exception
{
final List notifications = new ArrayList();
assertNotNull("MBeanServer is null.", m_server);
assertNotNull("Cache is null.", cache);
TreeCacheListener listener = new TreeCacheListener()
{
public void nodeCreated(Fqn fqn)
{
notifications.add("Created " + fqn);
}
public void nodeRemoved(Fqn fqn)
{
notifications.add("Removed " + fqn);
}
public void nodeLoaded(Fqn fqn)
{
notifications.add("Loaded " + fqn);
}
public void nodeEvicted(Fqn fqn)
{
notifications.add("Evicted " + fqn);
}
public void nodeModified(Fqn fqn)
{
notifications.add("Modified " + fqn);
}
public void nodeVisited(Fqn fqn)
{
notifications.add("Visited " + fqn);
}
public void cacheStarted(TreeCache cache)
{
notifications.add("Started");
}
public void cacheStopped(TreeCache cache)
{
notifications.add("Stopped");
}
public void viewChange(View new_view) // might be MergeView after merging
{
}
};
cache.addTreeCacheListener(listener);
cache.startService();
cache.put("/hello", "k", "v");
assertEquals("Started", notifications.remove(0));
assertEquals("Created /hello", notifications.remove(0));
assertEquals("Modified /hello", notifications.remove(0));
assertEquals(0, notifications.size());
cache.get("/hello", "k");
assertEquals("Visited /hello", notifications.remove(0));
assertEquals(0, notifications.size());
cache.put("/hello", "k", "v2");
assertEquals("Modified /hello", notifications.remove(0));
assertEquals(0, notifications.size());
}
private TreeCache createCache(String clusterName) throws Exception
{
TreeCache cache = new TreeCache();
PropertyConfigurator config=new PropertyConfigurator();
config.configure(cache, "META-INF/replSync-service.xml");
cache.setCacheMode(TreeCache.REPL_SYNC);
cache.setCacheLoaderConfiguration(getCacheLoaderConfig("location="+getTempDir()));
cache.setUseInterceptorMbeans(true);
cache.setClusterName(clusterName);
if (optimistic)
{
cache.setTransactionManagerLookupClass("org.jboss.cache.DummyTransactionManagerLookup");
cache.setNodeLockingScheme("OPTIMISTIC");
}
cache.createService();
// start the cache after the listener has been registered
//cache.startService();
return cache;
}
private String getTempDir()
{
return System.getProperty("java.io.tempdir", "/tmp");
}
private boolean getPre(Object data)
{
assertNotNull("User data is null, should be Object[]", data);
assertTrue("User data is " + data.getClass().getName() + ", should be Object[]", data instanceof Object[]);
Object[] parms = (Object[])data;
assertTrue("Parameter is " + parms[1].getClass().getName() + ", should be Boolean", parms[1] instanceof Boolean);
Boolean pre = (Boolean)parms[1];
return pre.booleanValue();
}
private Element getCacheLoaderConfig(String properties) throws Exception
{
String xml = "<config>\n" +
"<passivation>true</passivation>\n" +
"<preload></preload>\n" +
"<shared>true</shared>\n" +
"<cacheloader>\n" +
"<class>org.jboss.cache.loader.FileCacheLoader</class>\n" +
"<properties>" + properties + "</properties>\n" +
"<async>false</async>\n" +
"<fetchPersistentState>false</fetchPersistentState>\n" +
"<ignoreModifications>false</ignoreModifications>\n" +
"</cacheloader>\n" +
"</config>";
return XmlHelper.stringToElement(xml);
}
public static Test suite()
{
return new TestSuite(NotificationTest.class);
}
private class MyListener implements NotificationListener
{
public void handleNotification(Notification notification, Object handback)
{
String type = notification.getType();
Object userData = notification.getUserData();
if (type.equals(CacheMgmtInterceptor.NOTIF_CACHE_STARTED))
m_cacheStarted = true;
else if (type.equals(CacheMgmtInterceptor.NOTIF_CACHE_STOPPED))
m_cacheStopped = true;
else if (type.equals(CacheMgmtInterceptor.NOTIF_NODE_CREATED))
m_nodeCreated = true;
else if (type.equals(CacheMgmtInterceptor.NOTIF_NODE_EVICTED))
m_nodeEvicted = true;
else if (type.equals(CacheMgmtInterceptor.NOTIF_NODE_LOADED))
m_nodeLoaded = true;
else if (type.equals(CacheMgmtInterceptor.NOTIF_NODE_MODIFIED))
m_nodeModified = true;
else if (type.equals(CacheMgmtInterceptor.NOTIF_NODE_REMOVED))
m_nodeRemoved = true;
else if (type.equals(CacheMgmtInterceptor.NOTIF_NODE_VISITED))
m_nodeVisited = true;
else if (type.equals(CacheMgmtInterceptor.NOTIF_VIEW_CHANGE))
m_viewChange = true;
else if (type.equals(CacheMgmtInterceptor.NOTIF_NODE_ACTIVATE))
if (getPre(userData))
m_nodeActivatePre = true;
else
m_nodeActivatePost = true;
else if (type.equals(CacheMgmtInterceptor.NOTIF_NODE_EVICT))
if (getPre(userData))
m_nodeEvictPre = true;
else
m_nodeEvictPost = true;
else if (type.equals(CacheMgmtInterceptor.NOTIF_NODE_MODIFY))
if (getPre(userData))
m_nodeModifyPre = true;
else
m_nodeModifyPost = true;
else if (type.equals(CacheMgmtInterceptor.NOTIF_NODE_PASSIVATE))
if (getPre(userData))
m_nodePassivatePre = true;
else
m_nodePassivatePost = true;
else if (type.equals(CacheMgmtInterceptor.NOTIF_NODE_REMOVE))
if (getPre(userData))
m_nodeRemovePre = true;
else
m_nodeRemovePost = true;
}
}
}