Skip to content
This repository has been archived by the owner on Feb 9, 2021. It is now read-only.

Commit

Permalink
HADOOP-7594. Support HTTP REST in HttpServer.
Browse files Browse the repository at this point in the history
  • Loading branch information
szetszwo committed Sep 6, 2011
1 parent 53f7077 commit ae0a1bb
Show file tree
Hide file tree
Showing 6 changed files with 130 additions and 8 deletions.
2 changes: 2 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,8 @@ Release 0.20.205.0 - unreleased
HADOOP-7539. merge hadoop archive goodness from trunk to .20 (John George
via mahadev)

HADOOP-7594. Support HTTP REST in HttpServer. (szetszwo)

Release 0.20.204.0 - 2011-8-25

NEW FEATURES
Expand Down
17 changes: 17 additions & 0 deletions ivy.xml
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,23 @@
rev="${jetty-util.version}"
conf="jetty->master"/>

<dependency org="asm"
name="asm"
rev="${asm.version}"
conf="jetty->master"/>
<dependency org="com.sun.jersey"
name="jersey-core"
rev="${jersey-core.version}"
conf="jetty->master"/>
<dependency org="com.sun.jersey"
name="jersey-json"
rev="${jersey-json.version}"
conf="jetty->master"/>
<dependency org="com.sun.jersey"
name="jersey-server"
rev="${jersey-server.version}"
conf="jetty->master"/>

<dependency org="tomcat"
name="jasper-runtime"
rev="${jasper.version}"
Expand Down
4 changes: 4 additions & 0 deletions ivy/libraries.properties
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ hadoop-gpl-compression.version=0.1.0
apacheant.version=1.7.0
ant-task.version=2.0.10

asm.version=3.2
aspectj.version=1.6.5

checkstyle.version=4.2
Expand Down Expand Up @@ -57,6 +58,9 @@ jsp-2.1.version=6.1.14
jets3t.version=0.6.1
jetty.version=6.1.26
jetty-util.version=6.1.26
jersey-core.version=1.8
jersey-json.version=1.8
jersey-server.version=1.8
junit.version=4.5
jdeb.version=0.8
jdiff.version=1.0.9
Expand Down
23 changes: 20 additions & 3 deletions src/core/org/apache/hadoop/http/HttpServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,14 @@
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.CommonConfigurationKeys;
import org.apache.hadoop.jmx.JMXJsonServlet;
import org.apache.hadoop.log.LogLevel;
import org.apache.hadoop.security.Krb5AndCertsSslSocketConnector;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.Krb5AndCertsSslSocketConnector.MODE;
import org.apache.hadoop.security.UserGroupInformation;
import org.apache.hadoop.security.authorize.AccessControlList;
import org.apache.hadoop.util.ReflectionUtils;
import org.apache.hadoop.fs.CommonConfigurationKeys;

import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Handler;
import org.mortbay.jetty.Server;
Expand All @@ -68,6 +67,8 @@
import org.mortbay.thread.QueuedThreadPool;
import org.mortbay.util.MultiException;

import com.sun.jersey.spi.container.servlet.ServletContainer;

/**
* Create a Jetty embedded server to answer http requests. The primary goal
* is to serve up status information for the server.
Expand Down Expand Up @@ -307,6 +308,22 @@ public void setAttribute(Context context, String name, Object value) {
context.setAttribute(name, value);
}

/**
* Add a Jersey resource package.
* @param packageName The Java package name containing the Jersey resource.
* @param pathSpec The path spec for the servlet
*/
public void addJerseyResourcePackage(final String packageName,
final String pathSpec) {
LOG.info("addJerseyResourcePackage: packageName=" + packageName
+ ", pathSpec=" + pathSpec);
final ServletHolder sh = new ServletHolder(ServletContainer.class);
sh.setInitParameter("com.sun.jersey.config.property.resourceConfigClass",
"com.sun.jersey.api.core.PackagesResourceConfig");
sh.setInitParameter("com.sun.jersey.config.property.packages", packageName);
webAppContext.addServlet(sh, pathSpec);
}

