001/** 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018package org.apache.hadoop.hbase.http.jmx; 019 020import java.net.HttpURLConnection; 021import java.net.URL; 022import java.net.URLEncoder; 023import java.util.regex.Matcher; 024import java.util.regex.Pattern; 025import javax.servlet.http.HttpServletResponse; 026import org.apache.hadoop.hbase.HBaseClassTestRule; 027import org.apache.hadoop.hbase.http.HttpServer; 028import org.apache.hadoop.hbase.http.HttpServerFunctionalTest; 029import org.apache.hadoop.hbase.testclassification.MiscTests; 030import org.apache.hadoop.hbase.testclassification.SmallTests; 031import org.junit.AfterClass; 032import org.junit.BeforeClass; 033import org.junit.ClassRule; 034import org.junit.Test; 035import org.junit.experimental.categories.Category; 036import org.slf4j.Logger; 037import org.slf4j.LoggerFactory; 038 039@Category({MiscTests.class, SmallTests.class}) 040public class TestJMXJsonServlet extends HttpServerFunctionalTest { 041 042 @ClassRule 043 public static final HBaseClassTestRule CLASS_RULE = 044 HBaseClassTestRule.forClass(TestJMXJsonServlet.class); 045 046 private static final Logger LOG = LoggerFactory.getLogger(TestJMXJsonServlet.class); 047 private static HttpServer server; 048 private static URL baseUrl; 049 050 @BeforeClass public static void setup() throws Exception { 051 // Eclipse doesn't pick this up correctly from the plugin 052 // configuration in the pom. 053 System.setProperty(HttpServerFunctionalTest.TEST_BUILD_WEBAPPS, "target/test-classes/webapps"); 054 server = createTestServer(); 055 server.start(); 056 baseUrl = getServerURL(server); 057 } 058 059 @AfterClass public static void cleanup() throws Exception { 060 server.stop(); 061 } 062 063 public static void assertReFind(String re, String value) { 064 Pattern p = Pattern.compile(re); 065 Matcher m = p.matcher(value); 066 assertTrue("'"+p+"' does not match "+value, m.find()); 067 } 068 069 @Test public void testQuery() throws Exception { 070 String result = readOutput(new URL(baseUrl, "/jmx?qry=java.lang:type=Runtime")); 071 LOG.info("/jmx?qry=java.lang:type=Runtime RESULT: "+result); 072 assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Runtime\"", result); 073 assertReFind("\"modelerType\"", result); 074 075 result = readOutput(new URL(baseUrl, "/jmx?qry=java.lang:type=Memory")); 076 LOG.info("/jmx?qry=java.lang:type=Memory RESULT: "+result); 077 assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Memory\"", result); 078 assertReFind("\"modelerType\"", result); 079 080 result = readOutput(new URL(baseUrl, "/jmx")); 081 LOG.info("/jmx RESULT: "+result); 082 assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Memory\"", result); 083 084 // test to get an attribute of a mbean 085 result = readOutput(new URL(baseUrl, 086 "/jmx?get=java.lang:type=Memory::HeapMemoryUsage")); 087 LOG.info("/jmx RESULT: "+result); 088 assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Memory\"", result); 089 assertReFind("\"committed\"\\s*:", result); 090 091 // negative test to get an attribute of a mbean 092 result = readOutput(new URL(baseUrl, 093 "/jmx?get=java.lang:type=Memory::")); 094 LOG.info("/jmx RESULT: "+result); 095 assertReFind("\"ERROR\"", result); 096 097 // test to get JSONP result 098 result = readOutput(new URL(baseUrl, "/jmx?qry=java.lang:type=Memory&callback=mycallback1")); 099 LOG.info("/jmx?qry=java.lang:type=Memory&callback=mycallback RESULT: "+result); 100 assertReFind("^mycallback1\\(\\{", result); 101 assertReFind("\\}\\);$", result); 102 103 // negative test to get an attribute of a mbean as JSONP 104 result = readOutput(new URL(baseUrl, 105 "/jmx?get=java.lang:type=Memory::&callback=mycallback2")); 106 LOG.info("/jmx RESULT: "+result); 107 assertReFind("^mycallback2\\(\\{", result); 108 assertReFind("\"ERROR\"", result); 109 assertReFind("\\}\\);$", result); 110 111 // test to get an attribute of a mbean as JSONP 112 result = readOutput(new URL(baseUrl, 113 "/jmx?get=java.lang:type=Memory::HeapMemoryUsage&callback=mycallback3")); 114 LOG.info("/jmx RESULT: "+result); 115 assertReFind("^mycallback3\\(\\{", result); 116 assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Memory\"", result); 117 assertReFind("\"committed\"\\s*:", result); 118 assertReFind("\\}\\);$", result); 119 120 } 121 122 @Test 123 public void testDisallowedJSONPCallback() throws Exception { 124 String callback = "function(){alert('bigproblems!')};foo"; 125 URL url = new URL( 126 baseUrl, "/jmx?qry=java.lang:type=Memory&callback="+URLEncoder.encode(callback, "UTF-8")); 127 HttpURLConnection cnxn = (HttpURLConnection) url.openConnection(); 128 assertEquals(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, cnxn.getResponseCode()); 129 } 130 131 @Test 132 public void testUnderscoresInJSONPCallback() throws Exception { 133 String callback = "my_function"; 134 URL url = new URL( 135 baseUrl, "/jmx?qry=java.lang:type=Memory&callback="+URLEncoder.encode(callback, "UTF-8")); 136 HttpURLConnection cnxn = (HttpURLConnection) url.openConnection(); 137 assertEquals(HttpServletResponse.SC_OK, cnxn.getResponseCode()); 138 } 139}