Added clickable user names at the BecomeAnyAccountLoginServlet.

The first 5 (by accountId) user names are displayed as clickable
links. Clicking a user name logs in as this user.

This change speeds up switching between different users when using
the DEVELOPMENT_BECOME_ANY_ACCOUNT authentication type.

Change-Id: Ie9e5f2c4fe2809d03aa16bdf516e8fd04323c897
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java
index b09a50b..d80cbaf 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/become/BecomeAnyAccountLoginServlet.java
@@ -28,6 +28,7 @@
 import com.google.gerrit.server.account.AuthResult;
 import com.google.gerrit.server.config.CanonicalWebUrl;
 import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.client.ResultSet;
 import com.google.gwtorm.client.SchemaFactory;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
@@ -45,6 +46,7 @@
 
 import javax.annotation.Nullable;
 import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
 import javax.servlet.http.HttpServlet;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
@@ -58,42 +60,27 @@
   private final Provider<WebSession> webSession;
   private final Provider<String> urlProvider;
   private final AccountManager accountManager;
-  private final byte[] raw;
 
   @Inject
   BecomeAnyAccountLoginServlet(final Provider<WebSession> ws,
       final SchemaFactory<ReviewDb> sf,
       final @CanonicalWebUrl @Nullable Provider<String> up,
-      final AccountManager am, final ServletContext servletContext)
-      throws IOException {
+      final AccountManager am, final ServletContext servletContext) {
     webSession = ws;
     schema = sf;
     urlProvider = up;
     accountManager = am;
-
-    final String pageName = "BecomeAnyAccount.html";
-    final Document doc = HtmlDomUtil.parseFile(getClass(), pageName);
-    if (doc == null) {
-      throw new FileNotFoundException("No " + pageName + " in webapp");
-    }
-    if (!IS_DEV) {
-      final Element devmode = HtmlDomUtil.find(doc, "gerrit_gwtdevmode");
-      if (devmode != null) {
-        devmode.getParentNode().removeChild(devmode);
-      }
-    }
-    raw = HtmlDomUtil.toUTF8(doc);
   }
 
   @Override
   protected void doGet(final HttpServletRequest req,
-      final HttpServletResponse rsp) throws IOException {
+      final HttpServletResponse rsp) throws IOException, ServletException {
     doPost(req, rsp);
   }
 
   @Override
   protected void doPost(final HttpServletRequest req,
-      final HttpServletResponse rsp) throws IOException {
+      final HttpServletResponse rsp) throws IOException, ServletException {
     rsp.setHeader("Expires", "Fri, 01 Jan 1980 00:00:00 GMT");
     rsp.setHeader("Pragma", "no-cache");
     rsp.setHeader("Cache-Control", "no-cache, must-revalidate");
@@ -112,6 +99,12 @@
       res = byAccountId(rsp, req.getParameter("account_id"));
 
     } else {
+      byte[] raw;
+      try {
+        raw = prepareHtmlOutput();
+      } catch (OrmException e) {
+        throw new ServletException(e);
+      }
       rsp.setContentType("text/html");
       rsp.setCharacterEncoding(HtmlDomUtil.ENC);
       rsp.setContentLength(raw.length);
@@ -156,6 +149,48 @@
     }
   }
 
+  private byte[] prepareHtmlOutput() throws IOException, OrmException {
+    final String pageName = "BecomeAnyAccount.html";
+    final Document doc = HtmlDomUtil.parseFile(getClass(), pageName);
+    if (doc == null) {
+      throw new FileNotFoundException("No " + pageName + " in webapp");
+    }
+    if (!IS_DEV) {
+      final Element devmode = HtmlDomUtil.find(doc, "gerrit_gwtdevmode");
+      if (devmode != null) {
+        devmode.getParentNode().removeChild(devmode);
+      }
+    }
+
+    Element userlistElement = HtmlDomUtil.find(doc, "userlist");
+    ReviewDb db = schema.open();
+    try {
+      ResultSet<Account> accounts = db.accounts().firstNById(5);
+      for (Account a : accounts) {
+        String displayName;
+        if (a.getUserName() != null) {
+          displayName = a.getUserName();
+        } else if (a.getFullName() != null) {
+          displayName = a.getFullName();
+        } else if (a.getPreferredEmail() != null) {
+          displayName = a.getPreferredEmail();
+        } else {
+          displayName = a.getId().toString();
+        }
+
+        Element linkElement = doc.createElement("a");
+        linkElement.setAttribute("href", "?account_id=" + a.getId().toString());
+        linkElement.setTextContent(displayName);
+        userlistElement.appendChild(linkElement);
+        userlistElement.appendChild(doc.createElement("br"));
+      }
+    } finally {
+      db.close();
+    }
+
+    return HtmlDomUtil.toUTF8(doc);
+  }
+
   private AuthResult auth(final Account account) {
     if (account != null) {
       return new AuthResult(account.getId(), null, false);
diff --git a/gerrit-httpd/src/main/resources/com/google/gerrit/httpd/auth/become/BecomeAnyAccount.html b/gerrit-httpd/src/main/resources/com/google/gerrit/httpd/auth/become/BecomeAnyAccount.html
index 4795e91..c3c7503 100644
--- a/gerrit-httpd/src/main/resources/com/google/gerrit/httpd/auth/become/BecomeAnyAccount.html
+++ b/gerrit-httpd/src/main/resources/com/google/gerrit/httpd/auth/become/BecomeAnyAccount.html
@@ -62,6 +62,11 @@
           </form>
         </td>
       </tr>
+
+      <tr>
+        <th>Choose:</th>
+        <td id="userlist"/>
+      </tr>
     </table>
 
     <hr />
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountAccess.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountAccess.java
index 3c81152..d7a784a 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountAccess.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/AccountAccess.java
@@ -42,4 +42,7 @@
 
   @Query("LIMIT 1")
   ResultSet<Account> anyAccounts() throws OrmException;
+
+  @Query("ORDER BY accountId LIMIT ?")
+  ResultSet<Account> firstNById(int n) throws OrmException;
 }