ASTERIXDB-1786: Remove Hyracks Servlets.
Change-Id: Ifcd240591d12baab2db4ce3163c635a1dde5c4ba
Reviewed-on: https://asterix-gerrit.ics.uci.edu/1508
Reviewed-by: abdullah alamoudi <bamousaa@gmail.com>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
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);
}
}
@@ -110,9 +75,4 @@
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,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>
@@ -92,10 +101,6 @@
<artifactId>jetty-servlet</artifactId>
</dependency>
<dependency>
- <groupId>org.eclipse.jetty</groupId>
- <artifactId>jetty-http</artifactId>
- </dependency>
- <dependency>
<groupId>org.apache.wicket</groupId>
<artifactId>wicket-core</artifactId>
<version>1.5.2</version>
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>