[NO ISSUE][API] Make QueryServiceServlet return 'server' header

- user model changes: no
- storage format changes: no
- interface changes: yes

Details:
- Add 'server' header to QueryServiceServlet's
  'options' method response

Change-Id: If2e465f1f48235d5bd036ed0da8b0100a9ec7612
Reviewed-on: https://asterix-gerrit.ics.uci.edu/c/asterixdb/+/13585
Integration-Tests: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Tested-by: Jenkins <jenkins@fulliautomatix.ics.uci.edu>
Reviewed-by: Michael Blow <mblow@apache.org>
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
index 74682cf..26e4b96 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/api/http/server/QueryServiceServlet.java
@@ -63,6 +63,7 @@
 import org.apache.asterix.common.exceptions.ErrorCode;
 import org.apache.asterix.common.exceptions.RuntimeDataException;
 import org.apache.asterix.compiler.provider.ILangCompilationProvider;
+import org.apache.asterix.hyracks.bootstrap.ApplicationConfigurator;
 import org.apache.asterix.lang.common.base.IParser;
 import org.apache.asterix.lang.common.base.IParserFactory;
 import org.apache.asterix.lang.common.base.Statement;
@@ -145,6 +146,10 @@
             response.setHeader("Access-Control-Allow-Origin", request.getHeader("Origin"));
         }
         response.setHeader("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
+        String server = getServerHeaderValue();
+        if (server != null) {
+            HttpUtil.setServerHeader(response, server);
+        }
         response.setStatus(HttpResponseStatus.OK);
     }
 
@@ -520,4 +525,21 @@
     protected static boolean isPrintingProfile(IStatementExecutor.Stats stats) {
         return stats.getProfileType() == Stats.ProfileType.FULL && stats.getJobProfile() != null;
     }
+
+    protected final String getServerHeaderValue() {
+        String name = getApplicationName();
+        if (name == null) {
+            return null;
+        }
+        String version = getApplicationVersion();
+        return version != null ? name + "/" + version : name;
+    }
+
+    protected String getApplicationName() {
+        return ApplicationConfigurator.APPLICATION_NAME;
+    }
+
+    protected String getApplicationVersion() {
+        return ApplicationConfigurator.getApplicationVersion(appCtx.getBuildProperties());
+    }
 }
diff --git a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/ApplicationConfigurator.java b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/ApplicationConfigurator.java
index c76d9b8..98a1820 100644
--- a/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/ApplicationConfigurator.java
+++ b/asterixdb/asterix-app/src/main/java/org/apache/asterix/hyracks/bootstrap/ApplicationConfigurator.java
@@ -24,6 +24,7 @@
 import java.util.Properties;
 
 import org.apache.asterix.common.config.AsterixProperties;
+import org.apache.asterix.common.config.BuildProperties;
 import org.apache.asterix.common.exceptions.ErrorCode;
 import org.apache.asterix.common.exceptions.RuntimeDataException;
 import org.apache.hyracks.api.config.IConfigManager;
@@ -36,9 +37,11 @@
 import org.apache.logging.log4j.LogManager;
 import org.apache.logging.log4j.Logger;
 
-class ApplicationConfigurator {
+public class ApplicationConfigurator {
     private static final Logger LOGGER = LogManager.getLogger();
 
+    public static final String APPLICATION_NAME = "Apache AsterixDB";
+
     private ApplicationConfigurator() {
     }
 
@@ -83,4 +86,8 @@
             LOGGER.warn("JRE version \"" + javaVersion + "\" is untested");
         }
     }
+
+    public static String getApplicationVersion(BuildProperties buildProperties) {
+        return buildProperties.getAllProps().get("git.build.version");
+    }
 }
diff --git a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java
index 835cd54..1d5df5c 100644
--- a/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java
+++ b/hyracks-fullstack/hyracks/hyracks-http/src/main/java/org/apache/hyracks/http/server/utils/HttpUtil.java
@@ -110,6 +110,10 @@
         response.setHeader(HttpHeaderNames.CONTENT_TYPE, type);
     }
 
+    public static void setServerHeader(IServletResponse response, String value) throws IOException {
+        response.setHeader(HttpHeaderNames.SERVER, value);
+    }
+
     public static Map<String, String> getRequestHeaders(IServletRequest request) {
         Map<String, String> headers = new HashMap<>();
         request.getHttpRequest().headers().forEach(entry -> headers.put(entry.getKey(), entry.getValue()));