Till Westmann has submitted this change and it was merged.

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


ASTERIXDB-1786: Remove Hyracks Servlets.

Change-Id: Ifcd240591d12baab2db4ce3163c635a1dde5c4ba
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1508
Reviewed-by: abdullah alamoudi <bamou...@gmail.com>
Tested-by: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
---
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/ApplicationInstallationHandler.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
M 
hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/HttpServerHandler.java
A 
hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/StaticResourceServlet.java
M hyracks-fullstack/pom.xml
16 files changed, 304 insertions(+), 218 deletions(-)

Approvals:
  abdullah alamoudi: Looks good to me, approved
  Jenkins: Verified; Verified

Objections:
  Jenkins: Violations found; Violations found



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 40c7f2c..234d134 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
@@ -56,11 +56,11 @@
 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.utils.HttpUtil;
 import org.apache.hyracks.http.server.utils.HttpUtil.ContentType;
 import org.apache.hyracks.http.server.utils.HttpUtil.Encoding;
 
-import io.netty.handler.codec.http.HttpMethod;
 import io.netty.handler.codec.http.HttpResponseStatus;
 
 public class ApiServlet extends AbstractServlet {
@@ -191,7 +191,7 @@
                 outputStream.close();
                 return;
             }
-            String type = 
HttpUtil.mime(QueryWebInterfaceServlet.extension(resourcePath));
+            String type = 
HttpUtil.mime(StaticResourceServlet.extension(resourcePath));
             HttpUtil.setContentType(response, "".equals(type) ? 
HttpUtil.ContentType.TEXT_PLAIN : type,
                     HttpUtil.Encoding.UTF8);
             writeOutput(response, is, resourcePath);
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 b839b26..94ce017 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,19 +26,17 @@
 
 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.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.utils.HttpUtil;
 
 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) {
@@ -49,43 +45,12 @@
 
     @Override
     protected void get(IServletRequest request, IServletResponse response) 
throws IOException {
-        String resourcePath = null;
         String requestURI = request.getHttpRequest().uri();
-        response.setStatus(HttpResponseStatus.OK);
-
         if ("/".equals(requestURI)) {
             HttpUtil.setContentType(response, HttpUtil.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 = HttpUtil.mime(extension);
-                if (mime != null) {
-                    OutputStream out = response.outputStream();
-                    HttpUtil.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);
         }
     }
 
@@ -109,10 +74,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 6691309..5221c4e 100644
--- a/asterixdb/pom.xml
+++ b/asterixdb/pom.xml
@@ -1016,6 +1016,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..7076cf7 100644
--- a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/pom.xml
+++ b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/pom.xml
@@ -75,8 +75,17 @@
   <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>
@@ -90,10 +99,6 @@
     <dependency>
       <groupId>org.eclipse.jetty</groupId>
       <artifactId>jetty-servlet</artifactId>
-    </dependency>
-    <dependency>
-      <groupId>org.eclipse.jetty</groupId>
-      <artifactId>jetty-http</artifactId>
     </dependency>
     <dependency>
       <groupId>org.apache.wicket</groupId>
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 346f934..c47284c 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
@@ -173,10 +173,9 @@
         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);
         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/ApplicationInstallationHandler.java
 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/ApplicationInstallationHandler.java
index 75b7473..991649a 100755
--- 
a/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/ApplicationInstallationHandler.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-control/hyracks-control-cc/src/main/java/org/apache/hyracks/control/cc/web/ApplicationInstallationHandler.java
@@ -21,111 +21,113 @@
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
-import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
+import java.util.concurrent.ConcurrentMap;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.hyracks.control.cc.ClusterControllerService;
 import org.apache.hyracks.control.common.work.SynchronizableWork;
-import org.eclipse.jetty.http.HttpMethod;
-import org.eclipse.jetty.server.Request;
-import org.eclipse.jetty.server.handler.AbstractHandler;
+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.utils.HttpUtil;
 
-public class ApplicationInstallationHandler extends AbstractHandler {
+import io.netty.buffer.ByteBuf;
+import io.netty.handler.codec.http.HttpMethod;
+import io.netty.handler.codec.http.HttpResponseStatus;
+
+public class ApplicationInstallationHandler extends AbstractServlet {
+
+    private static final Logger LOGGER = 
Logger.getLogger(ApplicationInstallationHandler.class.getName());
+
     private ClusterControllerService ccs;
 
-    public ApplicationInstallationHandler(ClusterControllerService ccs) {
+    public ApplicationInstallationHandler(ConcurrentMap<String, Object> ctx, 
String[] paths,
+            ClusterControllerService ccs) {
+        super(ctx, paths);
         this.ccs = ccs;
     }
 
     @Override
-    public void handle(String target, Request baseRequest, HttpServletRequest 
request, HttpServletResponse response)
-            throws IOException, ServletException {
+    public void handle(IServletRequest request, IServletResponse response) {
+        String path = path(request);
+        while (path.startsWith("/")) {
+            path = path.substring(1);
+        }
+        final String[] params = path.split("&");
+        if (params.length != 2 || params[0].isEmpty() || params[1].isEmpty()) {
+            response.setStatus(HttpResponseStatus.BAD_REQUEST);
+            return;
+        }
+        final String deployIdString = params[0];
+        final String fileName = params[1];
+        final String rootDir = ccs.getServerContext().getBaseDir().toString();
+
+        final String deploymentDir = rootDir.endsWith(File.separator) ? 
rootDir + "applications/" + deployIdString
+                : rootDir + File.separator + "/applications/" + File.separator 
+ deployIdString;
+        final HttpMethod method = request.getHttpRequest().method();
         try {
-            while (target.startsWith("/")) {
-                target = target.substring(1);
+            if (method == HttpMethod.PUT) {
+                final ByteBuf content = request.getHttpRequest().content();
+                writeToFile(content, deploymentDir, fileName);
+            } else if (method == HttpMethod.GET) {
+                readFromFile(fileName, deploymentDir, response);
+            } else {
+                response.setStatus(HttpResponseStatus.METHOD_NOT_ALLOWED);
             }
-            while (target.endsWith("/")) {
-                target = target.substring(0, target.length() - 1);
-            }
-            String[] parts = target.split("/");
-            if (parts.length != 1) {
-                return;
-            }
-            final String[] params = parts[0].split("&");
-            String deployIdString = params[0];
-            String rootDir = ccs.getServerContext().getBaseDir().toString();
-            final String deploymentDir = rootDir.endsWith(File.separator) ? 
rootDir + "applications/" + deployIdString
-                    : rootDir + File.separator + "/applications/" + 
File.separator + deployIdString;
-            switch (HttpMethod.valueOf(request.getMethod())) {
-                case PUT: {
-                    class OutputStreamGetter extends SynchronizableWork {
-                        private OutputStream os;
+        } catch (Exception e) {
+            LOGGER.log(Level.WARNING, "Unhandled exception ", e);
+            response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);
+        }
+    }
 
-                        @Override
-                        protected void doRun() throws Exception {
-                            FileUtils.forceMkdir(new File(deploymentDir));
-                            String fileName = params[1];
-                            File jarFile = new File(deploymentDir, fileName);
-                            os = new FileOutputStream(jarFile);
-                        }
-                    }
-                    OutputStreamGetter r = new OutputStreamGetter();
-                    try {
-                        ccs.getWorkQueue().scheduleAndSync(r);
-                    } catch (Exception e) {
-                        throw new IOException(e);
-                    }
-                    try {
-                        IOUtils.copyLarge(request.getInputStream(), r.os);
-                    } finally {
-                        r.os.close();
-                    }
-                    break;
-                }
-                case GET: {
-                    class InputStreamGetter extends SynchronizableWork {
-                        private InputStream is;
+    protected void readFromFile(final String fileName, final String 
deploymentDir, IServletResponse response)
+            throws Exception {
+        class InputStreamGetter extends SynchronizableWork {
+            private InputStream is;
 
-                        @Override
-                        protected void doRun() throws Exception {
-                            String fileName = params[1];
-                            File jarFile = new File(deploymentDir, fileName);
-                            is = new FileInputStream(jarFile);
-                        }
-                    }
-                    InputStreamGetter r = new InputStreamGetter();
-                    try {
-                        ccs.getWorkQueue().scheduleAndSync(r);
-                    } catch (Exception e) {
-                        throw new IOException(e);
-                    }
-                    if (r.is == null) {
-                        response.setStatus(HttpServletResponse.SC_NOT_FOUND);
-                    } else {
-                        response.setContentType("application/octet-stream");
-                        response.setStatus(HttpServletResponse.SC_OK);
-                        try {
-                            IOUtils.copyLarge(r.is, 
response.getOutputStream());
-                        } finally {
-                            r.is.close();
-                        }
-                    }
-                    break;
-                }
-                default:
-                    throw new IllegalArgumentException(request.getMethod());
+            @Override
+            protected void doRun() throws Exception {
+                File jarFile = new File(deploymentDir, fileName);
+                is = new FileInputStream(jarFile);
             }
-            baseRequest.setHandled(true);
-        } catch (IOException e) {
-            e.printStackTrace();
-            throw e;
+        }
+        InputStreamGetter r = new InputStreamGetter();
+        ccs.getWorkQueue().scheduleAndSync(r);
+        if (r.is == null) {
+            response.setStatus(HttpResponseStatus.NOT_FOUND);
+        } else {
+            HttpUtil.setContentType(response, "application/octet-stream");
+            response.setStatus(HttpResponseStatus.OK);
+            try {
+                IOUtils.copyLarge(r.is, response.outputStream());
+            } finally {
+                r.is.close();
+            }
+        }
+    }
+
+    protected void writeToFile(ByteBuf content, final String deploymentDir, 
final String fileName) throws Exception {
+        class OutputStreamGetter extends SynchronizableWork {
+            private OutputStream os;
+
+            @Override
+            protected void doRun() throws Exception {
+                FileUtils.forceMkdir(new File(deploymentDir));
+                File jarFile = new File(deploymentDir, fileName);
+                os = new FileOutputStream(jarFile);
+            }
+        }
+        OutputStreamGetter r = new OutputStreamGetter();
+        ccs.getWorkQueue().scheduleAndSync(r);
+        try {
+            content.getBytes(0, r.os, content.readableBytes());
+        } finally {
+            r.os.close();
         }
     }
 }
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..f61d7c8 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,55 @@
 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.StaticResourceServlet;
+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());
+        server.addServlet(new StaticResourceServlet(ctx, new String[] { 
"/static/*" }));
+        server.addServlet(new ApplicationInstallationHandler(ctx, new String[] 
{ "/applications/*" }, ccs));
+    }
 
-        addHandler(createAdminConsoleHandler());
-        addHandler(createStaticResourcesHandler());
-
-        /** the service of uploading/downloading deployment jars */
-        handler = new ContextHandler("/applications");
-        handler.setHandler(new ApplicationInstallationHandler(ccs));
-        addHandler(handler);
+    private void addJSONHandler(String path, IJSONOutputFunction fn) {
+        server.addServlet(new JSONOutputRequestHandler(ctx, new String[] { 
path }, fn));
     }
 
     private Handler createAdminConsoleHandler() {
@@ -93,32 +85,15 @@
         return handler;
     }
 
-    private Handler createStaticResourcesHandler() {
-        String staticDir = 
WebServer.class.getClassLoader().getResource("static").toExternalForm();
-        ServletContextHandler handler = new 
ServletContextHandler(ServletContextHandler.SESSIONS);
-        handler.setContextPath("/static");
-        handler.setResourceBase(staticDir);
-        handler.addServlet(DefaultServlet.class, "/");
-        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..c6c76dd 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
@@ -19,41 +19,69 @@
 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.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
+import org.apache.hyracks.http.server.AbstractServlet;
+import org.apache.hyracks.http.server.utils.HttpUtil;
 
 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("/");
+        ObjectNode result = invoke(response, parts);
+        if (result != null) {
+            deliver(response, result);
+        }
+    }
+
+    protected ObjectNode invoke(IServletResponse response, String[] parts) {
         try {
-            ObjectNode result = fn.invoke(parts);
-            response.setContentType("application/json");
-            ObjectMapper om = new ObjectMapper();
-            om.writer().writeValue(response.getWriter(),result);
-            baseRequest.setHandled(true);
+            return fn.invoke(parts);
         } catch (Exception e) {
-            e.printStackTrace();
+            LOGGER.log(Level.WARNING, "Exception invoking " + 
fn.getClass().getName(), e);
+            response.setStatus(HttpResponseStatus.BAD_REQUEST);
+            response.writer().print(e.getMessage());
+        }
+        return null;
+    }
+
+    protected void deliver(IServletResponse response, ObjectNode result) {
+        try {
+            HttpUtil.setContentType(response, 
HttpUtil.ContentType.APPLICATION_JSON, HttpUtil.Encoding.UTF8);
+            ObjectMapper om = new ObjectMapper();
+            om.writer().writeValue(response.writer(), result);
+            response.setStatus(HttpResponseStatus.OK);
+        } catch (IOException e) {
+            LOGGER.log(Level.WARNING, "Exception delivering result in " + 
getClass().getName(), e);
+            response.setStatus(HttpResponseStatus.INTERNAL_SERVER_ERROR);
+            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 2795549..37ef3bb 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 java.util.logging.Level;
 import java.util.logging.Logger;
@@ -138,4 +139,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/HttpServerHandler.java
 
b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/HttpServerHandler.java
index 5b917cd..c0e7353 100644
--- 
a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/HttpServerHandler.java
+++ 
b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/HttpServerHandler.java
@@ -29,7 +29,6 @@
 import io.netty.channel.SimpleChannelInboundHandler;
 import io.netty.handler.codec.http.DefaultHttpResponse;
 import io.netty.handler.codec.http.FullHttpRequest;
-import io.netty.handler.codec.http.HttpMethod;
 import io.netty.handler.codec.http.HttpResponseStatus;
 
 public class HttpServerHandler extends SimpleChannelInboundHandler<Object> {
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..046b124
--- /dev/null
+++ 
b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/StaticResourceServlet.java
@@ -0,0 +1,101 @@
+/*
+ * 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.commons.io.IOUtils;
+import org.apache.hyracks.http.api.IServletRequest;
+import org.apache.hyracks.http.api.IServletResponse;
+import org.apache.hyracks.http.server.utils.HttpUtil;
+
+import io.netty.handler.codec.http.HttpMethod;
+import io.netty.handler.codec.http.HttpResponseStatus;
+
+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;
+            }
+            String extension = extension(resourcePath);
+            String mime = HttpUtil.mime(extension);
+            if (mime == null) {
+                response.setStatus(HttpResponseStatus.BAD_REQUEST);
+            } else {
+                OutputStream out = response.outputStream();
+                HttpUtil.setContentType(response, mime);
+                try {
+                    IOUtils.copy(is, out);
+                } catch (IOException e) {
+                    LOGGER.log(Level.WARNING, "Failure copying response", e);
+                } finally {
+                    if (out != null) {
+                        IOUtils.closeQuietly(out);
+                    }
+                    IOUtils.closeQuietly(is);
+                }
+            }
+        }
+    }
+
+    protected void doPost(IServletRequest request, IServletResponse response) 
throws IOException {
+        response.setStatus(HttpResponseStatus.METHOD_NOT_ALLOWED);
+    }
+
+    public static String extension(String path) {
+        int i = path.lastIndexOf('.');
+        return i < 1 ? "" : path.substring(i);
+    }
+}
diff --git a/hyracks-fullstack/pom.xml b/hyracks-fullstack/pom.xml
index 1494183..efbe0c0 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: merged
Gerrit-Change-Id: Ifcd240591d12baab2db4ce3163c635a1dde5c4ba
Gerrit-PatchSet: 14
Gerrit-Project: asterixdb
Gerrit-Branch: master
Gerrit-Owner: Till Westmann <ti...@apache.org>
Gerrit-Reviewer: Jenkins <jenk...@fulliautomatix.ics.uci.edu>
Gerrit-Reviewer: Michael Blow <mb...@apache.org>
Gerrit-Reviewer: Till Westmann <ti...@apache.org>
Gerrit-Reviewer: abdullah alamoudi <bamou...@gmail.com>

Reply via email to