You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@asterixdb.apache.org by ti...@apache.org on 2017/01/26 15:29:30 UTC
[3/5] asterixdb git commit: Replace Servlets with Netty Based HTTP
Servers
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/60e7f12b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ClusterNodeDetailsAPIServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ClusterNodeDetailsAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ClusterNodeDetailsAPIServlet.java
deleted file mode 100644
index d737ad8..0000000
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ClusterNodeDetailsAPIServlet.java
+++ /dev/null
@@ -1,215 +0,0 @@
-/*
- * 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.asterix.api.http.servlet;
-
-import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
-import org.apache.asterix.runtime.util.ClusterStateManager;
-import org.apache.hyracks.api.client.IHyracksClientConnection;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-public class ClusterNodeDetailsAPIServlet extends ClusterAPIServlet {
- private static final long serialVersionUID = 1L;
- private static final Logger LOGGER = Logger.getLogger(ClusterNodeDetailsAPIServlet.class.getName());
- private final ObjectMapper om = new ObjectMapper();
-
- @Override
- public void init() throws ServletException{
- om.enable(SerializationFeature.INDENT_OUTPUT);
- }
-
- @Override
- protected void getUnsafe(HttpServletRequest request, HttpServletResponse response) throws IOException {
- PrintWriter responseWriter = response.getWriter();
- ServletContext context = getServletContext();
- IHyracksClientConnection hcc = (IHyracksClientConnection) context.getAttribute(HYRACKS_CONNECTION_ATTR);
- try {
- ObjectNode json;
- if (request.getPathInfo() == null) {
- json = om.createObjectNode();
- json.set("ncs", getClusterStateJSON(request, "../").get("ncs"));
- } else {
- json = processNode(request, hcc);
- }
- response.setStatus(HttpServletResponse.SC_OK);
- response.setContentType("application/json");
- response.setCharacterEncoding("utf-8");
- responseWriter.write(om.writerWithDefaultPrettyPrinter().writeValueAsString(json));
- } catch (IllegalStateException e) { // NOSONAR - exception not logged or rethrown
- response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
- } catch (IllegalArgumentException e) { // NOSONAR - exception not logged or rethrown
- response.sendError(HttpServletResponse.SC_NOT_FOUND);
- } catch (Exception e) {
- LOGGER.log(Level.INFO, "exception thrown for " + request, e);
- response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.toString());
- }
- responseWriter.flush();
- }
-
- private ObjectNode processNode(HttpServletRequest request, IHyracksClientConnection hcc)
- throws Exception {
- String pathInfo = request.getPathInfo();
- if (pathInfo.endsWith("/")) {
- throw new IllegalArgumentException();
- }
- String[] parts = pathInfo.substring(1).split("/");
- final String node = parts[0];
-
- if (parts.length == 1) {
- ArrayNode ncs = (ArrayNode) getClusterStateJSON(request, "../../").get("ncs");
- for (int i = 0; i < ncs.size(); i++) {
- if (node.equals(ncs.get(i).get("node_id").asText())) {
- return (ObjectNode) ncs.get(i);
- }
- }
- if ("cc".equals(node)) {
- return om.createObjectNode();
- }
- throw new IllegalArgumentException();
- } else if (parts.length == 2) {
- ObjectNode json;
-
- switch (parts[1]) {
- case "config":
- json = processNodeConfig(hcc, node);
- break;
-
- case "stats":
- json = processNodeStats(hcc, node);
- break;
-
- case "threaddump":
- return processNodeThreadDump(hcc, node);
-
- default:
- throw new IllegalArgumentException();
- }
- fixupKeys(json);
-
- return json;
- } else {
- throw new IllegalArgumentException();
- }
- }
-
- protected ObjectNode fixupKeys(ObjectNode json) {
- // TODO (mblow): generate the keys with _ to begin with
- List<String> keys = new ArrayList<>();
- for (Iterator iter = json.fieldNames(); iter.hasNext(); ) {
- keys.add((String) iter.next());
- }
- for (String key : keys) {
- String newKey = key.replace('-', '_');
- if (!newKey.equals(key)) {
- json.set(newKey, json.remove(key));
- }
- }
- return json;
- }
-
- protected ObjectNode processNodeStats(IHyracksClientConnection hcc, String node) throws Exception {
- final String details = hcc.getNodeDetailsJSON(node, true, false);
- if (details == null) {
- throw new IllegalArgumentException();
- }
- ObjectNode json = (ObjectNode) om.readTree(details);
- int index = json.get("rrd-ptr").asInt() - 1;
- json.remove("rrd-ptr");
-
- List<String> keys = new ArrayList<>();
- for (Iterator iter = json.fieldNames(); iter.hasNext(); ) {
- keys.add((String) iter.next());
- }
-
- final ArrayNode gcNames = (ArrayNode) json.get("gc-names");
- final ArrayNode gcCollectionTimes = (ArrayNode) json.get("gc-collection-times");
- final ArrayNode gcCollectionCounts = (ArrayNode) json.get("gc-collection-counts");
-
- for (String key : keys) {
- if (key.startsWith("gc-")) {
- json.remove(key);
- } else {
- final JsonNode keyNode = json.get(key);
- if (keyNode instanceof ArrayNode) {
- final ArrayNode valueArray = (ArrayNode) keyNode;
- // fixup an index of -1 to the final element in the array (i.e. RRD_SIZE)
- if (index == -1) {
- index = valueArray.size() - 1;
- }
- final JsonNode value = valueArray.get(index);
- json.remove(key);
- json.set(key.replaceAll("s$",""), value);
- }
- }
- }
- ArrayNode gcs = om.createArrayNode();
-
- for (int i = 0; i < gcNames.size(); i++) {
- ObjectNode gc = om.createObjectNode();
- gc.set("name", gcNames.get(i));
- gc.set("collection-time", ((ArrayNode)gcCollectionTimes.get(i)).get(index));
- gc.set("collection-count", ((ArrayNode)gcCollectionCounts.get(i)).get(index));
- gcs.add(gc);
- }
- json.set("gcs", gcs);
-
- return json;
- }
-
- private ObjectNode processNodeConfig(IHyracksClientConnection hcc, String node) throws Exception {
- String config = hcc.getNodeDetailsJSON(node, false, true);
- if (config == null) {
- throw new IllegalArgumentException();
- }
- return (ObjectNode) om.readTree(config);
- }
-
- private ObjectNode processNodeThreadDump(IHyracksClientConnection hcc, String node) throws Exception {
- if ("cc".equals(node)) {
- return om.createObjectNode();
- }
- String dump = hcc.getThreadDump(node);
- if (dump == null) {
- // check to see if this is a node that is simply down
- throw ClusterStateManager.INSTANCE.getNodePartitions(node) != null
- ? new IllegalStateException()
- : new IllegalArgumentException();
- }
- return (ObjectNode) om.readTree(dump);
- }
-
-}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/60e7f12b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ConnectorAPIServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ConnectorAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ConnectorAPIServlet.java
deleted file mode 100644
index 78801b8..0000000
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/ConnectorAPIServlet.java
+++ /dev/null
@@ -1,181 +0,0 @@
-/*
- * 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.asterix.api.http.servlet;
-
-import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.List;
-import java.util.Map;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.asterix.metadata.MetadataManager;
-import org.apache.asterix.metadata.MetadataTransactionContext;
-import org.apache.asterix.metadata.declared.MetadataProvider;
-import org.apache.asterix.metadata.entities.Dataset;
-import org.apache.asterix.metadata.utils.DatasetUtils;
-import org.apache.asterix.om.types.ARecordType;
-import org.apache.asterix.util.FlushDatasetUtils;
-import org.apache.hyracks.api.client.IHyracksClientConnection;
-import org.apache.hyracks.api.client.NodeControllerInfo;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.apache.hyracks.api.io.FileSplit;
-
-/***
- * The REST API that takes a dataverse name and a dataset name as the input
- * and returns an array of file splits (IP, file-path) of the dataset in LOSSLESS_JSON.
- * It is mostly used by external runtime, e.g., Pregelix or IMRU to pull data
- * in parallel from existing AsterixDB datasets.
- *
- * @author yingyi
- */
-public class ConnectorAPIServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
-
- @Override
- public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
- response.setContentType("text/html");
- response.setCharacterEncoding("utf-8");
- PrintWriter out = response.getWriter();
- try {
- ObjectMapper om = new ObjectMapper();
- ObjectNode jsonResponse = om.createObjectNode();
- String dataverseName = request.getParameter("dataverseName");
- String datasetName = request.getParameter("datasetName");
- if (dataverseName == null || datasetName == null) {
- jsonResponse.put("error", "Parameter dataverseName or datasetName is null,");
- out.write(jsonResponse.toString());
- out.flush();
- return;
- }
- ServletContext context = getServletContext();
-
- IHyracksClientConnection hcc = null;
- synchronized (context) {
- hcc = (IHyracksClientConnection) context.getAttribute(HYRACKS_CONNECTION_ATTR);
- }
-
- // Metadata transaction begins.
- MetadataManager.INSTANCE.init();
- MetadataTransactionContext mdTxnCtx = MetadataManager.INSTANCE.beginTransaction();
-
- // Retrieves file splits of the dataset.
- MetadataProvider metadataProvider = new MetadataProvider(null);
- metadataProvider.setMetadataTxnContext(mdTxnCtx);
- Dataset dataset = metadataProvider.findDataset(dataverseName, datasetName);
- if (dataset == null) {
- jsonResponse.put("error",
- "Dataset " + datasetName + " does not exist in " + "dataverse " + dataverseName);
- out.write(jsonResponse.toString());
- out.flush();
- return;
- }
- boolean temp = dataset.getDatasetDetails().isTemp();
- FileSplit[] fileSplits = metadataProvider.splitsForDataset(mdTxnCtx, dataverseName, datasetName,
- datasetName, temp);
- ARecordType recordType = (ARecordType) metadataProvider.findType(dataset.getItemTypeDataverseName(),
- dataset.getItemTypeName());
- List<List<String>> primaryKeys = DatasetUtils.getPartitioningKeys(dataset);
- StringBuilder pkStrBuf = new StringBuilder();
- for (List<String> keys : primaryKeys) {
- for (String key : keys) {
- pkStrBuf.append(key).append(",");
- }
- }
- pkStrBuf.delete(pkStrBuf.length() - 1, pkStrBuf.length());
-
- // Constructs the returned json object.
- formResponseObject(jsonResponse, fileSplits, recordType, pkStrBuf.toString(), temp,
- hcc.getNodeControllerInfos());
-
- // Flush the cached contents of the dataset to file system.
- FlushDatasetUtils.flushDataset(hcc, metadataProvider, mdTxnCtx, dataverseName, datasetName, datasetName);
-
- // Metadata transaction commits.
- MetadataManager.INSTANCE.commitTransaction(mdTxnCtx);
- // Writes file splits.
- out.write(jsonResponse.toString());
- out.flush();
- } catch (Exception e) {
- e.printStackTrace();
- out.println(e.getMessage());
- out.flush();
- e.printStackTrace(out);
- }
- }
-
- private void formResponseObject(ObjectNode jsonResponse, FileSplit[] fileSplits, ARecordType recordType,
- String primaryKeys, boolean temp, Map<String, NodeControllerInfo> nodeMap) throws Exception {
- ObjectMapper om = new ObjectMapper();
- ArrayNode partititons = om.createArrayNode();
- // Whether the dataset is temp or not
- jsonResponse.put("temp", temp);
- // Adds a primary key.
- jsonResponse.put("keys", primaryKeys);
- // Adds record type.
- jsonResponse.set("type", recordType.toJSON());
- // Generates file partitions.
- for (FileSplit split : fileSplits) {
- String ipAddress = nodeMap.get(split.getNodeName()).getNetworkAddress().getAddress().toString();
- String path = split.getPath();
- FilePartition partition = new FilePartition(ipAddress, path);
- partititons.add(partition.toObjectNode());
- }
- // Generates the response object which contains the splits.
- jsonResponse.set("splits", partititons);
- }
-}
-
-class FilePartition {
- private final String ipAddress;
- private final String path;
-
- public FilePartition(String ipAddress, String path) {
- this.ipAddress = ipAddress;
- this.path = path;
- }
-
- public String getIPAddress() {
- return ipAddress;
- }
-
- public String getPath() {
- return path;
- }
-
- @Override
- public String toString() {
- return ipAddress + ":" + path;
- }
-
- public ObjectNode toObjectNode() {
- ObjectMapper om = new ObjectMapper();
- ObjectNode partition = om.createObjectNode();
- partition.put("ip", ipAddress);
- partition.put("path", path);
- return partition;
- }
-}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/60e7f12b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/DDLAPIServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/DDLAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/DDLAPIServlet.java
deleted file mode 100644
index 19a7609..0000000
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/DDLAPIServlet.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.asterix.api.http.servlet;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.asterix.compiler.provider.ILangCompilationProvider;
-import org.apache.asterix.lang.common.base.Statement;
-import org.apache.asterix.translator.IStatementExecutorFactory;
-
-public class DDLAPIServlet extends RESTAPIServlet {
- private static final long serialVersionUID = 1L;
- private static final byte ALLOWED_CATEGORIES = Statement.Category.QUERY | Statement.Category.UPDATE
- | Statement.Category.DDL;
-
- public DDLAPIServlet(ILangCompilationProvider compilationProvider,
- IStatementExecutorFactory statementExecutorFactory) {
- super(compilationProvider, statementExecutorFactory);
- }
-
- @Override
- protected String getQueryParameter(HttpServletRequest request) {
- return request.getParameter("ddl");
- }
-
- @Override
- protected byte getAllowedCategories() {
- return ALLOWED_CATEGORIES;
- }
-
- @Override
- protected String getErrorMessage() {
- return "Invalid statement: Non-DDL statement %s to the DDL API.";
- }
-}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/60e7f12b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/DiagnosticsAPIServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/DiagnosticsAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/DiagnosticsAPIServlet.java
deleted file mode 100644
index 4416d5c..0000000
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/DiagnosticsAPIServlet.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 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.asterix.api.http.servlet;
-
-import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.SerializationFeature;
-import org.apache.asterix.runtime.util.AppContextInfo;
-import org.apache.hyracks.api.client.IHyracksClientConnection;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-public class DiagnosticsAPIServlet extends ClusterNodeDetailsAPIServlet {
- private static final long serialVersionUID = 1L;
- private static final Logger LOGGER = Logger.getLogger(DiagnosticsAPIServlet.class.getName());
-
- @Override
- protected void getUnsafe(HttpServletRequest request, HttpServletResponse response) throws IOException {
- response.setContentType("application/json");
- response.setCharacterEncoding("utf-8");
- PrintWriter responseWriter = response.getWriter();
- ObjectNode json;
- ObjectMapper om = new ObjectMapper();
- om.enable(SerializationFeature.INDENT_OUTPUT);
- try {
- if (request.getPathInfo() != null) {
- throw new IllegalArgumentException();
- }
- json = getClusterDiagnosticsJSON();
- response.setStatus(HttpServletResponse.SC_OK);
- responseWriter.write(om.writerWithDefaultPrettyPrinter().writeValueAsString(json));
- } catch (IllegalStateException e) { // NOSONAR - exception not logged or rethrown
- response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
- } catch (IllegalArgumentException e) { // NOSONAR - exception not logged or rethrown
- response.sendError(HttpServletResponse.SC_NOT_FOUND);
- } catch (Exception e) {
- LOGGER.log(Level.INFO, "exception thrown for " + request, e);
- response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e.toString());
- }
- responseWriter.flush();
- }
-
- private ObjectNode getClusterDiagnosticsJSON() throws Exception {
- ObjectMapper om = new ObjectMapper();
- final ServletContext context = getServletContext();
- IHyracksClientConnection hcc = (IHyracksClientConnection) context.getAttribute(HYRACKS_CONNECTION_ATTR);
- ExecutorService executor = (ExecutorService) context.getAttribute(ServletConstants.EXECUTOR_SERVICE);
-
- Map<String, Future<ObjectNode>> ccFutureData = new HashMap<>();
- ccFutureData.put("threaddump",
- executor.submit(() -> fixupKeys((ObjectNode) om.readTree(hcc.getThreadDump(null)))));
- ccFutureData.put("config",
- executor.submit(() -> fixupKeys((ObjectNode) om.readTree(hcc.getNodeDetailsJSON(null, false, true)))));
- ccFutureData.put("stats",
- executor.submit(() -> fixupKeys((ObjectNode) om.readTree(hcc.getNodeDetailsJSON(null, true, false)))));
-
- Map<String, Map<String, Future<ObjectNode>>> ncDataMap = new HashMap<>();
- for (String nc : AppContextInfo.INSTANCE.getMetadataProperties().getNodeNames()) {
- Map<String, Future<ObjectNode>> ncData = new HashMap<>();
- ncData.put("threaddump", executor.submit(() -> fixupKeys((ObjectNode) om.readTree(hcc.getThreadDump(nc)))));
- ncData.put("config", executor
- .submit(() -> fixupKeys((ObjectNode) om.readTree(hcc.getNodeDetailsJSON(nc, false, true)))));
- ncData.put("stats", executor.submit(() -> fixupKeys(processNodeStats(hcc, nc))));
- ncDataMap.put(nc, ncData);
- }
- ObjectNode result = om.createObjectNode();
- result.putPOJO("cc", resolveFutures(ccFutureData));
- List<Map<String, ?>> ncList = new ArrayList<>();
- for (Map.Entry<String, Map<String, Future<ObjectNode>>> entry : ncDataMap.entrySet()) {
- final Map<String, Object> ncMap = resolveFutures(entry.getValue());
- ncMap.put("node_id", entry.getKey());
- ncList.add(ncMap);
- }
- result.putPOJO("ncs", ncList);
- result.putPOJO("date", new Date());
- return result;
- }
-
- private Map<String, Object> resolveFutures(Map<String, Future<ObjectNode>> futureMap)
- throws ExecutionException, InterruptedException {
- Map<String, Object> result = new HashMap<>();
- for (Map.Entry<String, Future<ObjectNode>> entry : futureMap.entrySet()) {
- result.put(entry.getKey(), entry.getValue().get());
- }
- return result;
- }
-}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/60e7f12b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/FeedServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/FeedServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/FeedServlet.java
deleted file mode 100644
index 6c8019d..0000000
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/FeedServlet.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.asterix.api.http.servlet;
-
-import java.awt.image.BufferedImage;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-
-import javax.imageio.ImageIO;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-public class FeedServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
-
- @Override
- public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
- String resourcePath = null;
- String requestURI = request.getRequestURI();
-
- if (requestURI.equals("/")) {
- response.setContentType("text/html");
- resourcePath = "/feed/home.html";
- } else {
- resourcePath = requestURI;
- }
-
- InputStream is = FeedServlet.class.getResourceAsStream(resourcePath);
- if (is == null) {
- response.sendError(HttpServletResponse.SC_NOT_FOUND);
- return;
- }
-
- // Special handler for font files and .png resources
- if (resourcePath.endsWith(".png")) {
-
- BufferedImage img = ImageIO.read(is);
- OutputStream outputStream = response.getOutputStream();
- String formatName = "png";
- response.setContentType("image/png");
- ImageIO.write(img, formatName, outputStream);
- outputStream.close();
- return;
-
- }
-
- response.setCharacterEncoding("utf-8");
- InputStreamReader isr = new InputStreamReader(is);
- StringBuilder sb = new StringBuilder();
- BufferedReader br = new BufferedReader(isr);
- String line = br.readLine();
-
- while (line != null) {
- sb.append(line + "\n");
- line = br.readLine();
- }
-
- String outStr = null;
- outStr = sb.toString();
-
- PrintWriter out = response.getWriter();
- out.println(outStr);
- }
-}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/60e7f12b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/FullAPIServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/FullAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/FullAPIServlet.java
deleted file mode 100644
index 0f86ec6..0000000
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/FullAPIServlet.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.asterix.api.http.servlet;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.asterix.compiler.provider.ILangCompilationProvider;
-import org.apache.asterix.lang.common.base.Statement;
-import org.apache.asterix.translator.IStatementExecutorFactory;
-
-public class FullAPIServlet extends RESTAPIServlet {
-
- private static final long serialVersionUID = 1L;
- private static final String AQL_STMT_PARAM_NAME = "aql";
- private static final byte ALLOWED_CATEGORIES = Statement.Category.QUERY | Statement.Category.UPDATE
- | Statement.Category.DDL | Statement.Category.PROCEDURE;
-
- public FullAPIServlet(ILangCompilationProvider compilationProvider,
- IStatementExecutorFactory statementExecutorFactory) {
- super(compilationProvider, statementExecutorFactory);
- }
-
- @Override
- protected String getQueryParameter(HttpServletRequest request) {
- return request.getParameter(AQL_STMT_PARAM_NAME);
- }
-
- @Override
- protected byte getAllowedCategories() {
- return ALLOWED_CATEGORIES;
- }
-
- @Override
- protected String getErrorMessage() {
- throw new IllegalStateException();
- }
-}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/60e7f12b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryAPIServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryAPIServlet.java
deleted file mode 100644
index cc70324..0000000
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryAPIServlet.java
+++ /dev/null
@@ -1,50 +0,0 @@
-/*
- * 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.asterix.api.http.servlet;
-
-import javax.servlet.http.HttpServletRequest;
-
-import org.apache.asterix.compiler.provider.ILangCompilationProvider;
-import org.apache.asterix.lang.common.base.Statement;
-import org.apache.asterix.translator.IStatementExecutorFactory;
-
-public class QueryAPIServlet extends RESTAPIServlet {
- private static final long serialVersionUID = 1L;
- private static final byte ALLOWED_CATEGORIES = Statement.Category.QUERY;
-
- public QueryAPIServlet(ILangCompilationProvider compilationProvider,
- IStatementExecutorFactory queryTranslatorFactory) {
- super(compilationProvider, queryTranslatorFactory);
- }
-
- @Override
- protected String getQueryParameter(HttpServletRequest request) {
- return request.getParameter("query");
- }
-
- @Override
- protected byte getAllowedCategories() {
- return ALLOWED_CATEGORIES;
- }
-
- @Override
- protected String getErrorMessage() {
- return "Invalid statement: Non-query statement %s to the query API.";
- }
-}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/60e7f12b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryResultAPIServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryResultAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryResultAPIServlet.java
deleted file mode 100644
index b250690..0000000
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryResultAPIServlet.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * 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.asterix.api.http.servlet;
-
-import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
-import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_DATASET_ATTR;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.asterix.app.result.ResultReader;
-import org.apache.asterix.app.result.ResultUtil;
-import org.apache.asterix.common.exceptions.AsterixException;
-import org.apache.asterix.translator.IStatementExecutor.Stats;
-import org.apache.asterix.translator.SessionConfig;
-import org.apache.hyracks.api.client.HyracksConnection;
-import org.apache.hyracks.api.client.IHyracksClientConnection;
-import org.apache.hyracks.api.dataset.IHyracksDataset;
-import org.apache.hyracks.api.dataset.ResultSetId;
-import org.apache.hyracks.api.job.JobId;
-import org.apache.hyracks.client.dataset.HyracksDataset;
-import com.fasterxml.jackson.databind.node.ArrayNode;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-public class QueryResultAPIServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
- private static final Logger LOGGER = Logger.getLogger(QueryResultAPIServlet.class.getName());
-
- @Override
- public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
- int respCode = HttpServletResponse.SC_OK;
- response.setContentType("text/html"); // TODO this seems wrong ...
- response.setCharacterEncoding("utf-8");
- String strHandle = request.getParameter("handle");
- PrintWriter out = response.getWriter();
- ServletContext context = getServletContext();
- IHyracksClientConnection hcc;
- IHyracksDataset hds;
-
- try {
- if (strHandle == null || strHandle.isEmpty()) {
- throw new AsterixException("Empty request, no handle provided");
- }
-
- HyracksProperties hp = new HyracksProperties();
- String strIP = hp.getHyracksIPAddress();
- int port = hp.getHyracksPort();
-
- synchronized (context) {
- hcc = (IHyracksClientConnection) context.getAttribute(HYRACKS_CONNECTION_ATTR);
- if (hcc == null) {
- hcc = new HyracksConnection(strIP, port);
- context.setAttribute(HYRACKS_CONNECTION_ATTR, hcc);
- }
-
- hds = (IHyracksDataset) context.getAttribute(HYRACKS_DATASET_ATTR);
- if (hds == null) {
- hds = new HyracksDataset(hcc, ResultReader.FRAME_SIZE, ResultReader.NUM_READERS);
- context.setAttribute(HYRACKS_DATASET_ATTR, hds);
- }
- }
- ObjectMapper om = new ObjectMapper();
- ObjectNode handleObj = (ObjectNode) om.readTree(strHandle);
- ArrayNode handle = (ArrayNode) handleObj.get("handle");
- JobId jobId = new JobId(handle.get(0).asLong());
- ResultSetId rsId = new ResultSetId(handle.get(1).asLong());
-
- ResultReader resultReader = new ResultReader(hds);
- resultReader.open(jobId, rsId);
-
- // QQQ The output format is determined by the initial
- // query and cannot be modified here, so calling back to
- // initResponse() is really an error. We need to find a
- // way to send the same OutputFormat value here as was
- // originally determined there. Need to save this value on
- // some object that we can obtain here.
- SessionConfig sessionConfig = RESTAPIServlet.initResponse(request, response);
- ResultUtil.printResults(resultReader, sessionConfig, new Stats(), null);
-
- } catch (Exception e) {
- respCode = HttpServletResponse.SC_BAD_REQUEST;
- out.println(e.getMessage());
- LOGGER.log(Level.WARNING, "Error retrieving result", e);
- }
- response.setStatus(respCode);
- if (out.checkError()) {
- LOGGER.warning("Error flushing output writer");
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/60e7f12b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryServiceServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryServiceServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryServiceServlet.java
deleted file mode 100644
index a0454fd..0000000
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryServiceServlet.java
+++ /dev/null
@@ -1,571 +0,0 @@
-/*
- * 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.asterix.api.http.servlet;
-
-import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
-import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_DATASET_ATTR;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-import java.util.UUID;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import com.fasterxml.jackson.core.JsonParseException;
-import com.fasterxml.jackson.core.JsonProcessingException;
-import com.fasterxml.jackson.databind.JsonMappingException;
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.asterix.app.result.ResultReader;
-import org.apache.asterix.app.result.ResultUtil;
-import org.apache.asterix.app.translator.QueryTranslator;
-import org.apache.asterix.common.api.IClusterManagementWork;
-import org.apache.asterix.common.config.GlobalConfig;
-import org.apache.asterix.common.exceptions.AsterixException;
-import org.apache.asterix.common.utils.JSONUtil;
-import org.apache.asterix.compiler.provider.ILangCompilationProvider;
-import org.apache.asterix.lang.aql.parser.TokenMgrError;
-import org.apache.asterix.lang.common.base.IParser;
-import org.apache.asterix.lang.common.base.Statement;
-import org.apache.asterix.metadata.MetadataManager;
-import org.apache.asterix.runtime.util.ClusterStateManager;
-import org.apache.asterix.translator.IStatementExecutor;
-import org.apache.asterix.translator.IStatementExecutor.Stats;
-import org.apache.asterix.translator.IStatementExecutorFactory;
-import org.apache.asterix.translator.SessionConfig;
-import org.apache.commons.io.IOUtils;
-import org.apache.hyracks.algebricks.common.exceptions.AlgebricksException;
-import org.apache.hyracks.algebricks.core.algebra.prettyprint.AlgebricksAppendable;
-import org.apache.hyracks.api.client.IHyracksClientConnection;
-import org.apache.hyracks.api.dataset.IHyracksDataset;
-import org.apache.hyracks.client.dataset.HyracksDataset;
-
-public class QueryServiceServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
-
- private static final Logger LOGGER = Logger.getLogger(QueryServiceServlet.class.getName());
- private final transient ILangCompilationProvider compilationProvider;
- private final transient IStatementExecutorFactory statementExecutorFactory;
-
- public QueryServiceServlet(ILangCompilationProvider compilationProvider,
- IStatementExecutorFactory statementExecutorFactory) {
- this.compilationProvider = compilationProvider;
- this.statementExecutorFactory = statementExecutorFactory;
- }
-
- public enum Parameter {
- STATEMENT("statement"),
- FORMAT("format"),
- CLIENT_ID("client_context_id"),
- PRETTY("pretty"),
- MODE("mode");
-
- private final String str;
-
- Parameter(String str) {
- this.str = str;
- }
-
- public String str() {
- return str;
- }
- }
-
- private enum MediaType {
- CSV("text/csv"),
- JSON("application/json"),
- ADM("application/x-adm");
-
- private final String str;
-
- MediaType(String str) {
- this.str = str;
- }
-
- public String str() {
- return str;
- }
- }
-
- private enum Attribute {
- HEADER("header"),
- LOSSLESS("lossless");
-
- private final String str;
-
- Attribute(String str) {
- this.str = str;
- }
-
- public String str() {
- return str;
- }
- }
-
- public enum ResultFields {
- REQUEST_ID("requestID"),
- CLIENT_ID("clientContextID"),
- SIGNATURE("signature"),
- TYPE("type"),
- STATUS("status"),
- RESULTS("results"),
- HANDLE("handle"),
- ERRORS("errors"),
- METRICS("metrics");
-
- private final String str;
-
- ResultFields(String str) {
- this.str = str;
- }
-
- public String str() {
- return str;
- }
- }
-
- public enum ResultStatus {
- SUCCESS("success"),
- TIMEOUT("timeout"),
- ERRORS("errors"),
- FATAL("fatal");
-
- private final String str;
-
- ResultStatus(String str) {
- this.str = str;
- }
-
- public String str() {
- return str;
- }
- }
-
- private enum ErrorField {
- CODE("code"),
- MSG("msg"),
- STACK("stack");
-
- private final String str;
-
- ErrorField(String str) {
- this.str = str;
- }
-
- public String str() {
- return str;
- }
- }
-
- private enum Metrics {
- ELAPSED_TIME("elapsedTime"),
- EXECUTION_TIME("executionTime"),
- RESULT_COUNT("resultCount"),
- RESULT_SIZE("resultSize");
-
- private final String str;
-
- Metrics(String str) {
- this.str = str;
- }
-
- public String str() {
- return str;
- }
- }
-
- enum TimeUnit {
- SEC("s", 9),
- MILLI("ms", 6),
- MICRO("�s", 3),
- NANO("ns", 0);
-
- String unit;
- int nanoDigits;
-
- TimeUnit(String unit, int nanoDigits) {
- this.unit = unit;
- this.nanoDigits = nanoDigits;
- }
-
- static String formatNanos(long nanoTime) {
- final String strTime = String.valueOf(nanoTime);
- final int len = strTime.length();
- for (TimeUnit tu : TimeUnit.values()) {
- if (len > tu.nanoDigits) {
- final String integer = strTime.substring(0, len - tu.nanoDigits);
- final String fractional = strTime.substring(len - tu.nanoDigits);
- return integer + (fractional.length() > 0 ? "." + fractional : "") + tu.unit;
- }
- }
- return "illegal string value: " + strTime;
- }
- }
-
- static class RequestParameters {
- String statement;
- String format;
- boolean pretty;
- String clientContextID;
- String mode;
-
- @Override
- public String toString() {
- return append(new StringBuilder()).toString();
- }
-
- public StringBuilder append(final StringBuilder sb) {
- sb.append("{ ");
- sb.append("\"statement\": \"");
- JSONUtil.escape(sb, statement);
- sb.append("\", ");
- sb.append("\"format\": \"").append(format).append("\", ");
- sb.append("\"pretty\": ").append(pretty).append(", ");
- sb.append("\"mode\": ").append(mode).append(", ");
- sb.append("\"clientContextID\": \"").append(clientContextID).append("\" ");
- sb.append('}');
- return sb;
- }
- }
-
- private static String getParameterValue(String content, String attribute) {
- if (content == null || attribute == null) {
- return null;
- }
- int sc = content.indexOf(';');
- if (sc < 0) {
- return null;
- }
- int eq = content.indexOf('=', sc + 1);
- if (eq < 0) {
- return null;
- }
- if (content.substring(sc + 1, eq).trim().equalsIgnoreCase(attribute)) {
- return content.substring(eq + 1).trim().toLowerCase();
- }
- return null;
- }
-
- private static String toLower(String s) {
- return s != null ? s.toLowerCase() : s;
- }
-
- private static SessionConfig.OutputFormat getFormat(String format) {
- if (format != null) {
- if (format.startsWith(MediaType.CSV.str())) {
- return SessionConfig.OutputFormat.CSV;
- }
- if (format.equals(MediaType.ADM.str())) {
- return SessionConfig.OutputFormat.ADM;
- }
- if (format.startsWith(MediaType.JSON.str())) {
- return Boolean.parseBoolean(getParameterValue(format, Attribute.LOSSLESS.str()))
- ? SessionConfig.OutputFormat.LOSSLESS_JSON : SessionConfig.OutputFormat.CLEAN_JSON;
- }
- }
- return SessionConfig.OutputFormat.CLEAN_JSON;
- }
-
- private static SessionConfig createSessionConfig(RequestParameters param, PrintWriter resultWriter) {
- SessionConfig.ResultDecorator resultPrefix = new SessionConfig.ResultDecorator() {
- int resultNo = -1;
-
- @Override
- public AlgebricksAppendable append(AlgebricksAppendable app) throws AlgebricksException {
- app.append("\t\"");
- app.append(ResultFields.RESULTS.str());
- if (resultNo >= 0) {
- app.append('-').append(String.valueOf(resultNo));
- }
- ++resultNo;
- app.append("\": ");
- return app;
- }
- };
-
-
- SessionConfig.ResultDecorator resultPostfix = (AlgebricksAppendable app) -> app.append("\t,\n");
-
- SessionConfig.ResultDecorator handlePrefix = new SessionConfig.ResultDecorator() {
- @Override
- public AlgebricksAppendable append(AlgebricksAppendable app) throws AlgebricksException {
- app.append("\t\"");
- app.append(ResultFields.HANDLE.str());
- app.append("\": ");
- return app;
- }
- };
-
- SessionConfig.ResultDecorator handlePostfix = (AlgebricksAppendable app) -> app.append(",\n");
-
- SessionConfig.OutputFormat format = getFormat(param.format);
- SessionConfig sessionConfig = new SessionConfig(resultWriter, format, resultPrefix, resultPostfix, handlePrefix,
- handlePostfix);
- sessionConfig.set(SessionConfig.FORMAT_WRAPPER_ARRAY, true);
- sessionConfig.set(SessionConfig.FORMAT_INDENT_JSON, param.pretty);
- sessionConfig.set(SessionConfig.FORMAT_QUOTE_RECORD,
- format != SessionConfig.OutputFormat.CLEAN_JSON && format != SessionConfig.OutputFormat.LOSSLESS_JSON);
- sessionConfig.set(SessionConfig.FORMAT_CSV_HEADER, format == SessionConfig.OutputFormat.CSV
- && "present".equals(getParameterValue(param.format, Attribute.HEADER.str())));
- return sessionConfig;
- }
-
- private static void printField(PrintWriter pw, String name, String value) {
- printField(pw, name, value, true);
- }
-
- private static void printField(PrintWriter pw, String name, String value, boolean comma) {
- pw.print("\t\"");
- pw.print(name);
- pw.print("\": \"");
- pw.print(value);
- pw.print('"');
- if (comma) {
- pw.print(',');
- }
- pw.print('\n');
- }
-
- private static UUID printRequestId(PrintWriter pw) {
- UUID requestId = UUID.randomUUID();
- printField(pw, ResultFields.REQUEST_ID.str(), requestId.toString());
- return requestId;
- }
-
- private static void printClientContextID(PrintWriter pw, RequestParameters params) {
- if (params.clientContextID != null && !params.clientContextID.isEmpty()) {
- printField(pw, ResultFields.CLIENT_ID.str(), params.clientContextID);
- }
- }
-
- private static void printSignature(PrintWriter pw) {
- printField(pw, ResultFields.SIGNATURE.str(), "*");
- }
-
- private static void printType(PrintWriter pw, SessionConfig sessionConfig) {
- switch (sessionConfig.fmt()) {
- case ADM:
- printField(pw, ResultFields.TYPE.str(), MediaType.ADM.str());
- break;
- case CSV:
- String contentType = MediaType.CSV.str() + "; header="
- + (sessionConfig.is(SessionConfig.FORMAT_CSV_HEADER) ? "present" : "absent");
- printField(pw, ResultFields.TYPE.str(), contentType);
- break;
- default:
- break;
- }
- }
-
- private static void printStatus(PrintWriter pw, ResultStatus rs) {
- printField(pw, ResultFields.STATUS.str(), rs.str());
- }
-
- private static void printError(PrintWriter pw, Throwable e) throws JsonProcessingException {
- Throwable rootCause = ResultUtil.getRootCause(e);
- if (rootCause == null) {
- rootCause = e;
- }
- final boolean addStack = false;
- pw.print("\t\"");
- pw.print(ResultFields.ERRORS.str());
- pw.print("\": [{ \n");
- printField(pw, ErrorField.CODE.str(), "1");
-
- final String msg = rootCause.getMessage();
- printField(pw, ErrorField.MSG.str(), JSONUtil.escape(msg != null ? msg : rootCause.getClass().getSimpleName()),
- addStack);
- pw.print("\t}],\n");
- }
-
- private static void printMetrics(PrintWriter pw, long elapsedTime, long executionTime, long resultCount,
- long resultSize) {
- pw.print("\t\"");
- pw.print(ResultFields.METRICS.str());
- pw.print("\": {\n");
- pw.print("\t");
- printField(pw, Metrics.ELAPSED_TIME.str(), TimeUnit.formatNanos(elapsedTime));
- pw.print("\t");
- printField(pw, Metrics.EXECUTION_TIME.str(), TimeUnit.formatNanos(executionTime));
- pw.print("\t");
- printField(pw, Metrics.RESULT_COUNT.str(), String.valueOf(resultCount));
- pw.print("\t");
- printField(pw, Metrics.RESULT_SIZE.str(), String.valueOf(resultSize), false);
- pw.print("\t}\n");
- }
-
- @Override
- protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException {
- try {
- handleRequest(getRequestParameters(request), response);
- } catch (IOException e) {
- // Servlet methods should not throw exceptions
- // http://cwe.mitre.org/data/definitions/600.html
- GlobalConfig.ASTERIX_LOGGER.log(Level.SEVERE, e.getMessage(), e);
- }
- }
-
- private String getOptText(JsonNode node, String fieldName) {
- final JsonNode value = node.get(fieldName);
- return value != null ? value.asText() : null;
- }
-
- private boolean getOptBoolean(JsonNode node, String fieldName, boolean defaultValue) {
- final JsonNode value = node.get(fieldName);
- return value != null ? value.asBoolean() : defaultValue;
- }
-
- private RequestParameters getRequestParameters(HttpServletRequest request) throws IOException {
- final String contentTypeParam = request.getContentType();
- int sep = contentTypeParam.indexOf(';');
- final String contentType = sep < 0 ? contentTypeParam.trim() : contentTypeParam.substring(0, sep).trim();
- RequestParameters param = new RequestParameters();
- if (MediaType.JSON.str().equals(contentType)) {
- try {
- JsonNode jsonRequest = new ObjectMapper().readTree(getRequestBody(request));
- param.statement = jsonRequest.get(Parameter.STATEMENT.str()).asText();
- param.format = toLower(getOptText(jsonRequest, Parameter.FORMAT.str()));
- param.pretty = getOptBoolean(jsonRequest, Parameter.PRETTY.str(), false);
- param.mode = toLower(getOptText(jsonRequest, Parameter.MODE.str()));
- param.clientContextID = getOptText(jsonRequest, Parameter.CLIENT_ID.str());
- } catch (JsonParseException | JsonMappingException e) {
- // if the JSON parsing fails, the statement is empty and we get an empty statement error
- GlobalConfig.ASTERIX_LOGGER.log(Level.SEVERE, e.getMessage(), e);
- }
- } else {
- param.statement = request.getParameter(Parameter.STATEMENT.str());
- if (param.statement == null) {
- param.statement = getRequestBody(request);
- }
- param.format = toLower(request.getParameter(Parameter.FORMAT.str()));
- param.pretty = Boolean.parseBoolean(request.getParameter(Parameter.PRETTY.str()));
- param.mode = toLower(request.getParameter(Parameter.MODE.str()));
- param.clientContextID = request.getParameter(Parameter.CLIENT_ID.str());
- }
- return param;
- }
-
- private static String getRequestBody(HttpServletRequest request) throws IOException {
- StringWriter sw = new StringWriter();
- IOUtils.copy(request.getInputStream(), sw, StandardCharsets.UTF_8.name());
- return sw.toString();
- }
-
- private static QueryTranslator.ResultDelivery parseResultDelivery(String mode) {
- if ("async".equals(mode)) {
- return QueryTranslator.ResultDelivery.ASYNC;
- } else if ("deferred".equals(mode)) {
- return QueryTranslator.ResultDelivery.DEFERRED;
- } else {
- return QueryTranslator.ResultDelivery.IMMEDIATE;
- }
- }
-
- private void handleRequest(RequestParameters param, HttpServletResponse response) throws IOException {
- LOGGER.info(param.toString());
- long elapsedStart = System.nanoTime();
- final StringWriter stringWriter = new StringWriter();
- final PrintWriter resultWriter = new PrintWriter(stringWriter);
-
- QueryTranslator.ResultDelivery delivery = parseResultDelivery(param.mode);
-
- SessionConfig sessionConfig = createSessionConfig(param, resultWriter);
- response.setCharacterEncoding("utf-8");
- response.setContentType(MediaType.JSON.str());
-
- int respCode = HttpServletResponse.SC_OK;
- Stats stats = new Stats();
- long execStart = -1;
- long execEnd = -1;
-
- resultWriter.print("{\n");
- printRequestId(resultWriter);
- printClientContextID(resultWriter, param);
- printSignature(resultWriter);
- printType(resultWriter, sessionConfig);
- try {
- final IClusterManagementWork.ClusterState clusterState = ClusterStateManager.INSTANCE.getState();
- if (clusterState != IClusterManagementWork.ClusterState.ACTIVE) {
- // using a plain IllegalStateException here to get into the right catch clause for a 500
- throw new IllegalStateException("Cannot execute request, cluster is " + clusterState);
- }
- if (param.statement == null || param.statement.isEmpty()) {
- throw new AsterixException("Empty request, no statement provided");
- }
- IHyracksClientConnection hcc;
- IHyracksDataset hds;
- ServletContext context = getServletContext();
- synchronized (context) {
- hcc = (IHyracksClientConnection) context.getAttribute(HYRACKS_CONNECTION_ATTR);
- hds = (IHyracksDataset) context.getAttribute(HYRACKS_DATASET_ATTR);
- if (hds == null) {
- hds = new HyracksDataset(hcc, ResultReader.FRAME_SIZE, ResultReader.NUM_READERS);
- context.setAttribute(HYRACKS_DATASET_ATTR, hds);
- }
- }
- IParser parser = compilationProvider.getParserFactory().createParser(param.statement);
- List<Statement> statements = parser.parse();
- MetadataManager.INSTANCE.init();
- IStatementExecutor translator = statementExecutorFactory.create(statements, sessionConfig,
- compilationProvider);
- execStart = System.nanoTime();
- translator.compileAndExecute(hcc, hds, delivery, stats);
- execEnd = System.nanoTime();
- printStatus(resultWriter, ResultStatus.SUCCESS);
- } catch (AsterixException | TokenMgrError | org.apache.asterix.aqlplus.parser.TokenMgrError pe) {
- GlobalConfig.ASTERIX_LOGGER.log(Level.SEVERE, pe.getMessage(), pe);
- printError(resultWriter, pe);
- printStatus(resultWriter, ResultStatus.FATAL);
- respCode = HttpServletResponse.SC_BAD_REQUEST;
- } catch (Exception e) {
- GlobalConfig.ASTERIX_LOGGER.log(Level.SEVERE, e.getMessage(), e);
- printError(resultWriter, e);
- printStatus(resultWriter, ResultStatus.FATAL);
- respCode = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
- } finally {
- if (execStart == -1) {
- execEnd = -1;
- } else if (execEnd == -1) {
- execEnd = System.nanoTime();
- }
- }
- printMetrics(resultWriter, System.nanoTime() - elapsedStart, execEnd - execStart, stats.getCount(),
- stats.getSize());
- resultWriter.print("}\n");
- resultWriter.flush();
- String result = stringWriter.toString();
-
- GlobalConfig.ASTERIX_LOGGER.log(Level.FINE, result);
-
- response.setStatus(respCode);
- response.getWriter().print(result);
- if (response.getWriter().checkError()) {
- LOGGER.warning("Error flushing output writer");
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/60e7f12b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryStatusAPIServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryStatusAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryStatusAPIServlet.java
deleted file mode 100644
index 6d1b1b2..0000000
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryStatusAPIServlet.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.asterix.api.http.servlet;
-
-import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
-import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_DATASET_ATTR;
-
-import java.io.IOException;
-import java.io.PrintWriter;
-
-import javax.servlet.ServletContext;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import com.fasterxml.jackson.databind.JsonNode;
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.asterix.app.result.ResultReader;
-import org.apache.hyracks.api.client.IHyracksClientConnection;
-import org.apache.hyracks.api.dataset.IHyracksDataset;
-import org.apache.hyracks.api.dataset.ResultSetId;
-import org.apache.hyracks.api.job.JobId;
-import org.apache.hyracks.client.dataset.HyracksDataset;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-public class QueryStatusAPIServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
-
- @Override
- public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
- response.setContentType("text/html");
- response.setCharacterEncoding("utf-8");
- String strHandle = request.getParameter("handle");
- PrintWriter out = response.getWriter();
- ServletContext context = getServletContext();
- IHyracksClientConnection hcc;
- IHyracksDataset hds;
-
- try {
- synchronized (context) {
- hcc = (IHyracksClientConnection) context.getAttribute(HYRACKS_CONNECTION_ATTR);
-
- hds = (IHyracksDataset) context.getAttribute(HYRACKS_DATASET_ATTR);
- if (hds == null) {
- hds = new HyracksDataset(hcc, ResultReader.FRAME_SIZE, ResultReader.NUM_READERS);
- context.setAttribute(HYRACKS_DATASET_ATTR, hds);
- }
- }
- ObjectMapper om = new ObjectMapper();
- JsonNode handleObj = om.readTree(strHandle);
- JsonNode handle = handleObj.get("handle");
- JobId jobId = new JobId(handle.get(0).asLong());
- ResultSetId rsId = new ResultSetId(handle.get(1).asLong());
-
- /* TODO(madhusudancs): We need to find a way to LOSSLESS_JSON serialize default format obtained from
- * metadataProvider in the AQLTranslator and store it as part of the result handle.
- */
- ResultReader resultReader = new ResultReader(hds);
- resultReader.open(jobId, rsId);
-
- ObjectNode jsonResponse = om.createObjectNode();
- String status;
- switch (resultReader.getStatus()) {
- case RUNNING:
- status = "RUNNING";
- break;
- case FAILED:
- status = "ERROR";
- break;
- case SUCCESS:
- status = "SUCCESS";
- break;
- default:
- status = "ERROR";
- break;
- }
- jsonResponse.put("status", status);
- out.write(jsonResponse.toString());
-
- } catch (Exception e) {
- out.println(e.getMessage());
- e.printStackTrace(out);
- }
- }
-}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/60e7f12b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryWebInterfaceServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryWebInterfaceServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryWebInterfaceServlet.java
deleted file mode 100644
index d3e5556..0000000
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/QueryWebInterfaceServlet.java
+++ /dev/null
@@ -1,132 +0,0 @@
-/*
- * 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.asterix.api.http.servlet;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.PrintWriter;
-import java.util.HashMap;
-import java.util.Map;
-
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import org.apache.asterix.common.config.ExternalProperties;
-import org.apache.asterix.runtime.util.AppContextInfo;
-import org.apache.commons.io.IOUtils;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-public class QueryWebInterfaceServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
- private static final HashMap<String, String> fileMimePair = new HashMap<>();
- private static final Log LOG = LogFactory.getLog(QueryWebInterfaceServlet.class);
-
- public QueryWebInterfaceServlet() {
- fileMimePair.put("png", "image/png");
- fileMimePair.put("eot", "application/vnd.ms-fontobject");
- fileMimePair.put("svg", "image/svg+xml\t");
- fileMimePair.put("ttf", "application/x-font-ttf");
- fileMimePair.put("woff", "application/x-font-woff");
- fileMimePair.put("woff2", "application/x-font-woff");
- fileMimePair.put("html", "text/html");
- fileMimePair.put("css", "text/css");
- fileMimePair.put("js", "application/javascript");
- }
-
- @Override
- public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
- String resourcePath = null;
- String requestURI = request.getRequestURI();
-
- if ("/".equals(requestURI)) {
- response.setContentType("text/html");
- resourcePath = "/queryui/queryui.html";
- } else {
- resourcePath = requestURI;
- }
-
- try (InputStream is = APIServlet.class.getResourceAsStream(resourcePath)) {
- if (is == null) {
- try {
- response.sendError(HttpServletResponse.SC_NOT_FOUND);
- } catch (IllegalStateException | IOException e) {
- LOG.error(e);
- }
- return;
- }
- // Multiple MIME type support
- for (Map.Entry<String, String> entry : fileMimePair.entrySet()) {
- OutputStream out = null;
- if (resourcePath.endsWith(entry.getKey())) {
- response.setContentType(entry.getValue());
- try {
- out = response.getOutputStream();
- IOUtils.copy(is, out);
-
- } catch (IOException e) {
- LOG.info(e);
- } finally {
-
- if (out != null) {
- IOUtils.closeQuietly(out);
- }
- IOUtils.closeQuietly(is);
-
- }
- return;
- }
- }
- try {
- response.sendError(HttpServletResponse.SC_BAD_REQUEST);
- } catch (IllegalStateException | IOException e) {
- LOG.error(e);
- }
- }
- }
-
- @Override
- public void doPost(HttpServletRequest request, HttpServletResponse response) throws IOException {
- response.setCharacterEncoding("utf-8");
- response.setContentType("application/json");
- ExternalProperties externalProperties = AppContextInfo.INSTANCE.getExternalProperties();
- ObjectMapper om = new ObjectMapper();
- ObjectNode obj = om.createObjectNode();
- try {
- PrintWriter out = response.getWriter();
- obj.put("api_port", String.valueOf(externalProperties.getAPIServerPort()));
- out.println(obj.toString());
- return;
- } catch (Exception e) {
- LOG.error(e);
- }
-
- try {
- response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- } catch (IllegalStateException | IOException e) {
- LOG.error(e);
- }
- }
-
-}
http://git-wip-us.apache.org/repos/asf/asterixdb/blob/60e7f12b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/RESTAPIServlet.java
----------------------------------------------------------------------
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/RESTAPIServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/RESTAPIServlet.java
deleted file mode 100644
index dd030b0..0000000
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/servlet/RESTAPIServlet.java
+++ /dev/null
@@ -1,252 +0,0 @@
-/*
- * 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.asterix.api.http.servlet;
-
-import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_CONNECTION_ATTR;
-import static org.apache.asterix.api.http.servlet.ServletConstants.HYRACKS_DATASET_ATTR;
-
-import java.io.IOException;
-import java.io.StringWriter;
-import java.nio.charset.StandardCharsets;
-import java.util.List;
-import java.util.logging.Level;
-
-import javax.servlet.ServletContext;
-import javax.servlet.ServletException;
-import javax.servlet.http.HttpServlet;
-import javax.servlet.http.HttpServletRequest;
-import javax.servlet.http.HttpServletResponse;
-
-import com.fasterxml.jackson.databind.ObjectMapper;
-import org.apache.asterix.app.result.ResultReader;
-import org.apache.asterix.app.result.ResultUtil;
-import org.apache.asterix.app.translator.QueryTranslator;
-import org.apache.asterix.common.config.GlobalConfig;
-import org.apache.asterix.common.exceptions.AsterixException;
-import org.apache.asterix.compiler.provider.ILangCompilationProvider;
-import org.apache.asterix.lang.aql.parser.TokenMgrError;
-import org.apache.asterix.lang.common.base.IParser;
-import org.apache.asterix.lang.common.base.IParserFactory;
-import org.apache.asterix.lang.common.base.Statement;
-import org.apache.asterix.metadata.MetadataManager;
-import org.apache.asterix.translator.IStatementExecutor;
-import org.apache.asterix.translator.IStatementExecutorFactory;
-import org.apache.asterix.translator.SessionConfig;
-import org.apache.asterix.translator.SessionConfig.OutputFormat;
-import org.apache.commons.io.IOUtils;
-import org.apache.hyracks.algebricks.core.algebra.prettyprint.AlgebricksAppendable;
-import org.apache.hyracks.api.client.IHyracksClientConnection;
-import org.apache.hyracks.api.dataset.IHyracksDataset;
-import org.apache.hyracks.client.dataset.HyracksDataset;
-import com.fasterxml.jackson.databind.node.ObjectNode;
-
-abstract class RESTAPIServlet extends HttpServlet {
- private static final long serialVersionUID = 1L;
-
- private final ILangCompilationProvider compilationProvider;
- private final IParserFactory parserFactory;
- private final transient IStatementExecutorFactory statementExecutorFactory;
-
- public RESTAPIServlet(ILangCompilationProvider compilationProvider,
- IStatementExecutorFactory statementExecutorFactory) {
- this.compilationProvider = compilationProvider;
- this.parserFactory = compilationProvider.getParserFactory();
- this.statementExecutorFactory = statementExecutorFactory;
- }
-
- /**
- * Initialize the Content-Type of the response, and construct a
- * SessionConfig with the appropriate output writer and output-format
- * based on the Accept: header and other servlet parameters.
- */
- static SessionConfig initResponse(HttpServletRequest request, HttpServletResponse response) throws IOException {
- response.setCharacterEncoding("utf-8");
-
- // CLEAN_JSON output is the default; most generally useful for a
- // programmatic HTTP API
- OutputFormat format = OutputFormat.CLEAN_JSON;
-
- // First check the "output" servlet parameter.
- String output = request.getParameter("output");
- String accept = request.getHeader("Accept");
- if (accept == null) {
- accept = "";
- }
- if (output != null) {
- if (output.equals("CSV")) {
- format = OutputFormat.CSV;
- } else if (output.equals("ADM")) {
- format = OutputFormat.ADM;
- }
- } else {
- // Second check the Accept: HTTP header.
- if (accept.contains("application/x-adm")) {
- format = OutputFormat.ADM;
- } else if (accept.contains("text/csv")) {
- format = OutputFormat.CSV;
- }
- }
-
- // If it's JSON, check for the "lossless" flag
-
- if (format == OutputFormat.CLEAN_JSON
- && ("true".equals(request.getParameter("lossless")) || accept.contains("lossless=true"))) {
- format = OutputFormat.LOSSLESS_JSON;
- }
-
- SessionConfig.ResultDecorator handlePrefix = (AlgebricksAppendable app) -> app.append("{ \"").append("handle")
- .append("\": ");
- SessionConfig.ResultDecorator handlePostfix = (AlgebricksAppendable app) -> app.append(" }");
-
- SessionConfig sessionConfig = new SessionConfig(response.getWriter(), format, null, null, handlePrefix,
- handlePostfix);
-
- // If it's JSON or ADM, check for the "wrapper-array" flag. Default is
- // "true" for JSON and "false" for ADM. (Not applicable for CSV.)
- boolean wrapper_array;
- switch (format) {
- case CLEAN_JSON:
- case LOSSLESS_JSON:
- wrapper_array = true;
- break;
- default:
- wrapper_array = false;
- break;
- }
- String wrapper_param = request.getParameter("wrapper-array");
- if (wrapper_param != null) {
- wrapper_array = Boolean.valueOf(wrapper_param);
- } else if (accept.contains("wrap-array=true")) {
- wrapper_array = true;
- } else if (accept.contains("wrap-array=false")) {
- wrapper_array = false;
- }
- sessionConfig.set(SessionConfig.FORMAT_WRAPPER_ARRAY, wrapper_array);
-
- // Now that format is set, output the content-type
- switch (format) {
- case ADM:
- response.setContentType("application/x-adm");
- break;
- case CLEAN_JSON:
- // No need to reflect "clean-ness" in output type; fall through
- case LOSSLESS_JSON:
- response.setContentType("application/json");
- break;
- case CSV: {
- // Check for header parameter or in Accept:.
- if ("present".equals(request.getParameter("header")) || accept.contains("header=present")) {
- response.setContentType("text/csv; header=present");
- sessionConfig.set(SessionConfig.FORMAT_CSV_HEADER, true);
- } else {
- response.setContentType("text/csv; header=absent");
- }
- }
- }
-
- return sessionConfig;
- }
-
- @Override
- protected void doPost(HttpServletRequest request, HttpServletResponse response)
- throws ServletException, IOException {
- StringWriter sw = new StringWriter();
- IOUtils.copy(request.getInputStream(), sw, StandardCharsets.UTF_8.name());
- String query = sw.toString();
- handleRequest(request, response, query);
- }
-
- @Override
- public void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
- String query = getQueryParameter(request);
- handleRequest(request, response, query);
- }
-
- public void handleRequest(HttpServletRequest request, HttpServletResponse response, String query)
- throws IOException {
- // enable cross-origin resource sharing
- response.addHeader("Access-Control-Allow-Origin", "*");
- response.addHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
-
- SessionConfig sessionConfig = initResponse(request, response);
- QueryTranslator.ResultDelivery resultDelivery = whichResultDelivery(request);
-
- ServletContext context = getServletContext();
- IHyracksClientConnection hcc;
- IHyracksDataset hds;
-
- try {
- synchronized (context) {
- hcc = (IHyracksClientConnection) context.getAttribute(HYRACKS_CONNECTION_ATTR);
- hds = (IHyracksDataset) context.getAttribute(HYRACKS_DATASET_ATTR);
- if (hds == null) {
- hds = new HyracksDataset(hcc, ResultReader.FRAME_SIZE, ResultReader.NUM_READERS);
- context.setAttribute(HYRACKS_DATASET_ATTR, hds);
- }
- }
-
- IParser parser = parserFactory.createParser(query);
- List<Statement> aqlStatements = parser.parse();
- if (!containsForbiddenStatements(aqlStatements)) {
- MetadataManager.INSTANCE.init();
- IStatementExecutor translator =
- statementExecutorFactory.create(aqlStatements, sessionConfig, compilationProvider);
- translator.compileAndExecute(hcc, hds, resultDelivery);
- }
- } catch (AsterixException | TokenMgrError | org.apache.asterix.aqlplus.parser.TokenMgrError pe) {
- GlobalConfig.ASTERIX_LOGGER.log(Level.SEVERE, pe.getMessage(), pe);
- String errorMessage = ResultUtil.buildParseExceptionMessage(pe, query);
- ObjectNode errorResp =
- ResultUtil.getErrorResponse(2, errorMessage, "", ResultUtil.extractFullStackTrace(pe));
- sessionConfig.out().write(new ObjectMapper().writeValueAsString(errorResp));
- response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- } catch (Exception e) {
- GlobalConfig.ASTERIX_LOGGER.log(Level.SEVERE, e.getMessage(), e);
- ResultUtil.apiErrorHandler(sessionConfig.out(), e);
- response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
- }
- }
-
- private boolean containsForbiddenStatements(List<Statement> aqlStatements) throws AsterixException {
- for (Statement st : aqlStatements) {
- if ((st.getCategory() & getAllowedCategories()) == 0) {
- throw new AsterixException(String.format(getErrorMessage(), st.getKind()));
- }
- }
- return false;
- }
-
- protected QueryTranslator.ResultDelivery whichResultDelivery(HttpServletRequest request) {
- String mode = request.getParameter("mode");
- if (mode != null) {
- if ("asynchronous".equals(mode) || "async".equals(mode)) {
- return QueryTranslator.ResultDelivery.ASYNC;
- } else if ("asynchronous-deferred".equals(mode) || "deferred".equals(mode)) {
- return QueryTranslator.ResultDelivery.DEFERRED;
- }
- }
- return QueryTranslator.ResultDelivery.IMMEDIATE;
- }
-
- protected abstract String getQueryParameter(HttpServletRequest request);
-
- protected abstract byte getAllowedCategories();
-
- protected abstract String getErrorMessage();
-}