ElasticRestClientProvider: Detect Elasticsearch version

On initialization of the client, make a GET request to the Elasticsearch
server and parse the version out of the response.

Log the version at info level.

In follow-up commits, the version will be stored and used to change the
structure of queries based on which Elasticsearch version is used.

Change-Id: I693b54d008b24191c66dbf16815a223441d22d43
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticException.java b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticException.java
new file mode 100644
index 0000000..d4baf75
--- /dev/null
+++ b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticException.java
@@ -0,0 +1,27 @@
+// Copyright (C) 2018 The Android Open Source Project
+//
+// Licensed 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 com.google.gerrit.elasticsearch;
+
+class ElasticException extends RuntimeException {
+  private static final long serialVersionUID = 1L;
+
+  ElasticException(String message) {
+    super(message);
+  }
+
+  ElasticException(String message, Throwable cause) {
+    super(message, cause);
+  }
+}
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticRestClientProvider.java b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticRestClientProvider.java
index 5217cfb..a81cae6 100644
--- a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticRestClientProvider.java
+++ b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticRestClientProvider.java
@@ -16,21 +16,28 @@
 
 import com.google.gerrit.extensions.events.LifecycleListener;
 import com.google.gerrit.lifecycle.LifecycleModule;
+import com.google.gson.JsonParser;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.Singleton;
 import java.io.IOException;
 import org.apache.http.HttpHost;
+import org.apache.http.HttpStatus;
+import org.apache.http.StatusLine;
 import org.apache.http.auth.AuthScope;
 import org.apache.http.auth.UsernamePasswordCredentials;
 import org.apache.http.client.CredentialsProvider;
 import org.apache.http.impl.client.BasicCredentialsProvider;
 import org.apache.http.impl.nio.client.HttpAsyncClientBuilder;
+import org.elasticsearch.client.Response;
 import org.elasticsearch.client.RestClient;
 import org.elasticsearch.client.RestClientBuilder;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 @Singleton
 class ElasticRestClientProvider implements Provider<RestClient>, LifecycleListener {
+  private static final Logger log = LoggerFactory.getLogger(ElasticRestClientProvider.class);
 
   private final HttpHost[] hosts;
   private final String username;
@@ -60,6 +67,8 @@
       synchronized (this) {
         if (client == null) {
           client = build();
+          String version = getVersion();
+          log.info("Connected to Elasticsearch version {}", version);
         }
       }
     }
@@ -80,6 +89,38 @@
     }
   }
 
+  public static class FailedToGetVersion extends ElasticException {
+    private static final long serialVersionUID = 1L;
+    private static final String MESSAGE = "Failed to get Elasticsearch version";
+
+    FailedToGetVersion(StatusLine status) {
+      super(String.format("%s: %d %s", MESSAGE, status.getStatusCode(), status.getReasonPhrase()));
+    }
+
+    FailedToGetVersion(Throwable cause) {
+      super(MESSAGE, cause);
+    }
+  }
+
+  private String getVersion() throws ElasticException {
+    try {
+      Response response = client.performRequest("GET", "");
+      StatusLine statusLine = response.getStatusLine();
+      if (statusLine.getStatusCode() != HttpStatus.SC_OK) {
+        throw new FailedToGetVersion(statusLine);
+      }
+      return new JsonParser()
+          .parse(AbstractElasticIndex.getContent(response))
+          .getAsJsonObject()
+          .get("version")
+          .getAsJsonObject()
+          .get("number")
+          .getAsString();
+    } catch (IOException e) {
+      throw new FailedToGetVersion(e);
+    }
+  }
+
   private RestClient build() {
     RestClientBuilder builder = RestClient.builder(hosts);
     setConfiguredCredentialsIfAny(builder);