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>