/**
* Add a servlet in the server.
* @param name The name of the servlet (can be passed as null)
Expand Down
28 changes: 23 additions & 5 deletions src/test/org/apache/hadoop/http/TestHttpServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,18 @@
import org.apache.commons.logging.LogFactory;
import org.apache.hadoop.conf.Configuration;
import org.apache.hadoop.fs.CommonConfigurationKeys;
import org.apache.hadoop.http.resource.JerseyResource;
import org.apache.hadoop.security.Groups;
import org.apache.hadoop.security.ShellBasedUnixGroupsMapping;
import org.apache.hadoop.security.authorize.AccessControlList;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mortbay.util.ajax.JSON;

public class TestHttpServer {
static final Log LOG = LogFactory.getLog(TestHttpServer.class);

private HttpServer server;
private URL baseUrl;

Expand All @@ -68,7 +72,7 @@ public void doGet(HttpServletRequest request,
) throws ServletException, IOException {
PrintStream out = new PrintStream(response.getOutputStream());
Map<String, String[]> params = request.getParameterMap();
SortedSet<String> keys = new TreeSet(params.keySet());
SortedSet<String> keys = new TreeSet<String>(params.keySet());
for(String key: keys) {
out.print(key);
out.print(':');
Expand All @@ -94,7 +98,7 @@ public void doGet(HttpServletRequest request,
HttpServletResponse response
) throws ServletException, IOException {
PrintStream out = new PrintStream(response.getOutputStream());
SortedSet<String> sortedKeys = new TreeSet();
SortedSet<String> sortedKeys = new TreeSet<String>();
Enumeration<String> keys = request.getParameterNames();
while(keys.hasMoreElements()) {
sortedKeys.add(keys.nextElement());
Expand Down Expand Up @@ -127,6 +131,8 @@ private String readOutput(URL url) throws IOException {
server = new HttpServer("test", "0.0.0.0", 0, true);
server.addServlet("echo", "/echo", EchoServlet.class);
server.addServlet("echomap", "/echomap", EchoMapServlet.class);
server.addJerseyResourcePackage(
JerseyResource.class.getPackage().getName(), "/jersey/*");
server.start();
int port = server.getPort();
baseUrl = new URL("http://localhost:" + port + "/");
Expand Down Expand Up @@ -158,9 +164,6 @@ private String readOutput(URL url) throws IOException {
*
*/
public static class DummyServletFilter implements Filter {

private static final Log LOG = LogFactory.getLog(
DummyServletFilter.class);
@Override
public void destroy() { }

Expand Down Expand Up @@ -306,4 +309,19 @@ public void testAuthorizationOfDefaultServlets() throws Exception {
}
myServer.stop();
}

@SuppressWarnings("unchecked")
private static Map<String, Object> parse(String jsonString) {
return (Map<String, Object>)JSON.parse(jsonString);
}

@Test public void testJersey() throws Exception {
LOG.info("BEGIN testJersey()");
final String js = readOutput(new URL(baseUrl, "/jersey/foo?op=bar"));
final Map<String, Object> m = parse(js);
LOG.info("m=" + m);
assertEquals("foo", m.get(JerseyResource.PATH));
assertEquals("bar", m.get(JerseyResource.OP));
LOG.info("END testJersey()");
}
}
64 changes: 64 additions & 0 deletions src/test/org/apache/hadoop/http/resource/JerseyResource.java
Original file line number Diff line number Diff line change
@@ -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.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.mortbay.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 {
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<String, Object>();
m.put(PATH, path);
m.put(OP, op);
final String js = JSON.toString(m);
return Response.ok(js).type(MediaType.APPLICATION_JSON).build();
}
}

0 comments on commit ae0a1bb

Please sign in to comment.