package org.jolokia.backend; /* * Copyright 2009-2011 Roland Huss * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ import java.io.IOException; import java.lang.management.ManagementFactory; import java.util.ArrayList; import java.util.List; import javax.management.*; import javax.management.openmbean.CompositeData; import org.easymock.EasyMock; import org.jolokia.backend.executor.MBeanServerExecutor; import org.jolokia.backend.executor.NotChangedException; import org.jolokia.config.*; import org.jolokia.config.Configuration; import org.jolokia.detector.ServerHandle; import org.jolokia.handler.JsonRequestHandler; import org.jolokia.request.JmxRequest; import org.jolokia.request.JmxRequestBuilder; import org.jolokia.util.LogHandler; import org.jolokia.util.RequestType; import org.testng.annotations.*; import static org.easymock.EasyMock.*; import static org.testng.Assert.*; /** * @author roland * @since 02.09.11 */ public class MBeanServerHandlerTest { private JmxRequest request; private MBeanServerHandler handler; @BeforeMethod public void setup() throws MalformedObjectNameException { TestDetector.reset(); Configuration config = new Configuration(ConfigKey.MBEAN_QUALIFIER,"qualifier=test", ConfigKey.MBEAN_PLUGIN_OPTIONS,"{\"test\" : { \"path\" : \"/tmp\" }}"); handler = new MBeanServerHandler(config,getEmptyLogHandler()); request = new JmxRequestBuilder(RequestType.READ,"java.lang:type=Memory").attribute("HeapMemoryUsage").build(); } @AfterMethod public void tearDown() throws JMException { handler.destroy(); assertTrue(TestMBeanPlugin.isInitCalled()); } @Test public void testPluginUsed() throws MalformedObjectNameException, AttributeNotFoundException, MBeanException, ReflectionException, InstanceNotFoundException, IOException { MBeanServerConnection conn = ManagementFactory.getPlatformMBeanServer(); ObjectName name = new ObjectName("jolokia:type=plugin,name=test"); long memBean = (Long) conn.getAttribute(name,"MemoryUsed"); CompositeData memSystemCd = (CompositeData) conn.getAttribute(new ObjectName("java.lang:type=Memory"),"HeapMemoryUsage"); long memSystem = (Long) memSystemCd.get("used"); double diff = Math.abs(memBean - memSystem) / memSystem * 100; // Less than 10% difference assertTrue(diff < 10); } @Test public void testPluginMax() throws MalformedObjectNameException, AttributeNotFoundException, MBeanException, ReflectionException, InstanceNotFoundException, IOException { MBeanServerConnection conn = ManagementFactory.getPlatformMBeanServer(); ObjectName name = new ObjectName("jolokia:type=plugin,name=test"); long memBean = (Long) conn.getAttribute(name,"MemoryMax"); CompositeData memSystemCd = (CompositeData) conn.getAttribute(new ObjectName("java.lang:type=Memory"),"HeapMemoryUsage"); long memSystem = (Long) memSystemCd.get("max"); assertEquals(memBean,memSystem); } @Test public void dispatchRequest() throws MalformedObjectNameException, InstanceNotFoundException, ReflectionException, AttributeNotFoundException, MBeanException, IOException, NotChangedException { JsonRequestHandler reqHandler = createMock(JsonRequestHandler.class); Object result = new Object(); expect(reqHandler.handleAllServersAtOnce(request)).andReturn(false); expect(reqHandler.handleRequest(EasyMock.<MBeanServerConnection>anyObject(), eq(request))).andReturn(result); replay(reqHandler); assertEquals(handler.dispatchRequest(reqHandler, request),result); } @Test(expectedExceptions = InstanceNotFoundException.class) public void dispatchRequestInstanceNotFound() throws MalformedObjectNameException, InstanceNotFoundException, ReflectionException, AttributeNotFoundException, MBeanException, IOException, NotChangedException { dispatchWithException(new InstanceNotFoundException()); } @Test(expectedExceptions = AttributeNotFoundException.class) public void dispatchRequestAttributeNotFound() throws MalformedObjectNameException, InstanceNotFoundException, ReflectionException, AttributeNotFoundException, MBeanException, IOException, NotChangedException { dispatchWithException(new AttributeNotFoundException()); } @Test(expectedExceptions = IllegalStateException.class) public void dispatchRequestIOException() throws MalformedObjectNameException, InstanceNotFoundException, ReflectionException, AttributeNotFoundException, MBeanException, IOException, NotChangedException { dispatchWithException(new IOException()); } private void dispatchWithException(Exception e) throws InstanceNotFoundException, AttributeNotFoundException, ReflectionException, MBeanException, IOException, NotChangedException { JsonRequestHandler reqHandler = createMock(JsonRequestHandler.class); expect(reqHandler.handleAllServersAtOnce(request)).andReturn(false); expect(reqHandler.handleRequest(EasyMock.<MBeanServerConnection>anyObject(), eq(request))).andThrow(e).anyTimes(); replay(reqHandler); handler.dispatchRequest(reqHandler, request); } @Test public void dispatchAtOnce() throws InstanceNotFoundException, IOException, ReflectionException, AttributeNotFoundException, MBeanException, NotChangedException { JsonRequestHandler reqHandler = createMock(JsonRequestHandler.class); Object result = new Object(); expect(reqHandler.handleAllServersAtOnce(request)).andReturn(true); expect(reqHandler.handleRequest(isA(MBeanServerExecutor.class), eq(request))).andReturn(result); replay(reqHandler); assertEquals(handler.dispatchRequest(reqHandler, request),result); } @Test(expectedExceptions = IllegalStateException.class,expectedExceptionsMessageRegExp = ".*Internal.*") public void dispatchAtWithException() throws InstanceNotFoundException, IOException, ReflectionException, AttributeNotFoundException, MBeanException, NotChangedException { JsonRequestHandler reqHandler = createMock(JsonRequestHandler.class); expect(reqHandler.handleAllServersAtOnce(request)).andReturn(true); expect(reqHandler.handleRequest(isA(MBeanServerExecutor.class), eq(request))).andThrow(new IOException()); replay(reqHandler); handler.dispatchRequest(reqHandler, request); } @Test public void mbeanServers() throws MBeanException, IOException, ReflectionException, MalformedObjectNameException { checkMBeans(new ObjectName("java.lang:type=Memory")); String info = handler.mBeanServersInfo(); assertTrue(info.contains("Platform MBeanServer")); assertTrue(info.contains("type=Memory")); } @Test public void mbeanRegistration() throws JMException, IOException { checkMBeans(new ObjectName(handler.getObjectName())); } private void checkMBeans(ObjectName oName) throws MBeanException, IOException, ReflectionException { MBeanServerExecutor servers = handler.getMBeanServerManager(); final List<Boolean> result = new ArrayList<Boolean>(); servers.each(oName, new MBeanServerExecutor.MBeanEachCallback() { public void callback(MBeanServerConnection pConn, ObjectName pName) throws ReflectionException, InstanceNotFoundException, IOException, MBeanException { // Throws an InstanceNotFoundException pConn.getObjectInstance(pName); result.add(pConn.isRegistered(pName)); } }); assertTrue(result.contains(Boolean.TRUE), "MBean not registered"); } @Test(expectedExceptions = InstanceNotFoundException.class) public void mbeanUnregistrationFailed1() throws JMException { handler.registerMBean(new Dummy(false, "test:type=dummy")); ManagementFactory.getPlatformMBeanServer().unregisterMBean(new ObjectName("test:type=dummy")); handler.destroy(); } @Test(expectedExceptions = JMException.class,expectedExceptionsMessageRegExp = ".*(dummy[12].*){2}.*") public void mbeanUnregistrationFailed2() throws JMException { handler.registerMBean(new Dummy(false, "test:type=dummy1")); handler.registerMBean(new Dummy(false,"test:type=dummy2")); ManagementFactory.getPlatformMBeanServer().unregisterMBean(new ObjectName("test:type=dummy1")); ManagementFactory.getPlatformMBeanServer().unregisterMBean(new ObjectName("test:type=dummy2")); handler.destroy(); } @Test public void serverHandle() { ServerHandle handle = handler.getServerHandle(); assertNotNull(handle); } @Test(expectedExceptions = IllegalStateException.class,expectedExceptionsMessageRegExp = ".*not register.*") public void mbeanRegistrationFailed() throws JMException { handler.registerMBean(new Dummy(true, "test:type=dummy")); } // =================================================================================================== private LogHandler getEmptyLogHandler() { return new LogHandler() { public void debug(String message) { } public void info(String message) { } public void error(String message, Throwable t) { } }; } public interface DummyMBean { } private class Dummy implements DummyMBean,MBeanRegistration { private boolean throwException; private String name; public Dummy(boolean b,String pName) { throwException = b; name = pName; } public ObjectName preRegister(MBeanServer server, ObjectName pName) throws Exception { if (throwException) { throw new RuntimeException(); } return new ObjectName(name); } public void postRegister(Boolean registrationDone) { } public void preDeregister() throws Exception { } public void postDeregister() { } } }