Merge branch 'stable-2.14' into stable-2.15

* stable-2.14:
  Update jruby to 9.1.17 and asciidoctorj to v1.5.7
  Elasticsearch: Ensure request URI is always prefixed with "/"
  AbstractElasticIndex: Factor out more variants of {post,perform}Request
  rest-api-projects: Fix "unterminated listing block" warning
  config-gerrit: Fix "invalid reference: database.h2.cachesize" warning
  Bazel: Specify name for downloaded file to http_file starlark rule
  Set version to 2.14.14-SNAPSHOT

Change-Id: I8a3bf774120fadea7c52871047b99631e2a798de
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
index 6d988aa..dc8d187 100644
--- a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
+++ b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/AbstractElasticIndex.java
@@ -21,6 +21,7 @@
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.io.CharStreams;
+import com.google.gerrit.common.Nullable;
 import com.google.gerrit.elasticsearch.ElasticMapping.MappingProperties;
 import com.google.gerrit.elasticsearch.builders.SearchSourceBuilder;
 import com.google.gerrit.elasticsearch.bulk.DeleteRequest;
@@ -135,7 +136,7 @@
   @Override
   public void delete(K id) throws IOException {
     String uri = getURI(type, BULK);
-    Response response = postRequest(getDeleteActions(id), uri, getRefreshParam());
+    Response response = postRequest(uri, getDeleteActions(id), getRefreshParam());
     int statusCode = response.getStatusLine().getStatusCode();
     if (statusCode != HttpStatus.SC_OK) {
       throw new IOException(
@@ -147,10 +148,10 @@
   public void deleteAll() throws IOException {
     // Delete the index, if it exists.
     String endpoint = indexName + client.adapter().indicesExistParam();
-    Response response = client.get().performRequest(new Request("HEAD", endpoint));
+    Response response = performRequest("HEAD", endpoint);
     int statusCode = response.getStatusLine().getStatusCode();
     if (statusCode == HttpStatus.SC_OK) {
-      response = client.get().performRequest(new Request("DELETE", indexName));
+      response = performRequest("DELETE", indexName);
       statusCode = response.getStatusLine().getStatusCode();
       if (statusCode != HttpStatus.SC_OK) {
         throw new IOException(
@@ -160,7 +161,7 @@
 
     // Recreate the index.
     String indexCreationFields = concatJsonString(getSettings(), getMappings());
-    response = performRequest("PUT", indexCreationFields, indexName, Collections.emptyMap());
+    response = performRequest("PUT", indexName, indexCreationFields);
     statusCode = response.getStatusLine().getStatusCode();
     if (statusCode != HttpStatus.SC_OK) {
       String error = String.format("Failed to create index %s: %s", indexName, statusCode);
@@ -228,20 +229,36 @@
     return encodedIndexName + "/" + encodedType + "/" + request;
   }
 
-  protected Response postRequest(Object payload, String uri, Map<String, String> params)
+  protected Response postRequest(String uri, Object payload) throws IOException {
+    return performRequest("POST", uri, payload);
+  }
+
+  protected Response postRequest(String uri, Object payload, Map<String, String> params)
       throws IOException {
-    return performRequest("POST", payload, uri, params);
+    return performRequest("POST", uri, payload, params);
   }
 
   private String concatJsonString(String target, String addition) {
     return target.substring(0, target.length() - 1) + "," + addition.substring(1);
   }
 
+  private Response performRequest(String method, String uri) throws IOException {
+    return performRequest(method, uri, null);
+  }
+
+  private Response performRequest(String method, String uri, @Nullable Object payload)
+      throws IOException {
+    return performRequest(method, uri, payload, Collections.emptyMap());
+  }
+
   private Response performRequest(
-      String method, Object payload, String uri, Map<String, String> params) throws IOException {
-    Request request = new Request(method, uri);
-    String payloadStr = payload instanceof String ? (String) payload : payload.toString();
-    request.setEntity(new NStringEntity(payloadStr, ContentType.APPLICATION_JSON));
+      String method, String uri, @Nullable Object payload, Map<String, String> params)
+      throws IOException {
+    Request request = new Request(method, uri.startsWith("/") ? uri : "/" + uri);
+    if (payload != null) {
+      String payloadStr = payload instanceof String ? (String) payload : payload.toString();
+      request.setEntity(new NStringEntity(payloadStr, ContentType.APPLICATION_JSON));
+    }
     for (Map.Entry<String, String> entry : params.entrySet()) {
       request.addParameter(entry.getKey(), entry.getValue());
     }
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticAccountIndex.java b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticAccountIndex.java
index 729cfe9..722e6d8 100644
--- a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticAccountIndex.java
+++ b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticAccountIndex.java
@@ -93,7 +93,7 @@
             .add(new UpdateRequest<>(schema, as));
 
     String uri = getURI(type, BULK);
-    Response response = postRequest(bulk, uri, getRefreshParam());
+    Response response = postRequest(uri, bulk, getRefreshParam());
     int statusCode = response.getStatusLine().getStatusCode();
     if (statusCode != HttpStatus.SC_OK) {
       throw new IOException(
@@ -152,7 +152,7 @@
       try {
         List<AccountState> results = Collections.emptyList();
         String uri = getURI(type, SEARCH);
-        Response response = postRequest(search, uri, Collections.emptyMap());
+        Response response = postRequest(uri, search);
         StatusLine statusLine = response.getStatusLine();
         if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
           String content = getContent(response);
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
index adb2a0f..264822e 100644
--- a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
+++ b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticChangeIndex.java
@@ -146,7 +146,7 @@
     }
 
     String uri = getURI(type, BULK);
-    Response response = postRequest(bulk, uri, getRefreshParam());
+    Response response = postRequest(uri, bulk, getRefreshParam());
     int statusCode = response.getStatusLine().getStatusCode();
     if (statusCode != HttpStatus.SC_OK) {
       throw new IOException(
@@ -227,7 +227,7 @@
       try {
         List<ChangeData> results = Collections.emptyList();
         String uri = getURI(types);
-        Response response = postRequest(search, uri, Collections.emptyMap());
+        Response response = postRequest(uri, search);
         StatusLine statusLine = response.getStatusLine();
         if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
           String content = getContent(response);
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java
index 72f7cc2..79701e1 100644
--- a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java
+++ b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticGroupIndex.java
@@ -92,7 +92,7 @@
             .add(new UpdateRequest<>(schema, group));
 
     String uri = getURI(type, BULK);
-    Response response = postRequest(bulk, uri, getRefreshParam());
+    Response response = postRequest(uri, bulk, getRefreshParam());
     int statusCode = response.getStatusLine().getStatusCode();
     if (statusCode != HttpStatus.SC_OK) {
       throw new IOException(
@@ -151,7 +151,7 @@
       try {
         List<InternalGroup> results = Collections.emptyList();
         String uri = getURI(type, SEARCH);
-        Response response = postRequest(search, uri, Collections.emptyMap());
+        Response response = postRequest(uri, search);
         StatusLine statusLine = response.getStatusLine();
         if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
           String content = getContent(response);
diff --git a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticQueryAdapter.java b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticQueryAdapter.java
index 64f6252..b52499b 100644
--- a/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticQueryAdapter.java
+++ b/gerrit-elasticsearch/src/main/java/com/google/gerrit/elasticsearch/ElasticQueryAdapter.java
@@ -32,7 +32,7 @@
   ElasticQueryAdapter(ElasticVersion version) {
     this.ignoreUnmapped = version == ElasticVersion.V2_4;
     this.usePostV5Type = version.isV6();
-    this.versionDiscoveryUrl = version.isV6() ? "%s*" : "%s*/_aliases";
+    this.versionDiscoveryUrl = version.isV6() ? "/%s*" : "/%s*/_aliases";
 
     switch (version) {
       case V5_6:
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 0a32886..9c1cf02 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
@@ -107,7 +107,7 @@
 
   private ElasticVersion getVersion() throws ElasticException {
     try {
-      Response response = client.performRequest(new Request("GET", ""));
+      Response response = client.performRequest(new Request("GET", "/"));
       StatusLine statusLine = response.getStatusLine();
       if (statusLine.getStatusCode() != HttpStatus.SC_OK) {
         throw new FailedToGetVersion(statusLine);