Merge branch 'stable-2.14' into stable-2.15

* stable-2.14:
  Upgrade bazlets to latest stable-2.14 to build with 2.14.21 API

Change-Id: I29312ca62064128b0d2b5f2dc97e7649bf35a542
diff --git a/WORKSPACE b/WORKSPACE
index 93544cf..cf972b5 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -3,7 +3,7 @@
 load("//:bazlets.bzl", "load_bazlets")
 
 load_bazlets(
-    commit = "78c35a7eb33ee5ea0980923e246c7dba37347193",
+    commit = "f53f51fb660552d0581aa0ba52c3836ed63d56a3",
     #local_path = "/home/<user>/projects/bazlets",
 )
 
diff --git a/src/main/java/com/googlesource/gerrit/plugins/readonly/ReadOnly.java b/src/main/java/com/googlesource/gerrit/plugins/readonly/ReadOnly.java
index f84101c..f0ffbbd 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/readonly/ReadOnly.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/readonly/ReadOnly.java
@@ -17,6 +17,7 @@
 import static javax.servlet.http.HttpServletResponse.SC_SERVICE_UNAVAILABLE;
 
 import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Sets;
 import com.google.gerrit.extensions.annotations.PluginName;
 import com.google.gerrit.httpd.AllRequestFilter;
 import com.google.gerrit.server.events.CommitReceivedEvent;
@@ -26,6 +27,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 import java.io.IOException;
+import java.util.HashSet;
 import java.util.List;
 import javax.servlet.FilterChain;
 import javax.servlet.ServletException;
@@ -42,13 +44,15 @@
 
   private final ReadOnlyState state;
   private final ReadOnlyConfig config;
-  private final String endpoint;
+  private final HashSet<String> endpoints;
 
   @Inject
   ReadOnly(ReadOnlyState state, ReadOnlyConfig config, @PluginName String pluginName) {
     this.state = state;
     this.config = config;
-    this.endpoint = String.format("/config/server/%s~readonly", pluginName);
+    this.endpoints =
+        Sets.newHashSet(
+            String.format("/config/server/%s~readonly", pluginName), "/config/server/readonly");
   }
 
   @Override
@@ -76,12 +80,16 @@
   private boolean shouldBlock(HttpServletRequest request) {
     String method = request.getMethod();
     String servletPath = request.getServletPath();
-    return !servletPath.endsWith(endpoint)
-        && (("POST".equals(method)
-                && !servletPath.endsWith(GIT_UPLOAD_PACK_PROTOCOL)
-                && !servletPath.equals(LOGIN_PREFIX)
-                && !servletPath.contains(LOGIN_INFIX))
-            || "PUT".equals(method)
-            || "DELETE".equals(method));
+    for (String endpoint : endpoints) {
+      if (servletPath.endsWith(endpoint)) {
+        return false;
+      }
+    }
+    return ("POST".equals(method)
+            && !servletPath.endsWith(GIT_UPLOAD_PACK_PROTOCOL)
+            && !servletPath.equals(LOGIN_PREFIX)
+            && !servletPath.contains(LOGIN_INFIX))
+        || "PUT".equals(method)
+        || "DELETE".equals(method);
   }
 }
diff --git a/src/main/java/com/googlesource/gerrit/plugins/readonly/ReadOnlyEndpoint.java b/src/main/java/com/googlesource/gerrit/plugins/readonly/ReadOnlyEndpoint.java
index caabb57..2482cab 100644
--- a/src/main/java/com/googlesource/gerrit/plugins/readonly/ReadOnlyEndpoint.java
+++ b/src/main/java/com/googlesource/gerrit/plugins/readonly/ReadOnlyEndpoint.java
@@ -58,7 +58,7 @@
     @Override
     public Response<String> apply(ConfigResource resource, Input input) throws IOException {
       state.setReadOnly(true);
-      return Response.ok("");
+      return Response.ok("on");
     }
   }
 
@@ -75,7 +75,7 @@
     @Override
     public Response<String> apply(ConfigResource resource, Input input) throws IOException {
       state.setReadOnly(false);
-      return Response.ok("");
+      return Response.ok("off");
     }
   }
 }
