1   /**
2    *  Copyright 2003-2007 Greg Luck
3    *
4    *  Licensed under the Apache License, Version 2.0 (the "License");
5    *  you may not use this file except in compliance with the License.
6    *  You may obtain a copy of the License at
7    *
8    *      http://www.apache.org/licenses/LICENSE-2.0
9    *
10   *  Unless required by applicable law or agreed to in writing, software
11   *  distributed under the License is distributed on an "AS IS" BASIS,
12   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   *  See the License for the specific language governing permissions and
14   *  limitations under the License.
15   */
16  
17  package net.sf.ehcache.management;
18  
19  import net.sf.ehcache.AbstractCacheTest;
20  import net.sf.ehcache.Ehcache;
21  import net.sf.ehcache.Element;
22  import net.sf.ehcache.config.Configuration;
23  import net.sf.ehcache.config.ConfigurationFactory;
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  
27  import javax.management.JMException;
28  import javax.management.MBeanAttributeInfo;
29  import javax.management.MBeanInfo;
30  import javax.management.MBeanServer;
31  import javax.management.MBeanServerConnection;
32  import javax.management.MBeanServerFactory;
33  import javax.management.ObjectName;
34  import javax.management.remote.JMXConnector;
35  import javax.management.remote.JMXConnectorServer;
36  import javax.management.remote.JMXConnectorServerFactory;
37  import javax.management.remote.JMXServiceURL;
38  import java.io.File;
39  import java.io.IOException;
40  import java.rmi.registry.LocateRegistry;
41  import java.util.Iterator;
42  import java.util.List;
43  import java.util.Set;
44  
45  /**
46   * These tests use the JDK1.5 platform mbean server
47   * To interactively examine behaviour, add a Thread.sleep(...) and add -Dcom.sun.management.jmxremote to the java
48   * invocation.
49   *
50   * On Mac OS X, add -Dcom.sun.management.jmxremote to the java command line for JConsole to see the test
51   *
52   * @author Greg Luck
53   * @version $Id: ManagementServiceTest.java 512 2007-07-10 09:18:45Z gregluck $
54   */
55  public class ManagementServiceTest extends AbstractCacheTest {
56  
57      private static final Log LOG = LogFactory.getLog(ManagementServiceTest.class.getName());
58      private MBeanServer mBeanServer;
59  
60  
61      /**
62       * setup test
63       */
64      protected void setUp() throws Exception {
65          super.setUp();
66          mBeanServer = createMBeanServer();
67      }
68  
69      private MBeanServer create14MBeanServer() {
70          return MBeanServerFactory.createMBeanServer("SimpleAgent");
71      }
72  
73      /**
74       * teardown
75       */
76      protected void tearDown() throws Exception {
77          super.tearDown();
78          //Ensure the CacheManager shutdown clears all ObjectNames from the MBeanServer
79          assertEquals(0, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
80      }
81  
82  
83      /**
84       * Integration test for the registration service
85       */
86      public void testRegistrationServiceFourTrue() throws Exception {
87          ManagementService.registerMBeans(manager, mBeanServer, true, true, true, true);
88          assertEquals(37, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
89      }
90  
91      /**
92       * Integration test for the registration service
93       */
94      public void testRegistrationServiceFourTrueUsing14MBeanServer() throws Exception {
95          mBeanServer = create14MBeanServer();
96          ManagementService.registerMBeans(manager, mBeanServer, true, true, true, true);
97          assertEquals(37, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
98      }
99  
100     /**
101      * Integration test for the registration service
102      */
103     public void testRegistrationServiceListensForCacheChanges() throws Exception {
104         ManagementService.registerMBeans(manager, mBeanServer, true, true, true, true);
105         assertEquals(37, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
106         manager.addCache("new cache");
107         assertEquals(40, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
108         manager.removeCache("sampleCache1");
109         assertEquals(37, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
110         //Thread.sleep(1000000);
111     }
112 
113     /**
114      * Integration test for the registration service
115      */
116     public void testMultipleCacheManagers() throws Exception {
117         ManagementService.registerMBeans(manager, mBeanServer, true, true, true, true);
118         assertEquals(37, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
119         File file = new File(AbstractCacheTest.SRC_CONFIG_DIR + "ehcache.xml");
120         Configuration configuration = ConfigurationFactory.parseConfiguration(file);
121         net.sf.ehcache.CacheManager secondCacheManager = new net.sf.ehcache.CacheManager(configuration);
122         ManagementService.registerMBeans(secondCacheManager, mBeanServer, true, true, true, true);
123         assertEquals(56, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
124         secondCacheManager.shutdown();
125         assertEquals(37, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
126 
127     }
128 
129     /**
130      * Checks that Statistics updates
131      */
132     public void testStatisticsMBeanUpdatesAsStatsChange() throws Exception {
133         ManagementService.registerMBeans(manager, mBeanServer, false, false, false, true);
134         Ehcache cache = manager.getCache("sampleCache1");
135         ObjectName name = CacheStatistics.createObjectName(manager.getName(), cache.getName());
136         assertEquals(new Long(0), mBeanServer.getAttribute(name, "ObjectCount"));
137         cache.put(new Element("1", "value"));
138         cache.get("1");
139         Thread.sleep(20);
140         assertEquals(new Long(1), mBeanServer.getAttribute(name, "ObjectCount"));
141 
142 //        Thread.sleep(1000000);
143 
144 
145     }
146 
147     /**
148      * Integration test for the registration service
149      */
150     public void testRegistrationServiceThreeTrue() throws Exception {
151         ManagementService.registerMBeans(manager, mBeanServer, true, true, true, false);
152         assertEquals(25, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
153 
154     }
155 
156     /**
157      * Integration test for the registration service
158      */
159     public void testRegistrationServiceTwoTrue() throws Exception {
160         ManagementService.registerMBeans(manager, mBeanServer, true, true, false, false);
161         assertEquals(13, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
162 
163     }
164 
165     /**
166      * Integration test for the registration service
167      */
168     public void testRegistrationServiceOneTrue() throws Exception {
169         ManagementService.registerMBeans(manager, mBeanServer, true, false, false, false);
170         assertEquals(1, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
171 
172     }
173 
174     /**
175      * Integration test for the registration service
176      */
177     public void testRegistrationServiceNoneTrue() throws Exception {
178         ManagementService.registerMBeans(manager, mBeanServer, false, false, false, false);
179         assertEquals(0, mBeanServer.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
180 
181     }
182 
183     /**
184      * Can we register the CacheManager MBean?
185      */
186     public void testRegisterCacheManager() throws Exception {
187         //Set size so the second element overflows to disk.
188         Ehcache ehcache = new net.sf.ehcache.Cache("testNoOverflowToDisk", 1, false, true, 500, 200);
189         manager.addCache(ehcache);
190 
191         ehcache.put(new Element("key1", "value1"));
192         ehcache.put(new Element("key2", "value1"));
193         assertNull(ehcache.get("key1"));
194         assertNotNull(ehcache.get("key2"));
195 
196 
197         ObjectName name = new ObjectName("net.sf.ehcache:type=CacheManager,name=1");
198         CacheManager cacheManager = new CacheManager(manager);
199         mBeanServer.registerMBean(cacheManager, name);
200         mBeanServer.unregisterMBean(name);
201 
202         name = new ObjectName("net.sf.ehcache:type=CacheManager.Cache,CacheManager=1,name=testOverflowToDisk");
203         mBeanServer.registerMBean(new Cache(ehcache), name);
204         mBeanServer.unregisterMBean(name);
205 
206         name = new ObjectName("net.sf.ehcache:type=CacheManager.Cache,CacheManager=1,name=sampleCache1");
207         mBeanServer.registerMBean(new Cache(manager.getCache("sampleCache1")), name);
208         mBeanServer.unregisterMBean(name);
209 
210     }
211 
212 
213     /**
214      * Can we register the CacheManager MBean?
215      */
216     public void testListCachesFromManager() throws Exception {
217         ManagementService.registerMBeans(manager, mBeanServer, true, false, false, false);
218 
219         Ehcache ehcache = manager.getCache("sampleCache1");
220 
221         ehcache.put(new Element("key1", "value1"));
222         ehcache.put(new Element("key2", "value1"));
223         assertNotNull(ehcache.get("key1"));
224         assertNotNull(ehcache.get("key2"));
225 
226         ObjectName name = CacheManager.createObjectName(manager);
227 
228         Object object = mBeanServer.getAttribute(name, "Status");
229         LOG.info(object);
230 
231         List caches = (List) mBeanServer.getAttribute(name, "Caches");
232         assertEquals(12, caches.size());
233 
234         for (int i = 0; i < caches.size(); i++) {
235             Cache cache = (Cache) caches.get(i);
236             String cacheName = cache.getName();
237             CacheStatistics cacheStatistics = cache.getStatistics();
238             CacheConfiguration cacheConfiguration = cache.getCacheConfiguration();
239             LOG.info(cacheName + " " + cacheStatistics + " " + cacheConfiguration);
240         }
241     }
242 
243     /**
244      * Shows that all MBeans are fully traversable locally
245      * @throws JMException
246      */
247     public void testTraversalUsingMBeanServer() throws JMException {
248         //Test CacheManager
249         //not all attributes are accessible due to serializability constraints
250         traverseMBeanAttributesUsingMBeanServer("CacheManager");
251 
252         //Test Cache
253         //not all attributes are accessible due to serializability constraints
254         traverseMBeanAttributesUsingMBeanServer("Cache");
255 
256         //Test CacheStatistics
257         traverseMBeanAttributesUsingMBeanServer("CacheStatistics");
258 
259         //Test CacheConfiguration
260         traverseMBeanAttributesUsingMBeanServer("CacheConfiguration");
261 
262     }
263 
264 
265     /**
266      * Creates an RMI JMXConnectorServer, connects to it and demonstrates what attributes are traversable.
267      * The answer is not all.
268      *
269      * Note that this test creates a Registry which will keep running until the JVM Exists. There
270      * is no way to stop it but it should do no harm.
271      *
272      *
273      */
274     public void testJMXConnectorServer() throws Exception {
275 
276         ManagementService.registerMBeans(manager, mBeanServer, true, true, true, true);
277 
278         LocateRegistry.createRegistry(55000);
279         String serverUrl = "service:jmx:rmi:///jndi/rmi://localhost:55000/server";
280         JMXServiceURL url = new JMXServiceURL(serverUrl);
281         JMXConnectorServer cs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, mBeanServer);
282         cs.start();
283         JMXConnector connector = cs.toJMXConnector(null);
284         connector.connect(null);
285         MBeanServerConnection connection = connector.getMBeanServerConnection();
286         assertEquals(37, connection.queryNames(new ObjectName("net.sf.ehcache:*"), null).size());
287 
288 
289         Ehcache ehcache = manager.getCache("sampleCache1");
290 
291         ehcache.put(new Element("key1", "value1"));
292         ehcache.put(new Element("key2", "value1"));
293         assertNotNull(ehcache.get("key1"));
294         assertNotNull(ehcache.get("key2"));
295 
296         //Test CacheManager
297         //not all attributes are accessible due to serializability constraints
298         //traverseMBeanAttributes(connection, "CacheManager");
299 
300         //Test Cache
301         //not all attributes are accessible due to serializability constraints
302         //traverseMBeanAttributes(connection, "Cache");
303 
304         //Test CacheStatistics
305         traverseMBeanAttributes(connection, "CacheStatistics");
306 
307         //Test CacheConfiguration
308         traverseMBeanAttributes(connection, "CacheConfiguration");
309 
310         cs.stop();
311     }
312 
313     private void traverseMBeanAttributes(MBeanServerConnection connection, String type) throws JMException, IOException {
314         Set objectNames = connection.queryNames(new ObjectName("net.sf.ehcache:type=" + type + ",*"), null);
315         for (Iterator iterator = objectNames.iterator(); iterator.hasNext();) {
316             ObjectName objectName = (ObjectName) iterator.next();
317             MBeanInfo mBeanInfo = connection.getMBeanInfo(objectName);
318             MBeanAttributeInfo[] attributes = mBeanInfo.getAttributes();
319             for (int i = 0; i < attributes.length; i++) {
320                 MBeanAttributeInfo attribute = attributes[i];
321                 LOG.info(attribute.getName() + " " + connection.getAttribute(objectName, attribute.getName()));
322             }
323         }
324     }
325 
326     private void traverseMBeanAttributesUsingMBeanServer(String type) throws JMException {
327         Set objectNames = mBeanServer.queryNames(new ObjectName("net.sf.ehcache:type=" + type + ",*"), null);
328         for (Iterator iterator = objectNames.iterator(); iterator.hasNext();) {
329             ObjectName objectName = (ObjectName) iterator.next();
330             MBeanInfo mBeanInfo = mBeanServer.getMBeanInfo(objectName);
331             MBeanAttributeInfo[] attributes = mBeanInfo.getAttributes();
332             for (int i = 0; i < attributes.length; i++) {
333                 MBeanAttributeInfo attribute = attributes[i];
334                 LOG.info(attribute.getName() + " " + mBeanServer.getAttribute(objectName, attribute.getName()));
335             }
336         }
337     }
338 
339 
340 }