package org.jolokia.handler; /* * Copyright 2009-2013 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.*; import javax.management.*; import org.easymock.EasyMock; import org.jolokia.backend.executor.MBeanServerExecutor; import org.jolokia.backend.MBeanServerExecutorLocal; import org.jolokia.backend.executor.NotChangedException; import org.jolokia.request.JmxListRequest; import org.jolokia.request.JmxRequestBuilder; import org.jolokia.restrictor.AllowAllRestrictor; import org.jolokia.config.ConfigKey; import org.jolokia.handler.list.DataKeys; import org.jolokia.util.RequestType; import org.testng.annotations.*; import static org.easymock.EasyMock.*; import static org.testng.Assert.*; /** * @author roland * @since 11.04.11 */ public class ListHandlerTest extends BaseHandlerTest { private ListHandler handler; private MBeanServerExecutorLocal executor; @BeforeMethod private void createHandler() { handler = new ListHandler(new AllowAllRestrictor()); executor = new MBeanServerExecutorLocal(); } @AfterMethod private void destroy() { executor.destroy(); } @Test public void singleSlashPath() throws Exception { for (String p : new String[]{null, "", "/"}) { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST).path(p).build(); Map res = execute(request); assertTrue(res.containsKey("java.lang")); assertTrue(res.get("java.lang") instanceof Map); } } @Test public void domainPath() throws Exception { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST).pathParts("java.lang").build(); Map res = execute(request); assertTrue(res.containsKey("type=Memory")); assertTrue(res.get("type=Memory") instanceof Map); } @Test public void propertiesPath() throws Exception { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST).pathParts("java.lang", "type=Memory").build(); Map res = execute(request); for (String k : new String[]{DataKeys.DESCRIPTION.getKey(), DataKeys.OPERATIONS.getKey(), DataKeys.ATTRIBUTES.getKey(), DataKeys.CLASSNAME.getKey()}) { assertTrue(res.containsKey(k)); } assertEquals(res.size(), 4); } @Test public void attrPath() throws Exception { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST).pathParts("java.lang","type=Memory","attr").build(); Map res = execute(request); assertTrue(res.containsKey("HeapMemoryUsage")); } @Test public void descPath() throws Exception { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST).pathParts("java.lang","type=Memory","desc").build(); String res = (String) handler.handleRequest(executor, request); assertNotNull(res); } @Test public void descPathWithDepth() throws Exception { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST) .pathParts("java.lang","type=Memory","desc") .option(ConfigKey.MAX_DEPTH,"4") .build(); String res = (String) handler.handleRequest(executor, request); assertNotNull(res); } @Test public void opPath() throws Exception { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST).pathParts("java.lang","type=Memory","op").build(); Map res = execute(request); assertTrue(res.containsKey("gc")); } @Test public void maxDepth1() throws Exception { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST).option(ConfigKey.MAX_DEPTH,"1").build(); Map res = execute(request); assertTrue(res.containsKey("java.lang")); assertFalse(res.get("java.lang") instanceof Map); } @Test public void maxDepth2() throws Exception { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST).option(ConfigKey.MAX_DEPTH,"2").build(); Map res = execute(request); assertTrue(res.containsKey("java.lang")); Map inner = (Map) res.get("java.lang"); assertTrue(inner.containsKey("type=Memory")); assertFalse(inner.get("type=Memory") instanceof Map); } @Test public void maxDepthAndPath() throws Exception { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST).pathParts("java.lang","type=Memory") .option(ConfigKey.MAX_DEPTH, "3").build(); Map res = execute(request); assertEquals(res.size(), 4); Map ops = (Map) res.get("op"); assertTrue(ops.containsKey("gc")); assertTrue(ops.get("gc") instanceof Map); Map attrs = (Map) res.get("attr"); // Java 7 introduces a new attribute 'ObjectName' here assertEquals(attrs.size(),attrs.containsKey("ObjectName") ? 5 : 4); assertTrue(attrs.get("HeapMemoryUsage") instanceof Map); assertTrue(res.get("desc") instanceof String); } @Test public void keyOrder() throws Exception { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST).option(ConfigKey.CANONICAL_NAMING,"true").build(); Map res = execute(request); Map<String,?> mbeans = (Map<String,?>) res.get("java.lang"); for (String key : mbeans.keySet()) { String parts[] = key.split(","); String partsSorted[] = parts.clone(); Arrays.sort(partsSorted); assertEquals(parts,partsSorted); } } @Test public void truncatedList() throws Exception { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST).pathParts("java.lang", "type=Runtime").build(); Map res = execute(request); assertFalse(res.containsKey("op")); assertEquals(res.size(),3); } @Test(expectedExceptions = { IllegalArgumentException.class }) public void invalidPath() throws Exception { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST) .pathParts("java.lang", "type=Memory", "attr", "unknownAttribute") .build(); execute(request); } @Test(expectedExceptions = { IllegalArgumentException.class }) public void invalidPath2() throws Exception { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST) .pathParts("java.lang", "type=Runtime", "op", "bla") .option(ConfigKey.MAX_DEPTH,"3") .build(); execute(request); } @Test(expectedExceptions = { IllegalArgumentException.class }) public void invalidPath3() throws Exception { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST) .pathParts("java.lang", "type=Runtime", "bla") .option(ConfigKey.MAX_DEPTH,"3") .build(); execute(request); } @Test(expectedExceptions = { IllegalArgumentException.class }) public void invalidPath4() throws Exception { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST) .pathParts("java.lang", "type=*") .build(); execute(request); } @Test public void invalidPath5() throws Exception { for (String what : new String[] { "attr", "op", "not" }) { try { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST) .pathParts("java.lang", "type=Memory", what, "HeapMemoryUsage", "bla") .build(); execute(request); fail(); } catch (IllegalArgumentException exp) { assertTrue(exp.getMessage().contains("bla")); } } } @Test(expectedExceptions = { IllegalArgumentException.class }, expectedExceptionsMessageRegExp = ".*bla.*") public void invalidPath8() throws Exception { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST) .pathParts("java.lang", "type=Memory", "desc", "bla") .build(); execute(request); } private Map execute(JmxListRequest pRequest) throws ReflectionException, InstanceNotFoundException, MBeanException, AttributeNotFoundException, IOException, NotChangedException { return (Map) handler.handleRequest(executor, pRequest); } @Test public void emptyMaps() throws Exception { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST) .pathParts("java.lang", "type=Runtime", "op") .build(); Map res = (Map) handler.handleRequest(executor,request); assertEquals(res.size(),0); request = new JmxRequestBuilder(RequestType.LIST) .pathParts("java.lang", "type=Runtime", "not") .build(); res = (Map) handler.handleRequest(executor,request); assertEquals(res.size(),0); } @Test public void singleMBeanMultipleServers() throws MalformedObjectNameException, InstanceNotFoundException, IOException, AttributeNotFoundException, ReflectionException, MBeanException, IntrospectionException, NotChangedException { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST) .pathParts("java.lang", "type=Memory", "attr") .build(); MBeanServerConnection dummyConn = EasyMock.createMock(MBeanServerConnection.class); Set<MBeanServerConnection> conns = new LinkedHashSet<MBeanServerConnection>(); conns.add(dummyConn); conns.add(ManagementFactory.getPlatformMBeanServer()); expect(dummyConn.getMBeanInfo(new ObjectName("java.lang:type=Memory"))).andThrow(new InstanceNotFoundException()); replay(dummyConn); Map res = (Map) handler.handleRequest(executor,request); assertEquals(((Map) res.get("Verbose")).get("type"),"boolean"); } @Test(expectedExceptions = IllegalArgumentException.class, expectedExceptionsMessageRegExp = ".*No MBean.*") public void noMBeanMultipleServers() throws MalformedObjectNameException, InstanceNotFoundException, IOException, AttributeNotFoundException, ReflectionException, MBeanException, IntrospectionException, NotChangedException { JmxListRequest request = new JmxRequestBuilder(RequestType.LIST) .pathParts("bullerbue", "country=sweden") .build(); MBeanServer dummyConn = EasyMock.createMock(MBeanServer.class); MBeanServerExecutor servers = getMBeanServerManager(dummyConn, ManagementFactory.getPlatformMBeanServer()); ObjectName name = new ObjectName("bullerbue:country=sweden"); expect(dummyConn.getMBeanInfo(name)).andThrow(new InstanceNotFoundException()); expect(dummyConn.isRegistered(name)).andReturn(false); replay(dummyConn); handler.handleRequest(servers,request); } }