Till Westmann has uploaded a new change for review.

  https://asterix-gerrit.ics.uci.edu/1508

Change subject: ASTERIXDB-1786: Remove Hyracks Servlets.
......................................................................

ASTERIXDB-1786: Remove Hyracks Servlets.

Change-Id: Ifcd240591d12baab2db4ce3163c635a1dde5c4ba
---
M asterixdb/asterix-app/pom.xml
M 
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
M 
asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryWebInterfaceServlet.java
M asterixdb/asterix-common/pom.xml
M asterixdb/pom.xml
M hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/pom.xml
M 
hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerService.java
M 
hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/JobsRESTAPIFunction.java
M 
hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/WebServer.java
M 
hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/util/JSONOutputRequestHandler.java
M hyracks-fullstack/hyracks/hyracks-http/pom.xml
M 
hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/AbstractServlet.java
A 
hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/StaticResourceServlet.java
M hyracks-fullstack/pom.xml
14 files changed, 205 insertions(+), 130 deletions(-)


  git pull ssh://asterix-gerrit.ics.uci.edu:29418/asterixdb 
refs/changes/08/1508/1

diff --git a/asterixdb/asterix-app/pom.xml b/asterixdb/asterix-app/pom.xml
index 99e58df..7ce71b7 100644
--- a/asterixdb/asterix-app/pom.xml
+++ b/asterixdb/asterix-app/pom.xml
@@ -463,7 +463,6 @@
     <dependency>
       <groupId>io.netty</groupId>
       <artifactId>netty-all</artifactId>
-      <version>4.1.6.Final</version>
     </dependency>
   </dependencies>
 </project>
\ No newline at end of file
diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
index 95eb6fb..db824aa 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/ApiServlet.java
@@ -82,7 +82,7 @@
         this.componentProvider = componentProvider;
     }
 
-    public void doPost(IServletRequest request, IServletResponse response) {
+    protected void doPost(IServletRequest request, IServletResponse response) {
         // Query language
         ILangCompilationProvider compilationProvider = 
"AQL".equals(request.getParameter("query-language"))
                 ? aqlCompilationProvider : sqlppCompilationProvider;
@@ -156,7 +156,7 @@
         }
     }
 
-    public void doGet(IServletRequest request, IServletResponse response) {
+    protected void doGet(IServletRequest request, IServletResponse response) {
         String resourcePath = null;
         String requestURI = request.getHttpRequest().uri();
 
@@ -188,7 +188,7 @@
                 outputStream.close();
                 return;
             }
-            String type = 
IServlet.ContentType.mime(QueryWebInterfaceServlet.extension(resourcePath));
+            String type = IServlet.ContentType.mime(extension(resourcePath));
             ServletUtils.setContentType(response, "".equals(type) ? 
IServlet.ContentType.TEXT_PLAIN : type,
                     IServlet.Encoding.UTF8);
             writeOutput(response, is, resourcePath);
@@ -199,6 +199,11 @@
         }
     }
 
