You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by zh...@apache.org on 2017/10/25 12:28:28 UTC
[06/21] hbase git commit: HBASE-19053 Split out o.a.h.h.http from
hbase-server into a separate module
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestSpnegoHttpServer.java
----------------------------------------------------------------------
diff --git a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestSpnegoHttpServer.java b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestSpnegoHttpServer.java
new file mode 100644
index 0000000..4fad031
--- /dev/null
+++ b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/TestSpnegoHttpServer.java
@@ -0,0 +1,258 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to you 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.
+ */
+package org.apache.hadoop.hbase.http;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.security.Principal;
+import java.security.PrivilegedExceptionAction;
+import java.util.Set;
+
+import javax.security.auth.Subject;
+import javax.security.auth.kerberos.KerberosTicket;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.http.TestHttpServer.EchoServlet;
+import org.apache.hadoop.hbase.http.resource.JerseyResource;
+import org.apache.hadoop.hbase.testclassification.MiscTests;
+import org.apache.hadoop.hbase.testclassification.SmallTests;
+import org.apache.hadoop.security.authentication.util.KerberosName;
+import org.apache.http.HttpHost;
+import org.apache.http.HttpResponse;
+import org.apache.http.auth.AuthSchemeProvider;
+import org.apache.http.auth.AuthScope;
+import org.apache.http.auth.KerberosCredentials;
+import org.apache.http.client.HttpClient;
+import org.apache.http.client.config.AuthSchemes;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.protocol.HttpClientContext;
+import org.apache.http.config.Lookup;
+import org.apache.http.config.RegistryBuilder;
+import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.entity.ContentType;
+import org.apache.http.impl.auth.SPNegoSchemeFactory;
+import org.apache.http.impl.client.BasicCredentialsProvider;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.util.EntityUtils;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.client.JaasKrbUtil;
+import org.apache.kerby.kerberos.kerb.server.SimpleKdcServer;
+import org.ietf.jgss.GSSCredential;
+import org.ietf.jgss.GSSManager;
+import org.ietf.jgss.GSSName;
+import org.ietf.jgss.Oid;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+/**
+ * Test class for SPNEGO authentication on the HttpServer. Uses Kerby's MiniKDC and Apache
+ * HttpComponents to verify that a simple Servlet is reachable via SPNEGO and unreachable w/o.
+ */
+@Category({MiscTests.class, SmallTests.class})
+public class TestSpnegoHttpServer extends HttpServerFunctionalTest {
+ private static final Log LOG = LogFactory.getLog(TestSpnegoHttpServer.class);
+ private static final String KDC_SERVER_HOST = "localhost";
+ private static final String CLIENT_PRINCIPAL = "client";
+
+ private static HttpServer server;
+ private static URL baseUrl;
+ private static SimpleKdcServer kdc;
+ private static File infoServerKeytab;
+ private static File clientKeytab;
+
+ @BeforeClass
+ public static void setupServer() throws Exception {
+ final String serverPrincipal = "HTTP/" + KDC_SERVER_HOST;
+ final File target = new File(System.getProperty("user.dir"), "target");
+ assertTrue(target.exists());
+
+ kdc = buildMiniKdc();
+ kdc.start();
+
+ File keytabDir = new File(target, TestSpnegoHttpServer.class.getSimpleName()
+ + "_keytabs");
+ if (keytabDir.exists()) {
+ deleteRecursively(keytabDir);
+ }
+ keytabDir.mkdirs();
+
+ infoServerKeytab = new File(keytabDir, serverPrincipal.replace('/', '_') + ".keytab");
+ clientKeytab = new File(keytabDir, CLIENT_PRINCIPAL + ".keytab");
+
+ setupUser(kdc, clientKeytab, CLIENT_PRINCIPAL);
+ setupUser(kdc, infoServerKeytab, serverPrincipal);
+
+ Configuration conf = buildSpnegoConfiguration(serverPrincipal, infoServerKeytab);
+
+ server = createTestServerWithSecurity(conf);
+ server.addServlet("echo", "/echo", EchoServlet.class);
+ server.addJerseyResourcePackage(JerseyResource.class.getPackage().getName(), "/jersey/*");
+ server.start();
+ baseUrl = getServerURL(server);
+
+ LOG.info("HTTP server started: "+ baseUrl);
+ }
+
+ @AfterClass
+ public static void stopServer() throws Exception {
+ try {
+ if (null != server) {
+ server.stop();
+ }
+ } catch (Exception e) {
+ LOG.info("Failed to stop info server", e);
+ }
+ try {
+ if (null != kdc) {
+ kdc.stop();
+ }
+ } catch (Exception e) {
+ LOG.info("Failed to stop mini KDC", e);
+ }
+ }
+
+ private static void setupUser(SimpleKdcServer kdc, File keytab, String principal)
+ throws KrbException {
+ kdc.createPrincipal(principal);
+ kdc.exportPrincipal(principal, keytab);
+ }
+
+ private static SimpleKdcServer buildMiniKdc() throws Exception {
+ SimpleKdcServer kdc = new SimpleKdcServer();
+
+ final File target = new File(System.getProperty("user.dir"), "target");
+ File kdcDir = new File(target, TestSpnegoHttpServer.class.getSimpleName());
+ if (kdcDir.exists()) {
+ deleteRecursively(kdcDir);
+ }
+ kdcDir.mkdirs();
+ kdc.setWorkDir(kdcDir);
+
+ kdc.setKdcHost(KDC_SERVER_HOST);
+ int kdcPort = getFreePort();
+ kdc.setAllowTcp(true);
+ kdc.setAllowUdp(false);
+ kdc.setKdcTcpPort(kdcPort);
+
+ LOG.info("Starting KDC server at " + KDC_SERVER_HOST + ":" + kdcPort);
+
+ kdc.init();
+
+ return kdc;
+ }
+
+ private static Configuration buildSpnegoConfiguration(String serverPrincipal, File
+ serverKeytab) {
+ Configuration conf = new Configuration();
+ KerberosName.setRules("DEFAULT");
+
+ conf.setInt(HttpServer.HTTP_MAX_THREADS, TestHttpServer.MAX_THREADS);
+
+ // Enable Kerberos (pre-req)
+ conf.set("hbase.security.authentication", "kerberos");
+ conf.set(HttpServer.HTTP_UI_AUTHENTICATION, "kerberos");
+ conf.set(HttpServer.HTTP_SPNEGO_AUTHENTICATION_PRINCIPAL_KEY, serverPrincipal);
+ conf.set(HttpServer.HTTP_SPNEGO_AUTHENTICATION_KEYTAB_KEY, serverKeytab.getAbsolutePath());
+
+ return conf;
+ }
+
+ @Test
+ public void testUnauthorizedClientsDisallowed() throws IOException {
+ URL url = new URL(getServerURL(server), "/echo?a=b");
+ HttpURLConnection conn = (HttpURLConnection) url.openConnection();
+ assertEquals(HttpURLConnection.HTTP_UNAUTHORIZED, conn.getResponseCode());
+ }
+
+ @Test
+ public void testAllowedClient() throws Exception {
+ // Create the subject for the client
+ final Subject clientSubject = JaasKrbUtil.loginUsingKeytab(CLIENT_PRINCIPAL, clientKeytab);
+ final Set<Principal> clientPrincipals = clientSubject.getPrincipals();
+ // Make sure the subject has a principal
+ assertFalse(clientPrincipals.isEmpty());
+
+ // Get a TGT for the subject (might have many, different encryption types). The first should
+ // be the default encryption type.
+ Set<KerberosTicket> privateCredentials =
+ clientSubject.getPrivateCredentials(KerberosTicket.class);
+ assertFalse(privateCredentials.isEmpty());
+ KerberosTicket tgt = privateCredentials.iterator().next();
+ assertNotNull(tgt);
+
+ // The name of the principal
+ final String principalName = clientPrincipals.iterator().next().getName();
+
+ // Run this code, logged in as the subject (the client)
+ HttpResponse resp = Subject.doAs(clientSubject,
+ new PrivilegedExceptionAction<HttpResponse>() {
+ @Override
+ public HttpResponse run() throws Exception {
+ // Logs in with Kerberos via GSS
+ GSSManager gssManager = GSSManager.getInstance();
+ // jGSS Kerberos login constant
+ Oid oid = new Oid("1.2.840.113554.1.2.2");
+ GSSName gssClient = gssManager.createName(principalName, GSSName.NT_USER_NAME);
+ GSSCredential credential = gssManager.createCredential(gssClient,
+ GSSCredential.DEFAULT_LIFETIME, oid, GSSCredential.INITIATE_ONLY);
+
+ HttpClientContext context = HttpClientContext.create();
+ Lookup<AuthSchemeProvider> authRegistry = RegistryBuilder.<AuthSchemeProvider>create()
+ .register(AuthSchemes.SPNEGO, new SPNegoSchemeFactory(true, true))
+ .build();
+
+ HttpClient client = HttpClients.custom().setDefaultAuthSchemeRegistry(authRegistry).build();
+ BasicCredentialsProvider credentialsProvider = new BasicCredentialsProvider();
+ credentialsProvider.setCredentials(AuthScope.ANY, new KerberosCredentials(credential));
+
+ URL url = new URL(getServerURL(server), "/echo?a=b");
+ context.setTargetHost(new HttpHost(url.getHost(), url.getPort()));
+ context.setCredentialsProvider(credentialsProvider);
+ context.setAuthSchemeRegistry(authRegistry);
+
+ HttpGet get = new HttpGet(url.toURI());
+ return client.execute(get, context);
+ }
+ });
+
+ assertNotNull(resp);
+ assertEquals(HttpURLConnection.HTTP_OK, resp.getStatusLine().getStatusCode());
+ assertEquals("a:b", EntityUtils.toString(resp.getEntity()).trim());
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void testMissingConfigurationThrowsException() throws Exception {
+ Configuration conf = new Configuration();
+ conf.setInt(HttpServer.HTTP_MAX_THREADS, TestHttpServer.MAX_THREADS);
+ // Enable Kerberos (pre-req)
+ conf.set("hbase.security.authentication", "kerberos");
+ // Intentionally skip keytab and principal
+
+ HttpServer customServer = createTestServerWithSecurity(conf);
+ customServer.addServlet("echo", "/echo", EchoServlet.class);
+ customServer.addJerseyResourcePackage(JerseyResource.class.getPackage().getName(), "/jersey/*");
+ customServer.start();
+ }
+}
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-http/src/test/java/org/apache/hadoop/hbase/http/conf/TestConfServlet.java
----------------------------------------------------------------------
diff --git a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/conf/TestConfServlet.java b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/conf/TestConfServlet.java
new file mode 100644
index 0000000..8bd1e6d
--- /dev/null
+++ b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/conf/TestConfServlet.java
@@ -0,0 +1,116 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.hadoop.hbase.http.conf;
+
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.Map;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import junit.framework.TestCase;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.hbase.testclassification.MiscTests;
+import org.apache.hadoop.hbase.testclassification.SmallTests;
+import org.eclipse.jetty.util.ajax.JSON;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+/**
+ * Basic test case that the ConfServlet can write configuration
+ * to its output in XML and JSON format.
+ */
+@Category({MiscTests.class, SmallTests.class})
+public class TestConfServlet extends TestCase {
+ private static final String TEST_KEY = "testconfservlet.key";
+ private static final String TEST_VAL = "testval";
+
+ private Configuration getTestConf() {
+ Configuration testConf = new Configuration();
+ testConf.set(TEST_KEY, TEST_VAL);
+ return testConf;
+ }
+
+ @Test
+ @SuppressWarnings("unchecked")
+ public void testWriteJson() throws Exception {
+ StringWriter sw = new StringWriter();
+ ConfServlet.writeResponse(getTestConf(), sw, "json");
+ String json = sw.toString();
+ boolean foundSetting = false;
+ Object parsed = JSON.parse(json);
+ Object[] properties = ((Map<String, Object[]>)parsed).get("properties");
+ for (Object o : properties) {
+ Map<String, Object> propertyInfo = (Map<String, Object>)o;
+ String key = (String)propertyInfo.get("key");
+ String val = (String)propertyInfo.get("value");
+ String resource = (String)propertyInfo.get("resource");
+ System.err.println("k: " + key + " v: " + val + " r: " + resource);
+ if (TEST_KEY.equals(key) && TEST_VAL.equals(val)
+ && "programatically".equals(resource)) {
+ foundSetting = true;
+ }
+ }
+ assertTrue(foundSetting);
+ }
+
+ @Test
+ public void testWriteXml() throws Exception {
+ StringWriter sw = new StringWriter();
+ ConfServlet.writeResponse(getTestConf(), sw, "xml");
+ String xml = sw.toString();
+
+ DocumentBuilderFactory docBuilderFactory
+ = DocumentBuilderFactory.newInstance();
+ DocumentBuilder builder = docBuilderFactory.newDocumentBuilder();
+ Document doc = builder.parse(new InputSource(new StringReader(xml)));
+ NodeList nameNodes = doc.getElementsByTagName("name");
+ boolean foundSetting = false;
+ for (int i = 0; i < nameNodes.getLength(); i++) {
+ Node nameNode = nameNodes.item(i);
+ String key = nameNode.getTextContent();
+ System.err.println("xml key: " + key);
+ if (TEST_KEY.equals(key)) {
+ foundSetting = true;
+ Element propertyElem = (Element)nameNode.getParentNode();
+ String val = propertyElem.getElementsByTagName("value").item(0).getTextContent();
+ assertEquals(TEST_VAL, val);
+ }
+ }
+ assertTrue(foundSetting);
+ }
+
+ @Test
+ public void testBadFormat() throws Exception {
+ StringWriter sw = new StringWriter();
+ try {
+ ConfServlet.writeResponse(getTestConf(), sw, "not a format");
+ fail("writeResponse with bad format didn't throw!");
+ } catch (ConfServlet.BadFormatException bfe) {
+ // expected
+ }
+ assertEquals("", sw.toString());
+ }
+}
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-http/src/test/java/org/apache/hadoop/hbase/http/jmx/TestJMXJsonServlet.java
----------------------------------------------------------------------
diff --git a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/jmx/TestJMXJsonServlet.java b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/jmx/TestJMXJsonServlet.java
new file mode 100644
index 0000000..484162a
--- /dev/null
+++ b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/jmx/TestJMXJsonServlet.java
@@ -0,0 +1,134 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.hadoop.hbase.http.jmx;
+
+import java.net.HttpURLConnection;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.servlet.http.HttpServletResponse;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.hadoop.hbase.testclassification.MiscTests;
+import org.apache.hadoop.hbase.testclassification.SmallTests;
+import org.apache.hadoop.hbase.http.HttpServer;
+import org.apache.hadoop.hbase.http.HttpServerFunctionalTest;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+@Category({MiscTests.class, SmallTests.class})
+public class TestJMXJsonServlet extends HttpServerFunctionalTest {
+ private static final Log LOG = LogFactory.getLog(TestJMXJsonServlet.class);
+ private static HttpServer server;
+ private static URL baseUrl;
+
+ @BeforeClass public static void setup() throws Exception {
+ // Eclipse doesn't pick this up correctly from the plugin
+ // configuration in the pom.
+ System.setProperty(HttpServerFunctionalTest.TEST_BUILD_WEBAPPS, "target/test-classes/webapps");
+ server = createTestServer();
+ server.start();
+ baseUrl = getServerURL(server);
+ }
+
+ @AfterClass public static void cleanup() throws Exception {
+ server.stop();
+ }
+
+ public static void assertReFind(String re, String value) {
+ Pattern p = Pattern.compile(re);
+ Matcher m = p.matcher(value);
+ assertTrue("'"+p+"' does not match "+value, m.find());
+ }
+
+ @Test public void testQuery() throws Exception {
+ String result = readOutput(new URL(baseUrl, "/jmx?qry=java.lang:type=Runtime"));
+ LOG.info("/jmx?qry=java.lang:type=Runtime RESULT: "+result);
+ assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Runtime\"", result);
+ assertReFind("\"modelerType\"", result);
+
+ result = readOutput(new URL(baseUrl, "/jmx?qry=java.lang:type=Memory"));
+ LOG.info("/jmx?qry=java.lang:type=Memory RESULT: "+result);
+ assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Memory\"", result);
+ assertReFind("\"modelerType\"", result);
+
+ result = readOutput(new URL(baseUrl, "/jmx"));
+ LOG.info("/jmx RESULT: "+result);
+ assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Memory\"", result);
+
+ // test to get an attribute of a mbean
+ result = readOutput(new URL(baseUrl,
+ "/jmx?get=java.lang:type=Memory::HeapMemoryUsage"));
+ LOG.info("/jmx RESULT: "+result);
+ assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Memory\"", result);
+ assertReFind("\"committed\"\\s*:", result);
+
+ // negative test to get an attribute of a mbean
+ result = readOutput(new URL(baseUrl,
+ "/jmx?get=java.lang:type=Memory::"));
+ LOG.info("/jmx RESULT: "+result);
+ assertReFind("\"ERROR\"", result);
+
+ // test to get JSONP result
+ result = readOutput(new URL(baseUrl, "/jmx?qry=java.lang:type=Memory&callback=mycallback1"));
+ LOG.info("/jmx?qry=java.lang:type=Memory&callback=mycallback RESULT: "+result);
+ assertReFind("^mycallback1\\(\\{", result);
+ assertReFind("\\}\\);$", result);
+
+ // negative test to get an attribute of a mbean as JSONP
+ result = readOutput(new URL(baseUrl,
+ "/jmx?get=java.lang:type=Memory::&callback=mycallback2"));
+ LOG.info("/jmx RESULT: "+result);
+ assertReFind("^mycallback2\\(\\{", result);
+ assertReFind("\"ERROR\"", result);
+ assertReFind("\\}\\);$", result);
+
+ // test to get an attribute of a mbean as JSONP
+ result = readOutput(new URL(baseUrl,
+ "/jmx?get=java.lang:type=Memory::HeapMemoryUsage&callback=mycallback3"));
+ LOG.info("/jmx RESULT: "+result);
+ assertReFind("^mycallback3\\(\\{", result);
+ assertReFind("\"name\"\\s*:\\s*\"java.lang:type=Memory\"", result);
+ assertReFind("\"committed\"\\s*:", result);
+ assertReFind("\\}\\);$", result);
+
+ }
+
+ @Test
+ public void testDisallowedJSONPCallback() throws Exception {
+ String callback = "function(){alert('bigproblems!')};foo";
+ URL url = new URL(
+ baseUrl, "/jmx?qry=java.lang:type=Memory&callback="+URLEncoder.encode(callback, "UTF-8"));
+ HttpURLConnection cnxn = (HttpURLConnection) url.openConnection();
+ assertEquals(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, cnxn.getResponseCode());
+ }
+
+ @Test
+ public void testUnderscoresInJSONPCallback() throws Exception {
+ String callback = "my_function";
+ URL url = new URL(
+ baseUrl, "/jmx?qry=java.lang:type=Memory&callback="+URLEncoder.encode(callback, "UTF-8"));
+ HttpURLConnection cnxn = (HttpURLConnection) url.openConnection();
+ assertEquals(HttpServletResponse.SC_OK, cnxn.getResponseCode());
+ }
+}
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-http/src/test/java/org/apache/hadoop/hbase/http/lib/TestStaticUserWebFilter.java
----------------------------------------------------------------------
diff --git a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/lib/TestStaticUserWebFilter.java b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/lib/TestStaticUserWebFilter.java
new file mode 100644
index 0000000..3adca50
--- /dev/null
+++ b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/lib/TestStaticUserWebFilter.java
@@ -0,0 +1,86 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.hadoop.hbase.http.lib;
+
+import static org.junit.Assert.assertEquals;
+import static org.mockito.Mockito.mock;
+
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletRequestWrapper;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.fs.CommonConfigurationKeys;
+import org.apache.hadoop.hbase.testclassification.MiscTests;
+import org.apache.hadoop.hbase.testclassification.SmallTests;
+import org.apache.hadoop.hbase.http.ServerConfigurationKeys;
+import org.apache.hadoop.hbase.http.lib.StaticUserWebFilter.StaticUserFilter;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mockito;
+
+@Category({MiscTests.class, SmallTests.class})
+public class TestStaticUserWebFilter {
+ private FilterConfig mockConfig(String username) {
+ FilterConfig mock = Mockito.mock(FilterConfig.class);
+ Mockito.doReturn(username).when(mock).getInitParameter(
+ ServerConfigurationKeys.HBASE_HTTP_STATIC_USER);
+ return mock;
+ }
+
+ @Test
+ public void testFilter() throws Exception {
+ FilterConfig config = mockConfig("myuser");
+ StaticUserFilter suf = new StaticUserFilter();
+ suf.init(config);
+
+ ArgumentCaptor<HttpServletRequestWrapper> wrapperArg =
+ ArgumentCaptor.forClass(HttpServletRequestWrapper.class);
+
+ FilterChain chain = mock(FilterChain.class);
+
+ suf.doFilter(mock(HttpServletRequest.class), mock(ServletResponse.class),
+ chain);
+
+ Mockito.verify(chain).doFilter(wrapperArg.capture(), Mockito.<ServletResponse>anyObject());
+
+ HttpServletRequestWrapper wrapper = wrapperArg.getValue();
+ assertEquals("myuser", wrapper.getUserPrincipal().getName());
+ assertEquals("myuser", wrapper.getRemoteUser());
+
+ suf.destroy();
+ }
+
+ @Test
+ public void testOldStyleConfiguration() {
+ Configuration conf = new Configuration();
+ conf.set("dfs.web.ugi", "joe,group1,group2");
+ assertEquals("joe", StaticUserWebFilter.getUsernameFromConf(conf));
+ }
+
+ @Test
+ public void testConfiguration() {
+ Configuration conf = new Configuration();
+ conf.set(CommonConfigurationKeys.HADOOP_HTTP_STATIC_USER, "dr.stack");
+ assertEquals("dr.stack", StaticUserWebFilter.getUsernameFromConf(conf));
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-http/src/test/java/org/apache/hadoop/hbase/http/log/TestLogLevel.java
----------------------------------------------------------------------
diff --git a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/log/TestLogLevel.java b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/log/TestLogLevel.java
new file mode 100644
index 0000000..e14e3b4
--- /dev/null
+++ b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/log/TestLogLevel.java
@@ -0,0 +1,92 @@
+/**
+* Licensed to the Apache Software Foundation (ASF) under one
+* or more contributor license agreements. See the NOTICE file
+* distributed with this work for additional information
+* regarding copyright ownership. The ASF licenses this file
+* to you 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.
+*/
+package org.apache.hadoop.hbase.http.log;
+
+import static org.junit.Assert.assertTrue;
+
+import java.io.*;
+import java.net.*;
+
+import org.apache.hadoop.hbase.testclassification.MiscTests;
+import org.apache.hadoop.hbase.testclassification.SmallTests;
+import org.apache.hadoop.hbase.http.HttpServer;
+import org.apache.hadoop.net.NetUtils;
+import org.apache.commons.logging.*;
+import org.apache.commons.logging.impl.*;
+import org.apache.log4j.*;
+import org.junit.Test;
+import org.junit.experimental.categories.Category;
+
+@Category({MiscTests.class, SmallTests.class})
+public class TestLogLevel {
+ static final PrintStream out = System.out;
+
+ @Test (timeout=60000)
+ @SuppressWarnings("deprecation")
+ public void testDynamicLogLevel() throws Exception {
+ String logName = TestLogLevel.class.getName();
+ Log testlog = LogFactory.getLog(logName);
+
+ //only test Log4JLogger
+ if (testlog instanceof Log4JLogger) {
+ Logger log = ((Log4JLogger)testlog).getLogger();
+ log.debug("log.debug1");
+ log.info("log.info1");
+ log.error("log.error1");
+ assertTrue(!Level.ERROR.equals(log.getEffectiveLevel()));
+
+ HttpServer server = null;
+ try {
+ server = new HttpServer.Builder().setName("..")
+ .addEndpoint(new URI("http://localhost:0")).setFindPort(true)
+ .build();
+
+ server.start();
+ String authority = NetUtils.getHostPortString(server
+ .getConnectorAddress(0));
+
+ //servlet
+ URL url =
+ new URL("http://" + authority + "/logLevel?log=" + logName + "&level=" + Level.ERROR);
+ out.println("*** Connecting to " + url);
+ try (BufferedReader in = new BufferedReader(new InputStreamReader(url.openStream()))) {
+ for(String line; (line = in.readLine()) != null; out.println(line));
+ }
+ log.debug("log.debug2");
+ log.info("log.info2");
+ log.error("log.error2");
+ assertTrue(Level.ERROR.equals(log.getEffectiveLevel()));
+
+ //command line
+ String[] args = {"-setlevel", authority, logName, Level.DEBUG.toString()};
+ LogLevel.main(args);
+ log.debug("log.debug3");
+ log.info("log.info3");
+ log.error("log.error3");
+ assertTrue(Level.DEBUG.equals(log.getEffectiveLevel()));
+ } finally {
+ if (server != null) {
+ server.stop();
+ }
+ }
+ }
+ else {
+ out.println(testlog.getClass() + " not tested.");
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-http/src/test/java/org/apache/hadoop/hbase/http/resource/JerseyResource.java
----------------------------------------------------------------------
diff --git a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/resource/JerseyResource.java b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/resource/JerseyResource.java
new file mode 100644
index 0000000..bf0e609
--- /dev/null
+++ b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/resource/JerseyResource.java
@@ -0,0 +1,64 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+package org.apache.hadoop.hbase.http.resource;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.TreeMap;
+
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.Response;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.eclipse.jetty.util.ajax.JSON;
+
+/**
+ * A simple Jersey resource class TestHttpServer.
+ * The servlet simply puts the path and the op parameter in a map
+ * and return it in JSON format in the response.
+ */
+@Path("")
+public class JerseyResource {
+ private static final Log LOG = LogFactory.getLog(JerseyResource.class);
+
+ public static final String PATH = "path";
+ public static final String OP = "op";
+
+ @GET
+ @Path("{" + PATH + ":.*}")
+ @Produces({MediaType.APPLICATION_JSON})
+ public Response get(
+ @PathParam(PATH) @DefaultValue("UNKNOWN_" + PATH) final String path,
+ @QueryParam(OP) @DefaultValue("UNKNOWN_" + OP) final String op
+ ) throws IOException {
+ LOG.info("get: " + PATH + "=" + path + ", " + OP + "=" + op);
+
+ final Map<String, Object> m = new TreeMap<>();
+ m.put(PATH, path);
+ m.put(OP, op);
+ final String js = JSON.toString(m);
+ return Response.ok(js).type(MediaType.APPLICATION_JSON).build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-http/src/test/java/org/apache/hadoop/hbase/http/ssl/KeyStoreTestUtil.java
----------------------------------------------------------------------
diff --git a/hbase-http/src/test/java/org/apache/hadoop/hbase/http/ssl/KeyStoreTestUtil.java b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/ssl/KeyStoreTestUtil.java
new file mode 100644
index 0000000..35d6236
--- /dev/null
+++ b/hbase-http/src/test/java/org/apache/hadoop/hbase/http/ssl/KeyStoreTestUtil.java
@@ -0,0 +1,342 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+
+package org.apache.hadoop.hbase.http.ssl;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.Writer;
+import java.math.BigInteger;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.InvalidKeyException;
+import java.security.Key;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SecureRandom;
+import java.security.SignatureException;
+import java.security.cert.Certificate;
+import java.security.cert.CertificateEncodingException;
+import java.security.cert.X509Certificate;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import javax.security.auth.x500.X500Principal;
+
+import org.apache.hadoop.conf.Configuration;
+import org.apache.hadoop.security.ssl.FileBasedKeyStoresFactory;
+import org.apache.hadoop.security.ssl.SSLFactory;
+import org.bouncycastle.x509.X509V1CertificateGenerator;
+
+public class KeyStoreTestUtil {
+
+ public static String getClasspathDir(Class<?> klass) throws Exception {
+ String file = klass.getName();
+ file = file.replace('.', '/') + ".class";
+ URL url = Thread.currentThread().getContextClassLoader().getResource(file);
+ String baseDir = url.toURI().getPath();
+ baseDir = baseDir.substring(0, baseDir.length() - file.length() - 1);
+ return baseDir;
+ }
+
+ /**
+ * Create a self-signed X.509 Certificate.
+ *
+ * @param dn the X.509 Distinguished Name, eg "CN=Test, L=London, C=GB"
+ * @param pair the KeyPair
+ * @param days how many days from now the Certificate is valid for
+ * @param algorithm the signing algorithm, eg "SHA1withRSA"
+ * @return the self-signed certificate
+ */
+ public static X509Certificate generateCertificate(String dn, KeyPair pair, int days, String algorithm)
+ throws CertificateEncodingException, InvalidKeyException, IllegalStateException,
+ NoSuchProviderException, NoSuchAlgorithmException, SignatureException {
+ Date from = new Date();
+ Date to = new Date(from.getTime() + days * 86400000l);
+ BigInteger sn = new BigInteger(64, new SecureRandom());
+ KeyPair keyPair = pair;
+ X509V1CertificateGenerator certGen = new X509V1CertificateGenerator();
+ X500Principal dnName = new X500Principal(dn);
+
+ certGen.setSerialNumber(sn);
+ certGen.setIssuerDN(dnName);
+ certGen.setNotBefore(from);
+ certGen.setNotAfter(to);
+ certGen.setSubjectDN(dnName);
+ certGen.setPublicKey(keyPair.getPublic());
+ certGen.setSignatureAlgorithm(algorithm);
+ X509Certificate cert = certGen.generate(pair.getPrivate());
+ return cert;
+ }
+
+ public static KeyPair generateKeyPair(String algorithm)
+ throws NoSuchAlgorithmException {
+ KeyPairGenerator keyGen = KeyPairGenerator.getInstance(algorithm);
+ keyGen.initialize(1024);
+ return keyGen.genKeyPair();
+ }
+
+ private static KeyStore createEmptyKeyStore()
+ throws GeneralSecurityException, IOException {
+ KeyStore ks = KeyStore.getInstance("JKS");
+ ks.load(null, null); // initialize
+ return ks;
+ }
+
+ private static void saveKeyStore(KeyStore ks, String filename,
+ String password)
+ throws GeneralSecurityException, IOException {
+ FileOutputStream out = new FileOutputStream(filename);
+ try {
+ ks.store(out, password.toCharArray());
+ } finally {
+ out.close();
+ }
+ }
+
+ public static void createKeyStore(String filename,
+ String password, String alias,
+ Key privateKey, Certificate cert)
+ throws GeneralSecurityException, IOException {
+ KeyStore ks = createEmptyKeyStore();
+ ks.setKeyEntry(alias, privateKey, password.toCharArray(),
+ new Certificate[]{cert});
+ saveKeyStore(ks, filename, password);
+ }
+
+ /**
+ * Creates a keystore with a single key and saves it to a file.
+ *
+ * @param filename String file to save
+ * @param password String store password to set on keystore
+ * @param keyPassword String key password to set on key
+ * @param alias String alias to use for the key
+ * @param privateKey Key to save in keystore
+ * @param cert Certificate to use as certificate chain associated to key
+ * @throws GeneralSecurityException for any error with the security APIs
+ * @throws IOException if there is an I/O error saving the file
+ */
+ public static void createKeyStore(String filename,
+ String password, String keyPassword, String alias,
+ Key privateKey, Certificate cert)
+ throws GeneralSecurityException, IOException {
+ KeyStore ks = createEmptyKeyStore();
+ ks.setKeyEntry(alias, privateKey, keyPassword.toCharArray(),
+ new Certificate[]{cert});
+ saveKeyStore(ks, filename, password);
+ }
+
+ public static void createTrustStore(String filename,
+ String password, String alias,
+ Certificate cert)
+ throws GeneralSecurityException, IOException {
+ KeyStore ks = createEmptyKeyStore();
+ ks.setCertificateEntry(alias, cert);
+ saveKeyStore(ks, filename, password);
+ }
+
+ public static <T extends Certificate> void createTrustStore(
+ String filename, String password, Map<String, T> certs)
+ throws GeneralSecurityException, IOException {
+ KeyStore ks = createEmptyKeyStore();
+ for (Map.Entry<String, T> cert : certs.entrySet()) {
+ ks.setCertificateEntry(cert.getKey(), cert.getValue());
+ }
+ saveKeyStore(ks, filename, password);
+ }
+
+ public static void cleanupSSLConfig(String keystoresDir, String sslConfDir)
+ throws Exception {
+ File f = new File(keystoresDir + "/clientKS.jks");
+ f.delete();
+ f = new File(keystoresDir + "/serverKS.jks");
+ f.delete();
+ f = new File(keystoresDir + "/trustKS.jks");
+ f.delete();
+ f = new File(sslConfDir + "/ssl-client.xml");
+ f.delete();
+ f = new File(sslConfDir + "/ssl-server.xml");
+ f.delete();
+ }
+
+ /**
+ * Performs complete setup of SSL configuration in preparation for testing an
+ * SSLFactory. This includes keys, certs, keystores, truststores, the server
+ * SSL configuration file, the client SSL configuration file, and the master
+ * configuration file read by the SSLFactory.
+ *
+ * @param keystoresDir String directory to save keystores
+ * @param sslConfDir String directory to save SSL configuration files
+ * @param conf Configuration master configuration to be used by an SSLFactory,
+ * which will be mutated by this method
+ * @param useClientCert boolean true to make the client present a cert in the
+ * SSL handshake
+ */
+ public static void setupSSLConfig(String keystoresDir, String sslConfDir,
+ Configuration conf, boolean useClientCert)
+ throws Exception {
+ String clientKS = keystoresDir + "/clientKS.jks";
+ String clientPassword = "clientP";
+ String serverKS = keystoresDir + "/serverKS.jks";
+ String serverPassword = "serverP";
+ String trustKS = keystoresDir + "/trustKS.jks";
+ String trustPassword = "trustP";
+
+ File sslClientConfFile = new File(sslConfDir + "/ssl-client.xml");
+ File sslServerConfFile = new File(sslConfDir + "/ssl-server.xml");
+
+ Map<String, X509Certificate> certs = new HashMap<>();
+
+ if (useClientCert) {
+ KeyPair cKP = KeyStoreTestUtil.generateKeyPair("RSA");
+ X509Certificate cCert =
+ KeyStoreTestUtil.generateCertificate("CN=localhost, O=client", cKP, 30,
+ "SHA1withRSA");
+ KeyStoreTestUtil.createKeyStore(clientKS, clientPassword, "client",
+ cKP.getPrivate(), cCert);
+ certs.put("client", cCert);
+ }
+
+ KeyPair sKP = KeyStoreTestUtil.generateKeyPair("RSA");
+ X509Certificate sCert =
+ KeyStoreTestUtil.generateCertificate("CN=localhost, O=server", sKP, 30,
+ "SHA1withRSA");
+ KeyStoreTestUtil.createKeyStore(serverKS, serverPassword, "server",
+ sKP.getPrivate(), sCert);
+ certs.put("server", sCert);
+
+ KeyStoreTestUtil.createTrustStore(trustKS, trustPassword, certs);
+
+ Configuration clientSSLConf = createClientSSLConfig(clientKS, clientPassword,
+ clientPassword, trustKS);
+ Configuration serverSSLConf = createServerSSLConfig(serverKS, serverPassword,
+ serverPassword, trustKS);
+
+ saveConfig(sslClientConfFile, clientSSLConf);
+ saveConfig(sslServerConfFile, serverSSLConf);
+
+ conf.set(SSLFactory.SSL_HOSTNAME_VERIFIER_KEY, "ALLOW_ALL");
+ conf.set(SSLFactory.SSL_CLIENT_CONF_KEY, sslClientConfFile.getName());
+ conf.set(SSLFactory.SSL_SERVER_CONF_KEY, sslServerConfFile.getName());
+ conf.setBoolean(SSLFactory.SSL_REQUIRE_CLIENT_CERT_KEY, useClientCert);
+ }
+
+ /**
+ * Creates SSL configuration for a client.
+ *
+ * @param clientKS String client keystore file
+ * @param password String store password, or null to avoid setting store
+ * password
+ * @param keyPassword String key password, or null to avoid setting key
+ * password
+ * @param trustKS String truststore file
+ * @return Configuration for client SSL
+ */
+ public static Configuration createClientSSLConfig(String clientKS,
+ String password, String keyPassword, String trustKS) {
+ Configuration clientSSLConf = createSSLConfig(SSLFactory.Mode.CLIENT,
+ clientKS, password, keyPassword, trustKS);
+ return clientSSLConf;
+ }
+
+ /**
+ * Creates SSL configuration for a server.
+ *
+ * @param serverKS String server keystore file
+ * @param password String store password, or null to avoid setting store
+ * password
+ * @param keyPassword String key password, or null to avoid setting key
+ * password
+ * @param trustKS String truststore file
+ * @return Configuration for server SSL
+ */
+ public static Configuration createServerSSLConfig(String serverKS,
+ String password, String keyPassword, String trustKS) throws IOException {
+ Configuration serverSSLConf = createSSLConfig(SSLFactory.Mode.SERVER,
+ serverKS, password, keyPassword, trustKS);
+ return serverSSLConf;
+ }
+
+ /**
+ * Creates SSL configuration.
+ *
+ * @param mode SSLFactory.Mode mode to configure
+ * @param keystore String keystore file
+ * @param password String store password, or null to avoid setting store
+ * password
+ * @param keyPassword String key password, or null to avoid setting key
+ * password
+ * @param trustKS String truststore file
+ * @return Configuration for SSL
+ */
+ private static Configuration createSSLConfig(SSLFactory.Mode mode,
+ String keystore, String password, String keyPassword, String trustKS) {
+ String trustPassword = "trustP";
+
+ Configuration sslConf = new Configuration(false);
+ if (keystore != null) {
+ sslConf.set(FileBasedKeyStoresFactory.resolvePropertyName(mode,
+ FileBasedKeyStoresFactory.SSL_KEYSTORE_LOCATION_TPL_KEY), keystore);
+ }
+ if (password != null) {
+ sslConf.set(FileBasedKeyStoresFactory.resolvePropertyName(mode,
+ FileBasedKeyStoresFactory.SSL_KEYSTORE_PASSWORD_TPL_KEY), password);
+ }
+ if (keyPassword != null) {
+ sslConf.set(FileBasedKeyStoresFactory.resolvePropertyName(mode,
+ FileBasedKeyStoresFactory.SSL_KEYSTORE_KEYPASSWORD_TPL_KEY),
+ keyPassword);
+ }
+ if (trustKS != null) {
+ sslConf.set(FileBasedKeyStoresFactory.resolvePropertyName(mode,
+ FileBasedKeyStoresFactory.SSL_TRUSTSTORE_LOCATION_TPL_KEY), trustKS);
+ }
+ if (trustPassword != null) {
+ sslConf.set(FileBasedKeyStoresFactory.resolvePropertyName(mode,
+ FileBasedKeyStoresFactory.SSL_TRUSTSTORE_PASSWORD_TPL_KEY),
+ trustPassword);
+ }
+ sslConf.set(FileBasedKeyStoresFactory.resolvePropertyName(mode,
+ FileBasedKeyStoresFactory.SSL_TRUSTSTORE_RELOAD_INTERVAL_TPL_KEY), "1000");
+
+ return sslConf;
+ }
+
+ /**
+ * Saves configuration to a file.
+ *
+ * @param file File to save
+ * @param conf Configuration contents to write to file
+ * @throws IOException if there is an I/O error saving the file
+ */
+ public static void saveConfig(File file, Configuration conf)
+ throws IOException {
+ Writer writer = new FileWriter(file);
+ try {
+ conf.writeXml(writer);
+ } finally {
+ writer.close();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-http/src/test/resources/log4j.properties
----------------------------------------------------------------------
diff --git a/hbase-http/src/test/resources/log4j.properties b/hbase-http/src/test/resources/log4j.properties
new file mode 100644
index 0000000..c322699
--- /dev/null
+++ b/hbase-http/src/test/resources/log4j.properties
@@ -0,0 +1,68 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you 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.
+
+# Define some default values that can be overridden by system properties
+hbase.root.logger=INFO,console
+hbase.log.dir=.
+hbase.log.file=hbase.log
+
+# Define the root logger to the system property "hbase.root.logger".
+log4j.rootLogger=${hbase.root.logger}
+
+# Logging Threshold
+log4j.threshold=ALL
+
+#
+# Daily Rolling File Appender
+#
+log4j.appender.DRFA=org.apache.log4j.DailyRollingFileAppender
+log4j.appender.DRFA.File=${hbase.log.dir}/${hbase.log.file}
+
+# Rollver at midnight
+log4j.appender.DRFA.DatePattern=.yyyy-MM-dd
+
+# 30-day backup
+#log4j.appender.DRFA.MaxBackupIndex=30
+log4j.appender.DRFA.layout=org.apache.log4j.PatternLayout
+# Debugging Pattern format
+log4j.appender.DRFA.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %C{2}(%L): %m%n
+
+
+#
+# console
+# Add "console" to rootlogger above if you want to use this
+#
+log4j.appender.console=org.apache.log4j.ConsoleAppender
+log4j.appender.console.target=System.err
+log4j.appender.console.layout=org.apache.log4j.PatternLayout
+log4j.appender.console.layout.ConversionPattern=%d{ISO8601} %-5p [%t] %C{2}(%L): %m%n
+
+# Custom Logging levels
+
+#log4j.logger.org.apache.hadoop.fs.FSNamesystem=DEBUG
+
+log4j.logger.org.apache.hadoop=WARN
+log4j.logger.org.apache.zookeeper=ERROR
+log4j.logger.org.apache.hadoop.hbase=DEBUG
+
+#These settings are workarounds against spurious logs from the minicluster.
+#See HBASE-4709
+log4j.logger.org.apache.hadoop.metrics2.impl.MetricsConfig=WARN
+log4j.logger.org.apache.hadoop.metrics2.impl.MetricsSinkAdapter=WARN
+log4j.logger.org.apache.hadoop.metrics2.impl.MetricsSystemImpl=WARN
+log4j.logger.org.apache.hadoop.metrics2.util.MBeans=WARN
+# Enable this to get detailed connection error/retry logging.
+# log4j.logger.org.apache.hadoop.hbase.client.ConnectionImplementation=TRACE
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-http/src/test/resources/webapps/static/test.css
----------------------------------------------------------------------
diff --git a/hbase-http/src/test/resources/webapps/static/test.css b/hbase-http/src/test/resources/webapps/static/test.css
new file mode 100644
index 0000000..ae43828
--- /dev/null
+++ b/hbase-http/src/test/resources/webapps/static/test.css
@@ -0,0 +1,21 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+/**
+ * Test CSS file for content type handling - empty, since we just check
+ * returned content type!
+ */
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-http/src/test/resources/webapps/test/testjsp.jsp
----------------------------------------------------------------------
diff --git a/hbase-http/src/test/resources/webapps/test/testjsp.jsp b/hbase-http/src/test/resources/webapps/test/testjsp.jsp
new file mode 100644
index 0000000..540adf9
--- /dev/null
+++ b/hbase-http/src/test/resources/webapps/test/testjsp.jsp
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?><%!
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you 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.
+ */
+%>
+<%@ page contentType="text/html; charset=UTF-8" %>
+Hello world!
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTServer.java
----------------------------------------------------------------------
diff --git a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTServer.java b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTServer.java
index c2f6cf6..360ab9d 100644
--- a/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTServer.java
+++ b/hbase-rest/src/main/java/org/apache/hadoop/hbase/rest/RESTServer.java
@@ -20,10 +20,8 @@ package org.apache.hadoop.hbase.rest;
import java.lang.management.ManagementFactory;
import java.util.ArrayList;
-import java.util.HashSet;
import java.util.List;
import java.util.Map;
-import java.util.Set;
import java.util.EnumSet;
import java.util.concurrent.ArrayBlockingQueue;
@@ -46,7 +44,7 @@ import org.apache.hadoop.hbase.rest.filter.GzipFilter;
import org.apache.hadoop.hbase.rest.filter.RestCsrfPreventionFilter;
import org.apache.hadoop.hbase.security.UserProvider;
import org.apache.hadoop.hbase.util.DNS;
-import org.apache.hadoop.hbase.util.HttpServerUtil;
+import org.apache.hadoop.hbase.http.HttpServerUtil;
import org.apache.hadoop.hbase.util.Pair;
import org.apache.hadoop.hbase.util.Strings;
import org.apache.hadoop.hbase.util.VersionInfo;
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/HBaseRESTTestingUtility.java
----------------------------------------------------------------------
diff --git a/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/HBaseRESTTestingUtility.java b/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/HBaseRESTTestingUtility.java
index 0714c7b..4c977fd 100644
--- a/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/HBaseRESTTestingUtility.java
+++ b/hbase-rest/src/test/java/org/apache/hadoop/hbase/rest/HBaseRESTTestingUtility.java
@@ -24,7 +24,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.hbase.security.UserProvider;
-import org.apache.hadoop.hbase.util.HttpServerUtil;
+import org.apache.hadoop.hbase.http.HttpServerUtil;
import org.apache.hadoop.util.StringUtils;
import org.eclipse.jetty.server.HttpConfiguration;
@@ -99,7 +99,7 @@ public class HBaseRESTTestingUtility {
// get the port
testServletPort = ((ServerConnector)server.getConnectors()[0]).getLocalPort();
- LOG.info("started " + server.getClass().getName() + " on port " +
+ LOG.info("started " + server.getClass().getName() + " on port " +
testServletPort);
}
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-server/pom.xml
----------------------------------------------------------------------
diff --git a/hbase-server/pom.xml b/hbase-server/pom.xml
index 3a025d1..ea02f26 100644
--- a/hbase-server/pom.xml
+++ b/hbase-server/pom.xml
@@ -360,6 +360,16 @@
<artifactId>hbase-common</artifactId>
</dependency>
<dependency>
+ <groupId>org.apache.hbase</groupId>
+ <artifactId>hbase-http</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hbase</groupId>
+ <artifactId>hbase-http</artifactId>
+ <type>test-jar</type>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
<!--Needed by the visiblity tags and acl CPEP things
in here in hbase-server (that should be out in hbase-endpoints
or integrated). -->
@@ -460,48 +470,13 @@
</dependency>
<dependency>
<groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-util</artifactId>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-util-ajax</artifactId>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-jsp</artifactId>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-webapp</artifactId>
</dependency>
<dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-http</artifactId>
- </dependency>
- <dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-security</artifactId>
- </dependency>
- <dependency>
- <groupId>com.fasterxml.jackson.core</groupId>
- <artifactId>jackson-databind</artifactId>
- </dependency>
- <dependency>
- <groupId>org.glassfish.jersey.containers</groupId>
- <artifactId>jersey-container-servlet-core</artifactId>
- </dependency>
- <dependency>
<!--For JspC used in ant task-->
<groupId>org.glassfish.web</groupId>
<artifactId>javax.servlet.jsp</artifactId>
</dependency>
- <!-- Specifically needed for jetty-jsp, included
- to bypass version scanning that hits a bad repo
- see HBASE-18831 -->
- <dependency>
- <groupId>org.glassfish</groupId>
- <artifactId>javax.el</artifactId>
- </dependency>
<dependency>
<groupId>org.codehaus.jettison</groupId>
<artifactId>jettison</artifactId>
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-server/src/main/java/org/apache/hadoop/hbase/http/AdminAuthorizedServlet.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/AdminAuthorizedServlet.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/AdminAuthorizedServlet.java
deleted file mode 100644
index bd8570e..0000000
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/AdminAuthorizedServlet.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-package org.apache.hadoop.hbase.http;
-
-import java.io.IOException;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import org.apache.yetus.audience.InterfaceAudience;
-import org.apache.yetus.audience.InterfaceStability;
-import org.eclipse.jetty.servlet.DefaultServlet;
-
-/**
- * General servlet which is admin-authorized.
- */
-@InterfaceAudience.Private
-@InterfaceStability.Evolving
-public class AdminAuthorizedServlet extends DefaultServlet {
-
- private static final long serialVersionUID = 1L;
-
- @Override
- protected void doGet(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- // Do the authorization
- if (HttpServer.hasAdministratorAccess(getServletContext(), request,
- response)) {
- // Authorization is done. Just call super.
- super.doGet(request, response);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-server/src/main/java/org/apache/hadoop/hbase/http/ClickjackingPreventionFilter.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/ClickjackingPreventionFilter.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/ClickjackingPreventionFilter.java
deleted file mode 100644
index 9944d29..0000000
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/ClickjackingPreventionFilter.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-package org.apache.hadoop.hbase.http;
-
-import javax.servlet.Filter;
-import javax.servlet.FilterChain;
-import javax.servlet.FilterConfig;
-import javax.servlet.ServletException;
-import javax.servlet.ServletRequest;
-import javax.servlet.ServletResponse;
-import javax.servlet.http.HttpServletResponse;
-import java.io.IOException;
-
-import org.apache.yetus.audience.InterfaceAudience;
-import org.apache.hadoop.hbase.HBaseInterfaceAudience;
-
-@InterfaceAudience.LimitedPrivate(HBaseInterfaceAudience.CONFIG)
-public class ClickjackingPreventionFilter implements Filter {
-
- private FilterConfig filterConfig;
-
- @Override
- public void init(FilterConfig filterConfig) throws ServletException {
- this.filterConfig = filterConfig;
- }
-
- @Override
- public void doFilter(ServletRequest req, ServletResponse res,
- FilterChain chain)
- throws IOException, ServletException {
- HttpServletResponse httpRes = (HttpServletResponse) res;
- httpRes.addHeader("X-Frame-Options", filterConfig.getInitParameter("xframeoptions"));
- chain.doFilter(req, res);
- }
-
- @Override
- public void destroy() {
- }
-
-}
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-server/src/main/java/org/apache/hadoop/hbase/http/FilterContainer.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/FilterContainer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/FilterContainer.java
deleted file mode 100644
index 7a79acc..0000000
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/FilterContainer.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-package org.apache.hadoop.hbase.http;
-
-import java.util.Map;
-
-/**
- * A container interface to add javax.servlet.Filter.
- */
-public interface FilterContainer {
- /**
- * Add a filter to the container.
- * @param name Filter name
- * @param classname Filter class name
- * @param parameters a map from parameter names to initial values
- */
- void addFilter(String name, String classname, Map<String, String> parameters);
- /**
- * Add a global filter to the container - This global filter will be
- * applied to all available web contexts.
- * @param name filter name
- * @param classname filter class name
- * @param parameters a map from parameter names to initial values
- */
- void addGlobalFilter(String name, String classname, Map<String, String> parameters);
-}
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-server/src/main/java/org/apache/hadoop/hbase/http/FilterInitializer.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/FilterInitializer.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/FilterInitializer.java
deleted file mode 100644
index e033c10..0000000
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/FilterInitializer.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-package org.apache.hadoop.hbase.http;
-
-import org.apache.hadoop.conf.Configuration;
-
-/**
- * Initialize a javax.servlet.Filter.
- */
-public abstract class FilterInitializer {
- /**
- * Initialize a Filter to a FilterContainer.
- * @param container The filter container
- * @param conf Configuration for run-time parameters
- */
- public abstract void initFilter(FilterContainer container, Configuration conf);
-}
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HtmlQuoting.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HtmlQuoting.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HtmlQuoting.java
deleted file mode 100644
index 60a74b7..0000000
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HtmlQuoting.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-package org.apache.hadoop.hbase.http;
-
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-/**
- * This class is responsible for quoting HTML characters.
- */
-public class HtmlQuoting {
- private static final byte[] ampBytes = "&".getBytes();
- private static final byte[] aposBytes = "'".getBytes();
- private static final byte[] gtBytes = ">".getBytes();
- private static final byte[] ltBytes = "<".getBytes();
- private static final byte[] quotBytes = """.getBytes();
-
- /**
- * Does the given string need to be quoted?
- * @param data the string to check
- * @param off the starting position
- * @param len the number of bytes to check
- * @return does the string contain any of the active html characters?
- */
- public static boolean needsQuoting(byte[] data, int off, int len) {
- if (off+len > data.length) {
- throw new IllegalStateException("off+len=" + off+len + " should be lower"
- + " than data length=" + data.length);
- }
- for(int i=off; i< off+len; ++i) {
- switch(data[i]) {
- case '&':
- case '<':
- case '>':
- case '\'':
- case '"':
- return true;
- default:
- break;
- }
- }
- return false;
- }
-
- /**
- * Does the given string need to be quoted?
- * @param str the string to check
- * @return does the string contain any of the active html characters?
- */
- public static boolean needsQuoting(String str) {
- if (str == null) {
- return false;
- }
- byte[] bytes = str.getBytes();
- return needsQuoting(bytes, 0 , bytes.length);
- }
-
- /**
- * Quote all of the active HTML characters in the given string as they
- * are added to the buffer.
- * @param output the stream to write the output to
- * @param buffer the byte array to take the characters from
- * @param off the index of the first byte to quote
- * @param len the number of bytes to quote
- */
- public static void quoteHtmlChars(OutputStream output, byte[] buffer,
- int off, int len) throws IOException {
- for(int i=off; i < off+len; i++) {
- switch (buffer[i]) {
- case '&': output.write(ampBytes); break;
- case '<': output.write(ltBytes); break;
- case '>': output.write(gtBytes); break;
- case '\'': output.write(aposBytes); break;
- case '"': output.write(quotBytes); break;
- default: output.write(buffer, i, 1);
- }
- }
- }
-
- /**
- * Quote the given item to make it html-safe.
- * @param item the string to quote
- * @return the quoted string
- */
- public static String quoteHtmlChars(String item) {
- if (item == null) {
- return null;
- }
- byte[] bytes = item.getBytes();
- if (needsQuoting(bytes, 0, bytes.length)) {
- ByteArrayOutputStream buffer = new ByteArrayOutputStream();
- try {
- quoteHtmlChars(buffer, bytes, 0, bytes.length);
- } catch (IOException ioe) {
- // Won't happen, since it is a bytearrayoutputstream
- }
- return buffer.toString();
- } else {
- return item;
- }
- }
-
- /**
- * Return an output stream that quotes all of the output.
- * @param out the stream to write the quoted output to
- * @return a new stream that the application show write to
- * @throws IOException if the underlying output fails
- */
- public static OutputStream quoteOutputStream(final OutputStream out
- ) throws IOException {
- return new OutputStream() {
- private byte[] data = new byte[1];
- @Override
- public void write(byte[] data, int off, int len) throws IOException {
- quoteHtmlChars(out, data, off, len);
- }
-
- @Override
- public void write(int b) throws IOException {
- data[0] = (byte) b;
- quoteHtmlChars(out, data, 0, 1);
- }
-
- @Override
- public void flush() throws IOException {
- out.flush();
- }
-
- @Override
- public void close() throws IOException {
- out.close();
- }
- };
- }
-
- /**
- * Remove HTML quoting from a string.
- * @param item the string to unquote
- * @return the unquoted string
- */
- public static String unquoteHtmlChars(String item) {
- if (item == null) {
- return null;
- }
- int next = item.indexOf('&');
- // nothing was quoted
- if (next == -1) {
- return item;
- }
- int len = item.length();
- int posn = 0;
- StringBuilder buffer = new StringBuilder();
- while (next != -1) {
- buffer.append(item.substring(posn, next));
- if (item.startsWith("&", next)) {
- buffer.append('&');
- next += 5;
- } else if (item.startsWith("'", next)) {
- buffer.append('\'');
- next += 6;
- } else if (item.startsWith(">", next)) {
- buffer.append('>');
- next += 4;
- } else if (item.startsWith("<", next)) {
- buffer.append('<');
- next += 4;
- } else if (item.startsWith(""", next)) {
- buffer.append('"');
- next += 6;
- } else {
- int end = item.indexOf(';', next)+1;
- if (end == 0) {
- end = len;
- }
- throw new IllegalArgumentException("Bad HTML quoting for " +
- item.substring(next,end));
- }
- posn = next;
- next = item.indexOf('&', posn);
- }
- buffer.append(item.substring(posn, len));
- return buffer.toString();
- }
-
- public static void main(String[] args) throws Exception {
- if (args.length == 0) {
- throw new IllegalArgumentException("Please provide some arguments");
- }
- for(String arg:args) {
- System.out.println("Original: " + arg);
- String quoted = quoteHtmlChars(arg);
- System.out.println("Quoted: "+ quoted);
- String unquoted = unquoteHtmlChars(quoted);
- System.out.println("Unquoted: " + unquoted);
- System.out.println();
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HttpConfig.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HttpConfig.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HttpConfig.java
deleted file mode 100644
index b9dde23..0000000
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HttpConfig.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-package org.apache.hadoop.hbase.http;
-
-import org.apache.yetus.audience.InterfaceAudience;
-import org.apache.yetus.audience.InterfaceStability;
-import org.apache.hadoop.conf.Configuration;
-
-/**
- * Statics to get access to Http related configuration.
- */
-@InterfaceAudience.Private
-@InterfaceStability.Unstable
-public class HttpConfig {
- private Policy policy;
- public enum Policy {
- HTTP_ONLY,
- HTTPS_ONLY,
- HTTP_AND_HTTPS;
-
- public Policy fromString(String value) {
- if (HTTPS_ONLY.name().equalsIgnoreCase(value)) {
- return HTTPS_ONLY;
- } else if (HTTP_AND_HTTPS.name().equalsIgnoreCase(value)) {
- return HTTP_AND_HTTPS;
- }
- return HTTP_ONLY;
- }
-
- public boolean isHttpEnabled() {
- return this == HTTP_ONLY || this == HTTP_AND_HTTPS;
- }
-
- public boolean isHttpsEnabled() {
- return this == HTTPS_ONLY || this == HTTP_AND_HTTPS;
- }
- }
-
- public HttpConfig(final Configuration conf) {
- boolean sslEnabled = conf.getBoolean(
- ServerConfigurationKeys.HBASE_SSL_ENABLED_KEY,
- ServerConfigurationKeys.HBASE_SSL_ENABLED_DEFAULT);
- policy = sslEnabled ? Policy.HTTPS_ONLY : Policy.HTTP_ONLY;
- if (sslEnabled) {
- conf.addResource("ssl-server.xml");
- conf.addResource("ssl-client.xml");
- }
- }
-
- public void setPolicy(Policy policy) {
- this.policy = policy;
- }
-
- public boolean isSecure() {
- return policy == Policy.HTTPS_ONLY;
- }
-
- public String getSchemePrefix() {
- return (isSecure()) ? "https://" : "http://";
- }
-
- public String getScheme(Policy policy) {
- return policy == Policy.HTTPS_ONLY ? "https://" : "http://";
- }
-}
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HttpRequestLog.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HttpRequestLog.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HttpRequestLog.java
deleted file mode 100644
index cfc0640..0000000
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HttpRequestLog.java
+++ /dev/null
@@ -1,93 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-package org.apache.hadoop.hbase.http;
-
-import java.util.HashMap;
-
-import org.apache.commons.logging.impl.Log4JLogger;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogConfigurationException;
-import org.apache.commons.logging.LogFactory;
-import org.apache.log4j.Appender;
-import org.apache.log4j.Logger;
-
-import org.eclipse.jetty.server.RequestLog;
-import org.eclipse.jetty.server.NCSARequestLog;
-
-/**
- * RequestLog object for use with Http
- */
-public class HttpRequestLog {
-
- private static final Log LOG = LogFactory.getLog(HttpRequestLog.class);
- private static final HashMap<String, String> serverToComponent;
-
- static {
- serverToComponent = new HashMap<>();
- serverToComponent.put("master", "master");
- serverToComponent.put("region", "regionserver");
- }
-
- public static RequestLog getRequestLog(String name) {
-
- String lookup = serverToComponent.get(name);
- if (lookup != null) {
- name = lookup;
- }
- String loggerName = "http.requests." + name;
- String appenderName = name + "requestlog";
- Log logger = LogFactory.getLog(loggerName);
-
- if (logger instanceof Log4JLogger) {
- Log4JLogger httpLog4JLog = (Log4JLogger)logger;
- Logger httpLogger = httpLog4JLog.getLogger();
- Appender appender = null;
-
- try {
- appender = httpLogger.getAppender(appenderName);
- } catch (LogConfigurationException e) {
- LOG.warn("Http request log for " + loggerName
- + " could not be created");
- throw e;
- }
-
- if (appender == null) {
- LOG.info("Http request log for " + loggerName
- + " is not defined");
- return null;
- }
-
- if (appender instanceof HttpRequestLogAppender) {
- HttpRequestLogAppender requestLogAppender
- = (HttpRequestLogAppender)appender;
- NCSARequestLog requestLog = new NCSARequestLog();
- requestLog.setFilename(requestLogAppender.getFilename());
- requestLog.setRetainDays(requestLogAppender.getRetainDays());
- return requestLog;
- } else {
- LOG.warn("Jetty request log for " + loggerName
- + " was of the wrong class");
- return null;
- }
- }
- else {
- LOG.warn("Jetty request log can only be enabled using Log4j");
- return null;
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/hbase/blob/3969b853/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HttpRequestLogAppender.java
----------------------------------------------------------------------
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HttpRequestLogAppender.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HttpRequestLogAppender.java
deleted file mode 100644
index 8039b34..0000000
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/http/HttpRequestLogAppender.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/**
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you 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.
- */
-package org.apache.hadoop.hbase.http;
-
-import org.apache.log4j.spi.LoggingEvent;
-import org.apache.log4j.AppenderSkeleton;
-
-/**
- * Log4j Appender adapter for HttpRequestLog
- */
-public class HttpRequestLogAppender extends AppenderSkeleton {
-
- private String filename;
- private int retainDays;
-
- public HttpRequestLogAppender() {
- }
-
- public void setRetainDays(int retainDays) {
- this.retainDays = retainDays;
- }
-
- public int getRetainDays() {
- return retainDays;
- }
-
- public void setFilename(String filename) {
- this.filename = filename;
- }
-
- public String getFilename() {
- return filename;
- }
-
- @Override
- public void append(LoggingEvent event) {
- }
-
- @Override
- public void close() {
- // Do nothing, we don't have close() on AppenderSkeleton.
- }
-
- @Override
- public boolean requiresLayout() {
- return false;
- }
-}