1 |
| package org.jboss.cache.jmx; |
2 |
| |
3 |
| import junit.framework.AssertionFailedError; |
4 |
| import junit.framework.TestCase; |
5 |
| import org.jboss.cache.CacheImpl; |
6 |
| import org.jboss.cache.DefaultCacheFactory; |
7 |
| import org.jboss.cache.Fqn; |
8 |
| import org.jboss.cache.config.CacheLoaderConfig; |
9 |
| import org.jboss.cache.config.Configuration; |
10 |
| import org.jboss.cache.config.Configuration.CacheMode; |
11 |
| import org.jboss.cache.factories.UnitTestCacheConfigurationFactory; |
12 |
| import org.jboss.cache.factories.XmlConfigurationParser; |
13 |
| import org.jboss.cache.loader.CacheLoader; |
14 |
| import org.jboss.cache.xml.XmlHelper; |
15 |
| import org.w3c.dom.Element; |
16 |
| |
17 |
| import javax.management.MBeanServer; |
18 |
| import javax.management.MBeanServerFactory; |
19 |
| import javax.management.Notification; |
20 |
| import javax.management.NotificationListener; |
21 |
| import javax.management.ObjectName; |
22 |
| import java.util.EnumSet; |
23 |
| import java.util.HashMap; |
24 |
| |
25 |
| |
26 |
| |
27 |
| |
28 |
| |
29 |
| |
30 |
| |
31 |
| public class NotificationTest extends TestCase |
32 |
| { |
33 |
| protected static final String CLUSTER_NAME = "NotificationTestCluster"; |
34 |
| |
35 |
| protected static final String CAPITAL = "capital"; |
36 |
| protected static final String CURRENCY = "currency"; |
37 |
| protected static final String POPULATION = "population"; |
38 |
| protected static final String EUROPE_NODE = "Europe"; |
39 |
| |
40 |
| public enum Type |
41 |
| { |
42 |
| STARTED, STOPPED, PRECREATE, POSTCREATE, PREEVICT, POSTEVICT, |
43 |
| PRELOAD, POSTLOAD, PREREMOVE, POSTREMOVE, PREVISIT, POSTVISIT, |
44 |
| PREMODIFY, POSTMODIFY, PREACTIVATE, POSTACTIVATE, PREPASSIVATE, |
45 |
| POSTPASSIVATE, VIEWCHANGE |
46 |
| } |
47 |
| |
48 |
| protected MBeanServer m_server; |
49 |
| protected EnumSet<Type> events = EnumSet.noneOf(Type.class); |
50 |
| |
51 |
| protected CacheImpl cache = null; |
52 |
| protected boolean optimistic = false; |
53 |
| |
54 |
16
| protected void setUp() throws Exception
|
55 |
| { |
56 |
16
| super.setUp();
|
57 |
16
| m_server = MBeanServerFactory.createMBeanServer();
|
58 |
| |
59 |
16
| Object cacheMBean = createCacheAndJmxWrapper();
|
60 |
| |
61 |
| |
62 |
16
| ObjectName mgmt = getWrapperObjectName();
|
63 |
| |
64 |
16
| m_server.registerMBean(cacheMBean, mgmt);
|
65 |
| } |
66 |
| |
67 |
8
| protected Object createCacheAndJmxWrapper() throws Exception
|
68 |
| { |
69 |
8
| cache = createCache(CLUSTER_NAME);
|
70 |
8
| return new CacheJmxWrapper(cache);
|
71 |
| } |
72 |
| |
73 |
16
| protected void tearDown() throws Exception
|
74 |
| { |
75 |
16
| try
|
76 |
| { |
77 |
16
| super.tearDown();
|
78 |
| |
79 |
16
| cleanup();
|
80 |
| } |
81 |
| finally |
82 |
| { |
83 |
| |
84 |
16
| if (m_server != null)
|
85 |
16
| MBeanServerFactory.releaseMBeanServer(m_server);
|
86 |
| } |
87 |
| } |
88 |
| |
89 |
20
| protected void cleanup() throws Exception
|
90 |
| { |
91 |
20
| events.clear();
|
92 |
| |
93 |
20
| destroyCache();
|
94 |
| |
95 |
20
| if (m_server != null)
|
96 |
| { |
97 |
20
| ObjectName mgmt = getWrapperObjectName();
|
98 |
20
| if (m_server.isRegistered(mgmt))
|
99 |
20
| m_server.unregisterMBean(mgmt);
|
100 |
| } |
101 |
| } |
102 |
| |
103 |
10
| protected void destroyCache()
|
104 |
| { |
105 |
10
| if (cache != null)
|
106 |
| { |
107 |
| |
108 |
| |
109 |
10
| cache.destroy();
|
110 |
10
| cache = null;
|
111 |
| } |
112 |
| } |
113 |
| |
114 |
26
| protected ObjectName getWrapperObjectName() throws Exception
|
115 |
| { |
116 |
26
| return new ObjectName(JmxUtil.PREFIX + CLUSTER_NAME);
|
117 |
| } |
118 |
| |
119 |
4
| public void testNotifications() throws Exception
|
120 |
| { |
121 |
4
| assertNotNull("MBeanServer is null.", m_server);
|
122 |
4
| assertNotNull("Cache is null.", cache);
|
123 |
| |
124 |
4
| ObjectName mgmt = getWrapperObjectName();
|
125 |
4
| MyListener listener = new MyListener(mgmt);
|
126 |
| |
127 |
| |
128 |
4
| m_server.addNotificationListener(mgmt, listener, null, null);
|
129 |
| |
130 |
| |
131 |
| |
132 |
4
| cache.start();
|
133 |
| |
134 |
| |
135 |
4
| HashMap albania = new HashMap(4);
|
136 |
4
| albania.put(CAPITAL, "Tirana");
|
137 |
4
| albania.put(CURRENCY, "Lek");
|
138 |
4
| cache.put("Europe/Albania", albania);
|
139 |
| |
140 |
| |
141 |
4
| cache.put("Europe/Albania", POPULATION, 3563112);
|
142 |
| |
143 |
| |
144 |
4
| Fqn key = Fqn.fromString("Europe/Albania");
|
145 |
4
| assertNotNull("Retrieval error: expected to retrieve " + CURRENCY + " for " + key, cache.get(key, CURRENCY));
|
146 |
| |
147 |
| |
148 |
4
| cache.evict(key);
|
149 |
| |
150 |
| |
151 |
4
| assertNotNull("Retrieval error: expected to retrieve " + CURRENCY + " for " + key, cache.get(key, CURRENCY));
|
152 |
| |
153 |
| |
154 |
4
| cache.remove(key);
|
155 |
| |
156 |
| |
157 |
4
| CacheLoader cl = cache.getCacheLoader();
|
158 |
4
| cl.remove(Fqn.fromString(EUROPE_NODE));
|
159 |
| |
160 |
| |
161 |
4
| cache.stop();
|
162 |
4
| m_server.removeNotificationListener(mgmt, listener);
|
163 |
| |
164 |
| |
165 |
4
| assertTrue("Expected CacheStarted notification", events.contains(Type.STARTED));
|
166 |
4
| assertTrue("Expected CacheStopped notification", events.contains(Type.STOPPED));
|
167 |
4
| assertTrue("Expected NodeCreated notification", events.contains(Type.PRECREATE));
|
168 |
4
| assertTrue("Expected NodeCreated notification", events.contains(Type.POSTCREATE));
|
169 |
4
| assertTrue("Expected NodeEvicted notification", events.contains(Type.PREEVICT));
|
170 |
4
| assertTrue("Expected NodeEvicted notification", events.contains(Type.POSTEVICT));
|
171 |
4
| assertTrue("Expected NodeLoaded notification", events.contains(Type.PRELOAD));
|
172 |
4
| assertTrue("Expected NodeLoaded notification", events.contains(Type.POSTLOAD));
|
173 |
4
| assertTrue("Expected NodeVisited notification", events.contains(Type.PREVISIT));
|
174 |
4
| assertTrue("Expected NodeVisited notification", events.contains(Type.POSTVISIT));
|
175 |
4
| assertTrue("Expected NodeActivated notification", events.contains(Type.PREACTIVATE));
|
176 |
4
| assertTrue("Expected NodeActivated notification", events.contains(Type.POSTACTIVATE));
|
177 |
4
| assertTrue("Expected NodeModified notification", events.contains(Type.PREMODIFY));
|
178 |
4
| assertTrue("Expected NodeModified notification", events.contains(Type.POSTMODIFY));
|
179 |
4
| assertTrue("Expected NodePassivated notification", events.contains(Type.PREPASSIVATE));
|
180 |
4
| assertTrue("Expected NodePassivated notification", events.contains(Type.POSTPASSIVATE));
|
181 |
4
| assertTrue("Expected NodeRemoved notification", events.contains(Type.PREREMOVE));
|
182 |
4
| assertTrue("Expected NodeRemoved notification", events.contains(Type.POSTREMOVE));
|
183 |
4
| assertTrue("Expected ViewChange notification", events.contains(Type.VIEWCHANGE));
|
184 |
4
| validateHealthyListener(listener);
|
185 |
| } |
186 |
| |
187 |
4
| public void testEarlyRegistration() throws Exception
|
188 |
| { |
189 |
| |
190 |
4
| cleanup();
|
191 |
| |
192 |
4
| CacheJmxWrapper wrapper = new CacheJmxWrapper();
|
193 |
4
| ObjectName mgmt = getWrapperObjectName();
|
194 |
4
| m_server.registerMBean(wrapper, mgmt);
|
195 |
4
| MyListener listener = new MyListener(mgmt);
|
196 |
4
| m_server.addNotificationListener(mgmt, listener, null, null);
|
197 |
| |
198 |
4
| cache = createCache(CLUSTER_NAME);
|
199 |
4
| wrapper.setCache(cache);
|
200 |
4
| cache.start();
|
201 |
4
| try
|
202 |
| { |
203 |
4
| assertTrue("Expected CacheStarted notification", events.contains(Type.STARTED));
|
204 |
4
| validateHealthyListener(listener);
|
205 |
| } |
206 |
| finally |
207 |
| { |
208 |
4
| cache.stop();
|
209 |
| } |
210 |
| } |
211 |
| |
212 |
4
| public void testLateRegistration() throws Exception
|
213 |
| { |
214 |
4
| assertNotNull("MBeanServer is null.", m_server);
|
215 |
4
| assertNotNull("Cache is null.", cache);
|
216 |
| |
217 |
| |
218 |
4
| cache.start();
|
219 |
| |
220 |
4
| try
|
221 |
| { |
222 |
4
| ObjectName mgmt = getWrapperObjectName();
|
223 |
4
| MyListener listener = new MyListener(mgmt);
|
224 |
| |
225 |
| |
226 |
4
| m_server.addNotificationListener(mgmt, listener, null, null);
|
227 |
| |
228 |
| |
229 |
4
| HashMap albania = new HashMap(4);
|
230 |
4
| albania.put(CAPITAL, "Tirana");
|
231 |
4
| albania.put(CURRENCY, "Lek");
|
232 |
4
| cache.put("Europe/Albania", albania);
|
233 |
| |
234 |
| |
235 |
4
| assertTrue("Expected NodeModified notification", events.contains(Type.PREMODIFY));
|
236 |
4
| assertTrue("Expected NodeModified notification", events.contains(Type.POSTMODIFY));
|
237 |
4
| validateHealthyListener(listener);
|
238 |
| } |
239 |
| finally |
240 |
| { |
241 |
4
| cache.stop();
|
242 |
| } |
243 |
| } |
244 |
| |
245 |
4
| public void testListenerRemoval() throws Exception
|
246 |
| { |
247 |
4
| assertNotNull("MBeanServer is null.", m_server);
|
248 |
4
| assertNotNull("Cache is null.", cache);
|
249 |
| |
250 |
4
| ObjectName mgmt = getWrapperObjectName();
|
251 |
4
| MyListener listener = new MyListener(mgmt);
|
252 |
| |
253 |
4
| m_server.addNotificationListener(mgmt, listener, null, null);
|
254 |
| |
255 |
| |
256 |
| |
257 |
4
| cache.start();
|
258 |
4
| boolean ok = false;
|
259 |
4
| try
|
260 |
| { |
261 |
4
| assertTrue("Expected CacheStarted notification", events.contains(Type.STARTED));
|
262 |
| |
263 |
4
| m_server.removeNotificationListener(mgmt, listener);
|
264 |
4
| ok = true;
|
265 |
| } |
266 |
| finally |
267 |
| { |
268 |
4
| cache.stop();
|
269 |
4
| if (ok)
|
270 |
| { |
271 |
4
| assertFalse("Expected no CacheStopped notification", events.contains(Type.STOPPED));
|
272 |
4
| validateHealthyListener(listener);
|
273 |
| } |
274 |
| } |
275 |
| } |
276 |
| |
277 |
12
| private CacheImpl createCache(String clusterName) throws Exception
|
278 |
| { |
279 |
12
| Configuration config = createConfiguration(clusterName);
|
280 |
12
| CacheImpl cache = (CacheImpl) DefaultCacheFactory.getInstance().createCache(config, false);
|
281 |
| |
282 |
12
| cache.create();
|
283 |
| |
284 |
| |
285 |
12
| return cache;
|
286 |
| } |
287 |
| |
288 |
20
| protected Configuration createConfiguration(String clusterName) throws Exception
|
289 |
| { |
290 |
20
| Configuration config = UnitTestCacheConfigurationFactory.createConfiguration(CacheMode.REPL_SYNC);
|
291 |
20
| config.setCacheMode(Configuration.CacheMode.REPL_SYNC);
|
292 |
20
| config.setCacheLoaderConfig(getCacheLoaderConfig("location=" + getTempDir()));
|
293 |
20
| config.setExposeManagementStatistics(true);
|
294 |
20
| config.setClusterName(clusterName);
|
295 |
20
| if (optimistic)
|
296 |
| { |
297 |
10
| config.setTransactionManagerLookupClass("org.jboss.cache.transaction.DummyTransactionManagerLookup");
|
298 |
10
| config.setNodeLockingScheme("OPTIMISTIC");
|
299 |
| } |
300 |
| |
301 |
20
| return config;
|
302 |
| } |
303 |
| |
304 |
20
| private static String getTempDir()
|
305 |
| { |
306 |
20
| return System.getProperty("java.io.tempdir", "/tmp");
|
307 |
| } |
308 |
| |
309 |
124
| private static boolean getPre(Object data)
|
310 |
| { |
311 |
124
| assertNotNull("User data is null, should be Object[]", data);
|
312 |
124
| assertTrue("User data is " + data.getClass().getName() + ", should be Object[]", data instanceof Object[]);
|
313 |
| |
314 |
124
| Object[] parms = (Object[]) data;
|
315 |
124
| assertTrue("Parameter is " + parms[1].getClass().getName() + ", should be Boolean", parms[1] instanceof Boolean);
|
316 |
124
| return (Boolean) parms[1];
|
317 |
| } |
318 |
| |
319 |
20
| protected static CacheLoaderConfig getCacheLoaderConfig(String properties) throws Exception
|
320 |
| { |
321 |
20
| String xml = "<config>\n" +
|
322 |
| "<passivation>true</passivation>\n" + |
323 |
| "<preload></preload>\n" + |
324 |
| "<shared>true</shared>\n" + |
325 |
| "<cacheloader>\n" + |
326 |
| "<class>org.jboss.cache.loader.FileCacheLoader</class>\n" + |
327 |
| "<properties>" + properties + "</properties>\n" + |
328 |
| "<async>false</async>\n" + |
329 |
| "<fetchPersistentState>false</fetchPersistentState>\n" + |
330 |
| "<ignoreModifications>false</ignoreModifications>\n" + |
331 |
| "</cacheloader>\n" + |
332 |
| "</config>"; |
333 |
20
| Element element = XmlHelper.stringToElement(xml);
|
334 |
20
| return XmlConfigurationParser.parseCacheLoaderConfig(element);
|
335 |
| } |
336 |
| |
337 |
16
| private static void validateHealthyListener(MyListener listener)
|
338 |
| { |
339 |
16
| if (listener.failure != null)
|
340 |
0
| throw listener.failure;
|
341 |
16
| if (listener.exception != null)
|
342 |
0
| throw listener.exception;
|
343 |
| } |
344 |
| |
345 |
| private class MyListener implements NotificationListener |
346 |
| { |
347 |
| private RuntimeException exception; |
348 |
| private AssertionFailedError failure; |
349 |
| private final String emitterObjectName; |
350 |
| |
351 |
16
| MyListener(ObjectName emitter)
|
352 |
| { |
353 |
16
| this.emitterObjectName = emitter.getCanonicalName();
|
354 |
| } |
355 |
| |
356 |
160
| public void handleNotification(Notification notification, Object handback)
|
357 |
| { |
358 |
160
| try
|
359 |
| { |
360 |
160
| String type = notification.getType();
|
361 |
160
| Object userData = notification.getUserData();
|
362 |
| |
363 |
160
| if (type.equals(CacheNotificationBroadcaster.NOTIF_CACHE_STARTED))
|
364 |
| { |
365 |
12
| events.add(Type.STARTED);
|
366 |
12
| assertEquals("Correct object name in start notification", emitterObjectName, userData);
|
367 |
| } |
368 |
148
| else if (type.equals(CacheNotificationBroadcaster.NOTIF_CACHE_STOPPED))
|
369 |
| { |
370 |
12
| events.add(Type.STOPPED);
|
371 |
12
| assertEquals("Correct object name in stop notification", emitterObjectName, userData);
|
372 |
| } |
373 |
136
| else if (type.equals(CacheNotificationBroadcaster.NOTIF_NODE_CREATED))
|
374 |
| { |
375 |
40
| if (getPre(userData))
|
376 |
| { |
377 |
20
| events.add(Type.PRECREATE);
|
378 |
| } |
379 |
| else |
380 |
| { |
381 |
20
| events.add(Type.POSTCREATE);
|
382 |
| } |
383 |
| } |
384 |
96
| else if (type.equals(CacheNotificationBroadcaster.NOTIF_NODE_EVICTED))
|
385 |
| { |
386 |
8
| if (getPre(userData))
|
387 |
| { |
388 |
4
| events.add(Type.PREEVICT);
|
389 |
| } |
390 |
| else |
391 |
| { |
392 |
4
| events.add(Type.POSTEVICT);
|
393 |
| } |
394 |
| } |
395 |
88
| else if (type.equals(CacheNotificationBroadcaster.NOTIF_NODE_LOADED))
|
396 |
| { |
397 |
8
| if (getPre(userData))
|
398 |
| { |
399 |
4
| events.add(Type.PRELOAD);
|
400 |
| } |
401 |
| else |
402 |
| { |
403 |
4
| events.add(Type.POSTLOAD);
|
404 |
| } |
405 |
| } |
406 |
80
| else if (type.equals(CacheNotificationBroadcaster.NOTIF_NODE_REMOVED))
|
407 |
| { |
408 |
8
| if (getPre(userData))
|
409 |
| { |
410 |
4
| events.add(Type.PREREMOVE);
|
411 |
| } |
412 |
| else |
413 |
| { |
414 |
4
| events.add(Type.POSTREMOVE);
|
415 |
| } |
416 |
| } |
417 |
72
| else if (type.equals(CacheNotificationBroadcaster.NOTIF_NODE_VISITED))
|
418 |
| { |
419 |
16
| if (getPre(userData))
|
420 |
| { |
421 |
8
| events.add(Type.PREVISIT);
|
422 |
| } |
423 |
| else |
424 |
| { |
425 |
8
| events.add(Type.POSTVISIT);
|
426 |
| } |
427 |
| } |
428 |
56
| else if (type.equals(CacheNotificationBroadcaster.NOTIF_VIEW_CHANGED))
|
429 |
| { |
430 |
12
| events.add(Type.VIEWCHANGE);
|
431 |
| } |
432 |
44
| else if (type.equals(CacheNotificationBroadcaster.NOTIF_NODE_ACTIVATED))
|
433 |
| { |
434 |
12
| if (getPre(userData))
|
435 |
| { |
436 |
8
| events.add(Type.PREACTIVATE);
|
437 |
| } |
438 |
| else |
439 |
| { |
440 |
4
| events.add(Type.POSTACTIVATE);
|
441 |
| } |
442 |
| } |
443 |
32
| else if (type.equals(CacheNotificationBroadcaster.NOTIF_NODE_MODIFIED))
|
444 |
| { |
445 |
24
| if (getPre(userData))
|
446 |
| { |
447 |
12
| events.add(Type.PREMODIFY);
|
448 |
| } |
449 |
| else |
450 |
| { |
451 |
12
| events.add(Type.POSTMODIFY);
|
452 |
| } |
453 |
| } |
454 |
8
| else if (type.equals(CacheNotificationBroadcaster.NOTIF_NODE_PASSIVATED))
|
455 |
| { |
456 |
8
| if (getPre(userData))
|
457 |
| { |
458 |
4
| events.add(Type.PREPASSIVATE);
|
459 |
| } |
460 |
| else |
461 |
| { |
462 |
4
| events.add(Type.POSTPASSIVATE);
|
463 |
| } |
464 |
| } |
465 |
| } |
466 |
| catch (RuntimeException e) |
467 |
| { |
468 |
| |
469 |
0
| exception = e;
|
470 |
| } |
471 |
| catch (AssertionFailedError e) |
472 |
| { |
473 |
| |
474 |
0
| failure = e;
|
475 |
| } |
476 |
| } |
477 |
| } |
478 |
| |
479 |
| } |