diff --git a/src/main/resources/Documentation/rest-api-config.md b/src/main/resources/Documentation/rest-api-config.md
new file mode 100644
index 0000000..b4cb0c3
--- /dev/null
+++ b/src/main/resources/Documentation/rest-api-config.md
@@ -0,0 +1,87 @@
+@PLUGIN@ - /config/ REST API
+==============================
+
+This page describes the REST endpoints that are added by the @PLUGIN@
+plugin.
+
+Please also take note of the general information on the
+[REST API](../../../Documentation/rest-api.html).
+
+<a id="config-endpoints" />
+Readonly Endpoints
+------------------------------------------
+
+<a id="get-readonly-status" />
+### Get Readonly Status
+_GET /config/server/@PLUGIN@~readonly_
+
+Get the Readonly status.
+
+#### Request
+
+```
+  GET /config/server/@PLUGIN@~readonly HTTP/1.0
+```
+
+As response a string is returned with the Readonly status, either `on` or `off`.
+
+#### Response
+
+```
+  HTTP/1.1 200 OK
+  Content-Disposition: attachment
+  Content-Type: application/json;charset=UTF-8
+
+  )]}'
+  "on"
+```
+
+<a id="set-readonly" />
+### Set Readonly Status
+_PUT /config/server/@PLUGIN@~readonly_
+
+Set the system in Readonly status.
+
+#### Request
+
+```
+  PUT /config/server/@PLUGIN@~readonly HTTP/1.0
+```
+
+As response a string is returned with the Readonly status, either `on` or `off`.
+
+#### Response
+
+```
+  HTTP/1.1 200 OK
+  Content-Disposition: attachment
+  Content-Type: application/json;charset=UTF-8
+
+  )]}'
+  "on"
+```
+
+<a id="delete-readonly" />
+### Remove Readonly Status
+_DELETE /config/server/@PLUGIN@~readonly_
+
+Set the system in Read-Write status.
+
+#### Request
+
+```
+  DELETE /config/server/@PLUGIN@~readonly HTTP/1.0
+```
+
+As response a string is returned with the Readonly status, either `on` or `off`.
+
+#### Response
+
+```
+  HTTP/1.1 200 OK
+  Content-Disposition: attachment
+  Content-Type: application/json;charset=UTF-8
+
+  )]}'
+  "off"
+```
diff --git a/src/test/java/com/googlesource/gerrit/plugins/readonly/ReadOnlyByHttpIT.java b/src/test/java/com/googlesource/gerrit/plugins/readonly/ReadOnlyByHttpIT.java
index 43f241c..b078dae 100644
--- a/src/test/java/com/googlesource/gerrit/plugins/readonly/ReadOnlyByHttpIT.java
+++ b/src/test/java/com/googlesource/gerrit/plugins/readonly/ReadOnlyByHttpIT.java
@@ -17,18 +17,45 @@
 import static com.google.common.truth.Truth.assertThat;
 
 import com.google.gerrit.acceptance.RestResponse;
+import com.google.gerrit.server.config.GerritServerConfig;
+import com.google.gerrit.testutil.ConfigSuite;
+import com.google.inject.Inject;
+import org.eclipse.jgit.lib.Config;
 
 public class ReadOnlyByHttpIT extends AbstractReadOnlyTest {
+  @ConfigSuite.Default
+  public static Config withPluginNamePrefix() {
+    Config cfg = new Config();
+    cfg.setString("readonly", "test", "endpoint", "readonly~readonly");
+    return cfg;
+  }
+
+  @ConfigSuite.Config
+  public static Config withoutPluginNamePrefix() {
+    Config cfg = new Config();
+    cfg.setString("readonly", "test", "endpoint", "readonly");
+    return cfg;
+  }
+
+  @Inject @GerritServerConfig private Config config;
+
   @Override
   protected void setReadOnly(boolean readOnly) throws Exception {
-    if (readOnly) {
-      adminRestSession.put("/config/server/readonly~readonly").assertOK();
-    } else {
-      adminRestSession.delete("/config/server/readonly~readonly").assertOK();
-    }
-    RestResponse response = adminRestSession.get("/config/server/readonly~readonly");
-    response.assertOK();
+    String endpoint =
+        String.format("/config/server/%s", config.getString("readonly", "test", "endpoint"));
     String expectedStatus = readOnly ? "on" : "off";
+    RestResponse response;
+    if (readOnly) {
+      response = adminRestSession.put(endpoint);
+      response.assertOK();
+      assertThat(response.getEntityContent()).contains(expectedStatus);
+    } else {
+      response = adminRestSession.delete(endpoint);
+      response.assertOK();
+      assertThat(response.getEntityContent()).contains(expectedStatus);
+    }
+    response = adminRestSession.get(endpoint);
+    response.assertOK();
     assertThat(response.getEntityContent()).contains(expectedStatus);
   }
 }