+    public static String extension(String path) {
+        int i = path.lastIndexOf('.');
+        return i < 1 ? "" : path.substring(i);
+    }
+
     private void writeOutput(IServletResponse response, InputStream is, String 
resourcePath) throws IOException {
         try (InputStreamReader isr = new InputStreamReader(is); BufferedReader 
br = new BufferedReader(isr)) {
             StringBuilder sb = new StringBuilder();
diff --git 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryWebInterfaceServlet.java
 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryWebInterfaceServlet.java
index 96df30f..bc9b115 100644
--- 
a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryWebInterfaceServlet.java
+++ 
b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryWebInterfaceServlet.java
@@ -19,8 +19,6 @@
 package org.apache.asterix.api.http.server;
 
 import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
 import java.io.PrintWriter;
 import java.util.concurrent.ConcurrentMap;
 import java.util.logging.Level;
@@ -28,85 +26,35 @@
 
 import org.apache.asterix.common.config.ExternalProperties;
 import org.apache.asterix.runtime.utils.AppContextInfo;
-import org.apache.commons.io.IOUtils;
 import org.apache.hyracks.http.api.IServlet;
 import org.apache.hyracks.http.api.IServletRequest;
 import org.apache.hyracks.http.api.IServletResponse;
-import org.apache.hyracks.http.server.AbstractServlet;
+import org.apache.hyracks.http.server.StaticResourceServlet;
 import org.apache.hyracks.http.server.util.ServletUtils;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 
-import io.netty.handler.codec.http.HttpMethod;
 import io.netty.handler.codec.http.HttpResponseStatus;
 
-public class QueryWebInterfaceServlet extends AbstractServlet {
+public class QueryWebInterfaceServlet extends StaticResourceServlet {
     private static final Logger LOGGER = 
Logger.getLogger(QueryWebInterfaceServlet.class.getName());
 
     public QueryWebInterfaceServlet(ConcurrentMap<String, Object> ctx, 
String[] paths) {
         super(ctx, paths);
     }
 
-    @Override
-    public void handle(IServletRequest request, IServletResponse response) {
-        try {
-            if (request.getHttpRequest().method() == HttpMethod.GET) {
-                doGet(request, response);
-            } else if (request.getHttpRequest().method() == HttpMethod.POST) {
-                doPost(response);
-            } else {
-                response.setStatus(HttpResponseStatus.METHOD_NOT_ALLOWED);
-            }
-        } catch (IOException e) {
-            LOGGER.log(Level.WARNING, "Failure setting content type", e);
-            response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);
-            return;
-        }
-    }
-
-    private void doGet(IServletRequest request, IServletResponse response) 
throws IOException {
-        String resourcePath = null;
+    protected void doGet(IServletRequest request, IServletResponse response) 
throws IOException {
         String requestURI = request.getHttpRequest().uri();
-        response.setStatus(HttpResponseStatus.OK);
-
         if ("/".equals(requestURI)) {
             ServletUtils.setContentType(response, 
IServlet.ContentType.TEXT_HTML);
-            resourcePath = "/queryui/queryui.html";
+            deliverResource("/queryui/queryui.html", response);
         } else {
-            resourcePath = requestURI;
-        }
-
-        try (InputStream is = 
QueryWebInterfaceServlet.class.getResourceAsStream(resourcePath)) {
-            if (is == null) {
-                response.setStatus(HttpResponseStatus.NOT_FOUND);
-                return;
-            }
-            int i = resourcePath.lastIndexOf('.');
-            if (i >= 0) {
-                String extension = resourcePath.substring(i);
-                String mime = IServlet.ContentType.mime(extension);
-                if (mime != null) {
-                    OutputStream out = response.outputStream();
-                    ServletUtils.setContentType(response, mime);
-                    try {
-                        IOUtils.copy(is, out);
-                    } catch (Exception e) {
-                        LOGGER.log(Level.WARNING, "Failure copying response", 
e);
-                    } finally {
-                        if (out != null) {
-                            IOUtils.closeQuietly(out);
-                        }
-                        IOUtils.closeQuietly(is);
-                    }
-                    return;
-                }
-            }
-            response.setStatus(HttpResponseStatus.BAD_REQUEST);
+            deliverResource(requestURI, response);
         }
     }
 
-    private void doPost(IServletResponse response) throws IOException {
+    protected void doPost(IServletRequest request, IServletResponse response) 
throws IOException {
         ServletUtils.setContentType(response, 
IServlet.ContentType.APPLICATION_JSON, IServlet.Encoding.UTF8);
         ExternalProperties externalProperties = 
AppContextInfo.INSTANCE.getExternalProperties();
         response.setStatus(HttpResponseStatus.OK);
@@ -125,10 +73,5 @@
         } catch (Exception e) {
             LOGGER.log(Level.SEVERE, "Failure setting response status", e);
         }
-    }
-
-    public static String extension(String path) {
-        int i = path.lastIndexOf('.');
-        return i < 1 ? "" : path.substring(i);
     }
 }
diff --git a/asterixdb/asterix-common/pom.xml b/asterixdb/asterix-common/pom.xml
index c2f1c6a..d642b57 100644
--- a/asterixdb/asterix-common/pom.xml
+++ b/asterixdb/asterix-common/pom.xml
@@ -295,7 +295,6 @@
     <dependency>
       <groupId>io.netty</groupId>
       <artifactId>netty-all</artifactId>
-      <version>4.1.6.Final</version>
     </dependency>
     <dependency>
       <groupId>com.fasterxml.jackson.core</groupId>
diff --git a/asterixdb/pom.xml b/asterixdb/pom.xml
index 57488bc..8226764 100644
--- a/asterixdb/pom.xml
+++ b/asterixdb/pom.xml
@@ -1011,6 +1011,11 @@
         <version>2.33</version>
       </dependency>
       <dependency>
+        <groupId>io.netty</groupId>
+        <artifactId>netty-all</artifactId>
+        <version>4.1.6.Final</version>
+      </dependency>
+      <dependency>
         <groupId>org.apache.httpcomponents</groupId>
         <artifactId>httpclient</artifactId>
         <version>4.5.2</version>
diff --git 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/pom.xml 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/pom.xml
index c960da9..76ce1b3 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/pom.xml
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/pom.xml
@@ -75,10 +75,19 @@
   <dependencies>
     <dependency>
       <groupId>org.apache.hyracks</groupId>
+      <artifactId>hyracks-http</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.hyracks</groupId>
       <artifactId>hyracks-control-common</artifactId>
       <version>${project.version}</version>
     </dependency>
     <dependency>
+      <groupId>io.netty</groupId>
+      <artifactId>netty-all</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.eclipse.jetty</groupId>
       <artifactId>jetty-server</artifactId>
     </dependency>
diff --git 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerService.java
 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerService.java
index 37c4177..897a47a 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerService.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/ClusterControllerService.java
@@ -137,7 +137,7 @@
         IIPCI ciIPCI = new ClientInterfaceIPCI(this);
         clientIPC = new IPCSystem(new 
InetSocketAddress(ccConfig.clientNetIpAddress, ccConfig.clientNetPort), ciIPCI,
                 new JavaSerializationBasedPayloadSerializerDeserializer());
-        webServer = new WebServer(this);
+        webServer = new WebServer(this, ccConfig.httpPort);
 
         // WorkQueue is in charge of heartbeat as well as other events.
         workQueue = new WorkQueue("ClusterController", Thread.MAX_PRIORITY);
@@ -173,7 +173,6 @@
         LOGGER.log(Level.INFO, "Starting ClusterControllerService: " + this);
         clusterIPC.start();
         clientIPC.start();
-        webServer.setPort(ccConfig.httpPort);
         webServer.start();
         info = new ClusterControllerInfo(ccConfig.clientNetIpAddress, 
ccConfig.clientNetPort,
                 webServer.getListeningPort());
diff --git 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/JobsRESTAPIFunction.java
 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/JobsRESTAPIFunction.java
index 892807b..ebd055d 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/JobsRESTAPIFunction.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/JobsRESTAPIFunction.java
@@ -18,9 +18,6 @@
  */
 package org.apache.hyracks.control.cc.web;
 
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
 import org.apache.hyracks.api.job.JobId;
 import org.apache.hyracks.control.cc.ClusterControllerService;
 import org.apache.hyracks.control.cc.web.util.IJSONOutputFunction;
@@ -28,6 +25,9 @@
 import org.apache.hyracks.control.cc.work.GetJobRunJSONWork;
 import org.apache.hyracks.control.cc.work.GetJobSummariesJSONWork;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
 public class JobsRESTAPIFunction implements IJSONOutputFunction {
     private ClusterControllerService ccs;
 
diff --git 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/WebServer.java
 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/WebServer.java
index 8fe68c1..ba94a37 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/WebServer.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/WebServer.java
@@ -19,63 +19,63 @@
 package org.apache.hyracks.control.cc.web;
 
 import java.util.EnumSet;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
 
 import javax.servlet.DispatcherType;
 
 import org.apache.hyracks.control.cc.ClusterControllerService;
 import 
org.apache.hyracks.control.cc.adminconsole.HyracksAdminConsoleApplication;
+import org.apache.hyracks.control.cc.web.util.IJSONOutputFunction;
 import org.apache.hyracks.control.cc.web.util.JSONOutputRequestHandler;
-import org.apache.hyracks.control.cc.web.util.RoutingHandler;
+import org.apache.hyracks.http.server.HttpServer;
+import org.apache.hyracks.http.server.WebManager;
 import org.apache.wicket.Application;
 import org.apache.wicket.RuntimeConfigurationType;
 import org.apache.wicket.protocol.http.ContextParamWebApplicationFactory;
 import org.apache.wicket.protocol.http.WicketFilter;
-import org.eclipse.jetty.server.Connector;
 import org.eclipse.jetty.server.Handler;
-import org.eclipse.jetty.server.Server;
-import org.eclipse.jetty.server.ServerConnector;
-import org.eclipse.jetty.server.handler.ContextHandler;
-import org.eclipse.jetty.server.handler.ContextHandlerCollection;
-import org.eclipse.jetty.server.handler.HandlerCollection;
 import org.eclipse.jetty.servlet.DefaultServlet;
 import org.eclipse.jetty.servlet.FilterHolder;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 
 public class WebServer {
     private final ClusterControllerService ccs;
-    private final Server server;
-    private final ServerConnector connector;
-    private final HandlerCollection handlerCollection;
+    private final int listeningPort;
+    private final ConcurrentMap<String, Object> ctx;
+    private final WebManager webMgr;
+    private final HttpServer server;
 
-    public WebServer(ClusterControllerService ccs) throws Exception {
+    public WebServer(ClusterControllerService ccs, int port) throws Exception {
         this.ccs = ccs;
-        server = new Server();
-
-        connector = new ServerConnector(server);
-
-        server.setConnectors(new Connector[] { connector });
-
-        handlerCollection = new ContextHandlerCollection();
-        server.setHandler(handlerCollection);
+        listeningPort = port;
+        ctx = new ConcurrentHashMap<String, Object>();
+        webMgr = new WebManager();
+        server = new HttpServer(webMgr.getBosses(), webMgr.getWorkers(), 
listeningPort);
         addHandlers();
+        webMgr.add(server);
     }
 
     private void addHandlers() {
-        ContextHandler handler = new ContextHandler("/rest");
-        RoutingHandler rh = new RoutingHandler();
-        rh.addHandler("jobs", new JSONOutputRequestHandler(new 
JobsRESTAPIFunction(ccs)));
-        rh.addHandler("nodes", new JSONOutputRequestHandler(new 
NodesRESTAPIFunction(ccs)));
-        rh.addHandler("statedump", new JSONOutputRequestHandler(new 
StateDumpRESTAPIFunction(ccs)));
-        handler.setHandler(rh);
-        addHandler(handler);
+        addJSONHandler("/rest/jobs/*", new JobsRESTAPIFunction(ccs));
+        addJSONHandler("/rest/nodes", new NodesRESTAPIFunction(ccs));
+        addJSONHandler("/rest/statedump", new StateDumpRESTAPIFunction(ccs));
 
+        /* TODO(tillw)
         addHandler(createAdminConsoleHandler());
         addHandler(createStaticResourcesHandler());
+        /*
 
         /** the service of uploading/downloading deployment jars */
+        /* TODO(tillw)
         handler = new ContextHandler("/applications");
         handler.setHandler(new ApplicationInstallationHandler(ccs));
         addHandler(handler);
+        */
+    }
+
+    private void addJSONHandler(String path, IJSONOutputFunction fn) {
+        server.addLet(new JSONOutputRequestHandler(ctx, new String[] { path }, 
fn));
     }
 
     private Handler createAdminConsoleHandler() {
@@ -102,23 +102,15 @@
         return handler;
     }
 
-    public void setPort(int port) {
-        connector.setPort(port);
-    }
-
     public int getListeningPort() {
-        return connector.getLocalPort();
+        return listeningPort;
     }
 
     public void start() throws Exception {
-        server.start();
+        webMgr.start();
     }
 
     public void stop() throws Exception {
-        server.stop();
-    }
-
-    public void addHandler(Handler handler) {
-        handlerCollection.addHandler(handler);
+        webMgr.stop();
     }
 }
diff --git 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/util/JSONOutputRequestHandler.java
 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/util/JSONOutputRequestHandler.java
index e736406..88283d0 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/util/JSONOutputRequestHandler.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/util/JSONOutputRequestHandler.java
@@ -18,42 +18,52 @@
  */
 package org.apache.hyracks.control.cc.web.util;
 
-import java.io.IOException;
+import java.util.concurrent.ConcurrentMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import org.apache.hyracks.http.api.IServlet;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
+import org.apache.hyracks.http.server.AbstractServlet;
+import org.apache.hyracks.http.server.util.ServletUtils;
 
 import com.fasterxml.jackson.databind.ObjectMapper;
 import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.handler.AbstractHandler;
 
-public class JSONOutputRequestHandler extends AbstractHandler {
+import io.netty.handler.codec.http.HttpMethod;
+import io.netty.handler.codec.http.HttpResponseStatus;
+
+public class JSONOutputRequestHandler extends AbstractServlet {
+
+    private static final Logger LOGGER = 
Logger.getLogger(JSONOutputRequestHandler.class.getName());
     private final IJSONOutputFunction fn;
 
-    public JSONOutputRequestHandler(IJSONOutputFunction fn) {
+    public JSONOutputRequestHandler(ConcurrentMap<String, Object> ctx, 
String[] paths, IJSONOutputFunction fn) {
+        super(ctx, paths);
         this.fn = fn;
     }
 
     @Override
-    public void handle(String target, Request baseRequest, HttpServletRequest 
request, HttpServletResponse response)
-            throws IOException, ServletException {
-        while (target.startsWith("/")) {
-            target = target.substring(1);
+    public void handle(IServletRequest request, IServletResponse response) {
+        if (request.getHttpRequest().method() != HttpMethod.GET) {
+            response.setStatus(HttpResponseStatus.METHOD_NOT_ALLOWED);
+            return;
         }
-        while (target.endsWith("/")) {
-            target = target.substring(0, target.length() - 1);
+        String path = path(request);
+        while (path.startsWith("/")) {
+            path = path.substring(1);
         }
-        String[] parts = target.split("/");
+        String[] parts = path.split("/");
         try {
             ObjectNode result = fn.invoke(parts);
-            response.setContentType("application/json");
+            ServletUtils.setContentType(response, 
IServlet.ContentType.APPLICATION_JSON, IServlet.Encoding.UTF8);
             ObjectMapper om = new ObjectMapper();
-            om.writer().writeValue(response.getWriter(),result);
-            baseRequest.setHandled(true);
+            om.writer().writeValue(response.writer(), result);
         } catch (Exception e) {
-            e.printStackTrace();
+            LOGGER.log(Level.WARNING, "Unhandled Exception thrown from " + 
getClass().getName(), e);
+            response.setStatus(HttpResponseStatus.BAD_REQUEST);
+            response.writer().print(e.getMessage());
         }
     }
 }
diff --git a/hyracks-fullstack/hyracks/hyracks-http/pom.xml 
b/hyracks-fullstack/hyracks/hyracks-http/pom.xml
index 8dc57a2..fb2a39d 100644
--- a/hyracks-fullstack/hyracks/hyracks-http/pom.xml
+++ b/hyracks-fullstack/hyracks/hyracks-http/pom.xml
@@ -28,7 +28,10 @@
     <dependency>
       <groupId>io.netty</groupId>
       <artifactId>netty-all</artifactId>
-      <version>4.1.6.Final</version>
+    </dependency>
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
     </dependency>
   </dependencies>
 </project>
\ No newline at end of file
diff --git 
a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/AbstractServlet.java
 
b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/AbstractServlet.java
index 7d24994..dd38911 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/AbstractServlet.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/AbstractServlet.java
@@ -18,6 +18,7 @@
  */
 package org.apache.hyracks.http.server;
 
+import java.util.Arrays;
 import java.util.concurrent.ConcurrentMap;
 
 import org.apache.hyracks.http.api.IServlet;
@@ -69,4 +70,9 @@
         }
         return request.getHttpRequest().uri().substring(trim);
     }
+
+    @Override
+    public String toString() {
+        return this.getClass().getSimpleName() + Arrays.toString(paths);
+    }
 }
diff --git 
a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/StaticResourceServlet.java
 
b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/StaticResourceServlet.java
new file mode 100644
index 0000000..5f9bb68
--- /dev/null
+++ 
b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/StaticResourceServlet.java
@@ -0,0 +1,100 @@
+/*
+ * 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.hyracks.http.server;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.concurrent.ConcurrentMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import org.apache.hyracks.http.api.IServlet;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
+
+import io.netty.handler.codec.http.HttpMethod;
+import org.apache.commons.io.IOUtils;
+import io.netty.handler.codec.http.HttpResponseStatus;
+import org.apache.hyracks.http.server.util.ServletUtils;
+
+public class StaticResourceServlet extends AbstractServlet {
+
+    private static final Logger LOGGER = 
Logger.getLogger(StaticResourceServlet.class.getName());
+
+    public StaticResourceServlet(ConcurrentMap<String, Object> ctx, String[] 
paths) {
+        super(ctx, paths);
+    }
+
+    @Override
+    public void handle(IServletRequest request, IServletResponse response) {
+        try {
+            if (request.getHttpRequest().method() == HttpMethod.GET) {
+                doGet(request, response);
+            } else if (request.getHttpRequest().method() == HttpMethod.POST) {
+                doPost(request, response);
+            } else {
+                response.setStatus(HttpResponseStatus.METHOD_NOT_ALLOWED);
+            }
+        } catch (IOException e) {
+            LOGGER.log(Level.WARNING, "Failure setting content type", e);
+            response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
+
+    protected void doGet(IServletRequest request, IServletResponse response) 
throws IOException {
+        String resourcePath = request.getHttpRequest().uri();
+        deliverResource(resourcePath, response);
+    }
+
+    protected void deliverResource(String resourcePath, IServletResponse 
response) throws IOException {
+        response.setStatus(HttpResponseStatus.OK);
+        try (InputStream is = 
StaticResourceServlet.class.getResourceAsStream(resourcePath)) {
+            if (is == null) {
+                response.setStatus(HttpResponseStatus.NOT_FOUND);
+                return;
+            }
+            int i = resourcePath.lastIndexOf('.');
+            if (i >= 0) {
+                String extension = resourcePath.substring(i);
+                String mime = ContentType.mime(extension);
+                if (mime != null) {
+                    OutputStream out = response.outputStream();
+                    ServletUtils.setContentType(response, mime);
+                    try {
+                        IOUtils.copy(is, out);
+                    } catch (Exception e) {
+                        LOGGER.log(Level.WARNING, "Failure copying response", 
e);
+                    } finally {
+                        if (out != null) {
+                            IOUtils.closeQuietly(out);
+                        }
+                        IOUtils.closeQuietly(is);
+                    }
+                    return;
+                }
+            }
+            response.setStatus(HttpResponseStatus.BAD_REQUEST);
+        }
+    }
+
+    protected void doPost(IServletRequest request, IServletResponse response) 
throws IOException {
+        response.setStatus(HttpResponseStatus.METHOD_NOT_ALLOWED);
+    }
+}
diff --git a/hyracks-fullstack/pom.xml b/hyracks-fullstack/pom.xml
index 5ddbf92..f972818 100644
--- a/hyracks-fullstack/pom.xml
+++ b/hyracks-fullstack/pom.xml
@@ -84,6 +84,11 @@
         <version>${jetty.version}</version>
       </dependency>
       <dependency>
+        <groupId>io.netty</groupId>
+        <artifactId>netty-all</artifactId>
+        <version>4.1.6.Final</version>
+      </dependency>
+      <dependency>
         <groupId>junit</groupId>
         <artifactId>junit</artifactId>
         <version>4.12</version>

-- 
To view, visit https://asterix-gerrit.ics.uci.edu/1508
To unsubscribe, visit https://asterix-gerrit.ics.uci.edu/settings

Gerrit-MessageType: newchange
Gerrit-Change-Id: Ifcd240591d12baab2db4ce3163c635a1dde5c4ba
Gerrit-PatchSet: 1
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Owner: Till Westmann <[email protected]>

Reply via email to