Merge "For the 'conflicts' operator return only changes that actually conflict"
diff --git a/Documentation/cmd-gc.txt b/Documentation/cmd-gc.txt
index 50710e2..3066ca0 100644
--- a/Documentation/cmd-gc.txt
+++ b/Documentation/cmd-gc.txt
@@ -10,6 +10,7 @@
 [verse]
 'ssh' -p <port> <host> 'gerrit gc'
   [--all]
+  [--show-progress]
   <NAME> ...
 
 DESCRIPTION
@@ -46,6 +47,9 @@
 	If specified the Git garbage collection is run for all projects
 	sequentially.
 
+--show-progress::
+	If specified progress information is shown.
+
 EXAMPLES
 --------
 
diff --git a/Documentation/js-api.txt b/Documentation/js-api.txt
index 0e470e7..7411026 100644
--- a/Documentation/js-api.txt
+++ b/Documentation/js-api.txt
@@ -425,6 +425,13 @@
   comes with an onkeypress handler installed to play nicely with
   Gerrit's keyboard binding system.
 
+* `select(a,i)`: a new `<select>` element containing one `<option>`
+  element for each entry in the provided array `a`.  The option with
+  the index `i` will be pre-selected in the drop-down-list.
+
+* `selected(s)`: returns the text of the `<option>` element that is
+  currently selected in the provided `<select>` element `s`.
+
 * `span(...)`: a new `<span>` wrapping the (optional) arguments.
 
 * `msg(label)`: a new label.
diff --git a/Documentation/rest-api-accounts.txt b/Documentation/rest-api-accounts.txt
index 52c6ac9..f72c154 100644
--- a/Documentation/rest-api-accounts.txt
+++ b/Documentation/rest-api-accounts.txt
@@ -924,6 +924,7 @@
   }
 ----
 
+[[get-starred-changes]]
 Get Starred Changes
 ~~~~~~~~~~~~~~~~~~~
 [verse]
@@ -967,6 +968,7 @@
   ]
 ----
 
+[[star-change]]
 Star Change
 ~~~~~~~~~~~
 [verse]
@@ -986,6 +988,7 @@
   HTTP/1.1 204 No Content
 ----
 
+[[unstar-change]]
 Unstar Change
 ~~~~~~~~~~~~~
 [verse]
diff --git a/Documentation/rest-api-projects.txt b/Documentation/rest-api-projects.txt
index 1ac232a..c2e937a 100644
--- a/Documentation/rest-api-projects.txt
+++ b/Documentation/rest-api-projects.txt
@@ -552,9 +552,17 @@
 
 Run the Git garbage collection for the repository of a project.
 
+Options for the Git garbage collection can be specified in the
+request body as a link:#gc-input[GCInput] entity.
+
 .Request
 ----
   POST /projects/plugins%2Freplication/gc HTTP/1.0
+  Content-Type: application/json;charset=UTF-8
+
+  {
+    "show_progress": true
+  }
 ----
 
 The response is the streamed output of the garbage collection.
@@ -1317,6 +1325,19 @@
 Tokens such as `${project}` are not resolved.
 |===========================
 
+[[gc-input]]
+GCInput
+~~~~~~~
+The `GCInput` entity contains information to run the Git garbage
+collection.
+
+[options="header",width="50%",cols="1,^2,4"]
+|=============================
+|Field Name      ||Description
+|`show_progress` |`false` if not set|
+Whether progress information should be shown.
+|=============================
+
 [[head-input]]
 HeadInput
 ~~~~~~~~~
diff --git a/ReleaseNotes/ReleaseNotes-2.8.txt b/ReleaseNotes/ReleaseNotes-2.8.txt
index 27ed297..d183cca 100644
--- a/ReleaseNotes/ReleaseNotes-2.8.txt
+++ b/ReleaseNotes/ReleaseNotes-2.8.txt
@@ -278,6 +278,15 @@
 * link:https://gerrit-documentation.storage.googleapis.com/Documentation/2.8/rest-api-accounts.html#get-username[
 Get account username]
 
+* link:https://gerrit-documentation.storage.googleapis.com/Documentation/2.8/rest-api-accounts.html#get-starred-changes[
+Get starred changes]
+
+* link:https://gerrit-documentation.storage.googleapis.com/Documentation/2.8/rest-api-accounts.html#star-change[
+Star change]
+
+* link:https://gerrit-documentation.storage.googleapis.com/Documentation/2.8/rest-api-accounts.html#unstar-change[
+Unstar change]
+
 Changes
 ^^^^^^^
 
@@ -741,5 +750,7 @@
 * Update guava to 15.0
 * Update H2 to 1.3.173
 * Update bouncycastle to 1.44
+* Update Apache Mina to 2.0.7
+* Update Apache SSHD to 0.9.0.201311081
 * asciidoctor 0.1.4 is now required to build the documentation
 * jsr305 library was removed
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/ReviewInput.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/ReviewInput.java
index 969c23d..5f106fc 100644
--- a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/ReviewInput.java
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/api/changes/ReviewInput.java
@@ -60,15 +60,15 @@
   public String onBehalfOf;
 
   public static enum DraftHandling {
-    DELETE, PUBLISH, KEEP;
+    DELETE, PUBLISH, KEEP
   }
 
   public static enum NotifyHandling {
-    NONE, OWNER, OWNER_REVIEWERS, ALL;
+    NONE, OWNER, OWNER_REVIEWERS, ALL
   }
 
   public static enum Side {
-    PARENT, REVISION;
+    PARENT, REVISION
   }
 
   public static class Comment {
diff --git a/gerrit-gwtui/BUCK b/gerrit-gwtui/BUCK
index 1ae823e..0c873ee 100644
--- a/gerrit-gwtui/BUCK
+++ b/gerrit-gwtui/BUCK
@@ -1,4 +1,5 @@
 include_defs('//gerrit-gwtui/gwt.defs')
+include_defs('//tools/gwt-constants.defs')
 
 genrule(
   name = 'ui_optdbg',
@@ -25,13 +26,7 @@
 gwt_application(
   name = 'ui_opt',
   module_target = MODULE,
-  compiler_opts = [
-    '-strict',
-    '-style', 'OBF',
-    '-optimize', '9',
-    '-XdisableClassMetadata',
-    '-XdisableCastChecking',
-  ],
+  compiler_opts = GWT_COMPILER_OPTS,
   deps = APP_DEPS,
 )
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ActionContext.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ActionContext.java
index 7b00821..f22fa3f 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ActionContext.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ActionContext.java
@@ -93,6 +93,21 @@
         e.onkeypress = stopPropagation;
         return e;
       },
+      select: function(a,s) {
+        var e = doc.createElement('select');
+        for (var i = 0; i < a.length; i++) {
+          var o = doc.createElement('option');
+          if (i==s) {
+            o.setAttributeNode(doc.createAttribute("selected"));
+          }
+          o.appendChild(doc.createTextNode(a[i]));
+          e.appendChild(o);
+        }
+        return e;
+      },
+      selected: function(e) {
+        return e.options[e.selectedIndex].text;
+      },
 
       popup: function(e){this._p=@com.google.gerrit.client.api.PopupHelper::popup(Lcom/google/gerrit/client/api/ActionContext;Lcom/google/gwt/dom/client/Element;)(this,e)},
       hide: function() {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/DefaultActions.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/DefaultActions.java
index fcd6056..53a3784 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/DefaultActions.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/DefaultActions.java
@@ -22,6 +22,7 @@
 import com.google.gerrit.client.rpc.RestApi;
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.Project;
 import com.google.gwt.core.client.JavaScriptObject;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -44,7 +45,8 @@
     invoke(action, api, cb);
   }
 
-  static void invokeProjectAction(ActionInfo action, RestApi api) {
+  static void invokeProjectAction(final Project.NameKey project,
+      ActionInfo action, RestApi api) {
     AsyncCallback<JavaScriptObject> cb = new GerritCallback<JavaScriptObject>() {
       @Override
       public void onSuccess(JavaScriptObject msg) {
@@ -54,7 +56,7 @@
             Window.alert(str.asString());
           }
         }
-        Gerrit.display(PageLinks.ADMIN_PROJECTS);
+        Gerrit.display(PageLinks.toProject(project));
       }
     };
     invoke(action, api, cb);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ProjectGlue.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ProjectGlue.java
index b95f4e0..bce691c 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ProjectGlue.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/api/ProjectGlue.java
@@ -35,7 +35,7 @@
       c.button(button);
       ApiGlue.invoke(f, c);
     } else {
-      DefaultActions.invokeProjectAction(action, api);
+      DefaultActions.invokeProjectAction(project, action, api);
     }
   }
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SidePanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SidePanel.java
index b0431e9..52bb003 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SidePanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/SidePanel.java
@@ -114,7 +114,7 @@
     Label gutter = wrapper.gutter;
     final double height = cm.heightAtLine(line, "local");
     final double scrollbarHeight = cmB.getScrollbarV().getClientHeight();
-    double top = height / (double) cmB.getSizer().getClientHeight() *
+    double top = height / cmB.getSizer().getClientHeight() *
         scrollbarHeight +
         cmB.getScrollbarV().getAbsoluteTop();
     if (top == 0) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RestApi.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RestApi.java
index eeb45d4..5ae3091 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RestApi.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/rpc/RestApi.java
@@ -124,29 +124,31 @@
         }
 
       } else if (200 <= status && status < 300) {
-        if (!isJsonBody(res)) {
+        T data;
+        if (isTextBody(res)) {
+          data = NativeString.wrap(res.getText()).cast();
+        } else if (isJsonBody(res)) {
+          try {
+            // javac generics bug
+            data = RestApi.<T>cast(parseJson(res));
+          } catch (JSONException e) {
+            if (!background) {
+              RpcStatus.INSTANCE.onRpcComplete();
+            }
+            cb.onFailure(new StatusCodeException(SC_BAD_RESPONSE,
+                "Invalid JSON: " + e.getMessage()));
+            return;
+          }
+        } else {
           if (!background) {
             RpcStatus.INSTANCE.onRpcComplete();
           }
           cb.onFailure(new StatusCodeException(SC_BAD_RESPONSE, "Expected "
-              + JSON_TYPE + "; received Content-Type: "
+              + JSON_TYPE + " or " + TEXT_TYPE + "; received Content-Type: "
               + res.getHeader("Content-Type")));
           return;
         }
 
-        T data;
-        try {
-          // javac generics bug
-          data = RestApi.<T>cast(parseJson(res));
-        } catch (JSONException e) {
-          if (!background) {
-            RpcStatus.INSTANCE.onRpcComplete();
-          }
-          cb.onFailure(new StatusCodeException(SC_BAD_RESPONSE,
-              "Invalid JSON: " + e.getMessage()));
-          return;
-        }
-
         cb.onSuccess(data);
         if (!background) {
           RpcStatus.INSTANCE.onRpcComplete();
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java
index 68e0f6a..3cfd1bb 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java
@@ -56,7 +56,7 @@
   @Option(name = "--list-plugins", usage = "List available plugins")
   private boolean listPlugins;
 
-  @Option(name = "--install-plugin", usage = "Install given plugin without asking", multiValued = true)
+  @Option(name = "--install-plugin", usage = "Install given plugin without asking")
   private List<String> installPlugins;
 
   @Inject
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/PrologShell.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/PrologShell.java
index 803b702..4c66f0b 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/PrologShell.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/PrologShell.java
@@ -32,7 +32,7 @@
 import java.util.List;
 
 public class PrologShell extends AbstractProgram {
-  @Option(name = "-s", multiValued = true, metaVar = "FILE.pl", usage = "file to load")
+  @Option(name = "-s", metaVar = "FILE.pl", usage = "file to load")
   private List<String> fileName = new ArrayList<String>();
 
   @Override
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/HiddenErrorHandler.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/HiddenErrorHandler.java
index 9fd8929..5ca53df 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/HiddenErrorHandler.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/HiddenErrorHandler.java
@@ -18,9 +18,9 @@
 import com.google.common.base.Strings;
 import com.google.gwtexpui.server.CacheHeaders;
 
-import org.eclipse.jetty.http.HttpHeaders;
+import org.eclipse.jetty.http.HttpHeader;
 import org.eclipse.jetty.http.HttpStatus;
-import org.eclipse.jetty.server.AbstractHttpConnection;
+import org.eclipse.jetty.server.HttpConnection;
 import org.eclipse.jetty.server.Request;
 import org.eclipse.jetty.server.handler.ErrorHandler;
 import org.slf4j.Logger;
@@ -37,8 +37,8 @@
 
   public void handle(String target, Request baseRequest,
       HttpServletRequest req, HttpServletResponse res) throws IOException {
-    AbstractHttpConnection conn = AbstractHttpConnection.getCurrentConnection();
-    conn.getRequest().setHandled(true);
+    HttpConnection conn = HttpConnection.getCurrentConnection();
+    baseRequest.setHandled(true);
     try {
       log(req);
     } finally {
@@ -46,10 +46,11 @@
     }
   }
 
-  private void reply(AbstractHttpConnection conn, HttpServletResponse res)
+  private void reply(HttpConnection conn, HttpServletResponse res)
       throws IOException {
     byte[] msg = message(conn);
-    res.setHeader(HttpHeaders.CONTENT_TYPE, "text/plain; charset=ISO-8859-1");
+    res.setHeader(HttpHeader.CONTENT_TYPE.asString(),
+        "text/plain; charset=ISO-8859-1");
     res.setContentLength(msg.length);
     try {
       CacheHeaders.setNotCacheable(res);
@@ -63,10 +64,11 @@
     }
   }
 
-  private static byte[] message(AbstractHttpConnection conn) {
-    String msg = conn.getResponse().getReason();
+  private static byte[] message(HttpConnection conn) {
+    String msg = conn.getHttpChannel().getResponse().getReason();
     if (msg == null) {
-      msg = HttpStatus.getMessage(conn.getResponse().getStatus());
+      msg = HttpStatus.getMessage(conn.getHttpChannel()
+          .getResponse().getStatus());
     }
     return msg.getBytes(Charsets.ISO_8859_1);
   }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
index e1d1281b..615e11e 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/JettyServer.java
@@ -32,21 +32,24 @@
 import com.google.inject.servlet.GuiceFilter;
 import com.google.inject.servlet.GuiceServletContextListener;
 
-import org.eclipse.jetty.io.EndPoint;
 import org.eclipse.jetty.server.Connector;
+import org.eclipse.jetty.server.ForwardedRequestCustomizer;
 import org.eclipse.jetty.server.Handler;
-import org.eclipse.jetty.server.Request;
+import org.eclipse.jetty.server.HttpConfiguration;
+import org.eclipse.jetty.server.HttpConnectionFactory;
+import org.eclipse.jetty.server.SecureRequestCustomizer;
 import org.eclipse.jetty.server.Server;
+import org.eclipse.jetty.server.ServerConnector;
+import org.eclipse.jetty.server.SslConnectionFactory;
 import org.eclipse.jetty.server.handler.ContextHandler;
 import org.eclipse.jetty.server.handler.ContextHandlerCollection;
 import org.eclipse.jetty.server.handler.RequestLogHandler;
-import org.eclipse.jetty.server.nio.SelectChannelConnector;
 import org.eclipse.jetty.server.session.SessionHandler;
-import org.eclipse.jetty.server.ssl.SslSelectChannelConnector;
 import org.eclipse.jetty.servlet.DefaultServlet;
 import org.eclipse.jetty.servlet.FilterHolder;
 import org.eclipse.jetty.servlet.ServletContextHandler;
 import org.eclipse.jetty.servlet.ServletHolder;
+import org.eclipse.jetty.util.BlockingArrayQueue;
 import org.eclipse.jetty.util.resource.Resource;
 import org.eclipse.jetty.util.ssl.SslContextFactory;
 import org.eclipse.jetty.util.thread.QueuedThreadPool;
@@ -131,9 +134,8 @@
       throws MalformedURLException, IOException {
     this.site = site;
 
-    httpd = new Server();
-    httpd.setConnectors(listen(cfg));
-    httpd.setThreadPool(threadPool(cfg));
+    httpd = new Server(threadPool(cfg));
+    httpd.setConnectors(listen(httpd, cfg));
 
     Handler app = makeContext(env, cfg);
     if (cfg.getBoolean("httpd", "requestLog", !reverseProxy)) {
@@ -142,15 +144,12 @@
       handler.setHandler(app);
       app = handler;
     }
-    httpd.setHandler(app);
 
+    httpd.setHandler(app);
     httpd.setStopAtShutdown(false);
-    httpd.setSendDateHeader(true);
-    httpd.setSendServerVersion(false);
-    httpd.setGracefulShutdown((int) MILLISECONDS.convert(1, SECONDS));
   }
 
-  private Connector[] listen(final Config cfg) {
+  private Connector[] listen(Server server, Config cfg) {
     // OpenID and certain web-based single-sign-on products can cause
     // some very long headers, especially in the Referer header. We
     // need to use a larger default header size to ensure we have
@@ -168,7 +167,8 @@
     for (int idx = 0; idx < listenUrls.length; idx++) {
       final URI u = listenUrls[idx];
       final int defaultPort;
-      final SelectChannelConnector c;
+      final ServerConnector c;
+      HttpConfiguration config = defaultConfig(requestHeaderSize);
 
       if (AuthType.CLIENT_SSL_CERT_LDAP.equals(authType) && ! "https".equals(u.getScheme())) {
         throw new IllegalArgumentException("Protocol '" + u.getScheme()
@@ -179,7 +179,9 @@
 
       if ("http".equals(u.getScheme())) {
         defaultPort = 80;
-        c = new SelectChannelConnector();
+        c = new ServerConnector(server, null, null, null, 0, acceptors,
+            new HttpConnectionFactory(config));
+
       } else if ("https".equals(u.getScheme())) {
         SslContextFactory ssl = new SslContextFactory();
         final File keystore = getFile(cfg, "sslkeystore", "etc/keystore");
@@ -188,7 +190,7 @@
           password = "gerrit";
         }
         ssl.setKeyStorePath(keystore.getAbsolutePath());
-        ssl.setTrustStore(keystore.getAbsolutePath());
+        ssl.setTrustStorePath(keystore.getAbsolutePath());
         ssl.setKeyStorePassword(password);
         ssl.setTrustStorePassword(password);
 
@@ -203,24 +205,27 @@
         }
 
         defaultPort = 443;
-        c = new SslSelectChannelConnector(ssl);
+
+        config.addCustomizer(new SecureRequestCustomizer());
+        c = new ServerConnector(server,
+            null, null, null, 0, acceptors,
+            new SslConnectionFactory(ssl, "http/1.1"),
+            new HttpConnectionFactory(config));
 
       } else if ("proxy-http".equals(u.getScheme())) {
         defaultPort = 8080;
-        c = new SelectChannelConnector();
-        c.setForwarded(true);
+        config.addCustomizer(new ForwardedRequestCustomizer());
+        c = new ServerConnector(server,
+            null, null, null, 0, acceptors,
+            new HttpConnectionFactory(config));
 
       } else if ("proxy-https".equals(u.getScheme())) {
         defaultPort = 8080;
-        c = new SelectChannelConnector() {
-          @Override
-          public void customize(EndPoint endpoint, Request request)
-              throws IOException {
-            request.setScheme("https");
-            super.customize(endpoint, request);
-          }
-        };
-        c.setForwarded(true);
+        config.addCustomizer(new ForwardedRequestCustomizer());
+        config.addCustomizer(new SecureRequestCustomizer());
+        c = new ServerConnector(server,
+            null, null, null, 0, acceptors,
+            new HttpConnectionFactory(config));
 
       } else {
         throw new IllegalArgumentException("Protocol '" + u.getScheme() + "' "
@@ -249,16 +254,20 @@
         throw new IllegalArgumentException("Invalid httpd.listenurl " + u, e);
       }
 
-      c.setRequestHeaderSize(requestHeaderSize);
-      c.setAcceptors(acceptors);
       c.setReuseAddress(reuseAddress);
-      c.setStatsOn(false);
-
       connectors[idx] = c;
     }
     return connectors;
   }
 
+  private HttpConfiguration defaultConfig(int requestHeaderSize) {
+    HttpConfiguration config = new HttpConfiguration();
+    config.setRequestHeaderSize(requestHeaderSize);
+    config.setSendServerVersion(false);
+    config.setSendDateHeader(true);
+    return config;
+  }
+
   static boolean isReverseProxied(final URI[] listenUrls) {
     for (URI u : listenUrls) {
       if ("http".equals(u.getScheme()) || "https".equals(u.getScheme())) {
@@ -295,11 +304,20 @@
   }
 
   private ThreadPool threadPool(Config cfg) {
-    final QueuedThreadPool pool = new QueuedThreadPool();
+    int maxThreads = cfg.getInt("httpd", null, "maxthreads", 25);
+    int minThreads = cfg.getInt("httpd", null, "minthreads", 5);
+    int maxCapacity = cfg.getInt("httpd", null, "maxqueued", 50);
+    int idleTimeout = (int)MILLISECONDS.convert(60, SECONDS);
+    QueuedThreadPool pool = new QueuedThreadPool(
+        maxThreads,
+        minThreads,
+        idleTimeout,
+        new BlockingArrayQueue<Runnable>(
+            minThreads, // capacity,
+            minThreads, // growBy,
+            maxCapacity // maxCapacity
+    ));
     pool.setName("HTTP");
-    pool.setMinThreads(cfg.getInt("httpd", null, "minthreads", 5));
-    pool.setMaxThreads(cfg.getInt("httpd", null, "maxthreads", 25));
-    pool.setMaxQueued(cfg.getInt("httpd", null, "maxqueued", 50));
     return pool;
   }
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AddSshKey.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AddSshKey.java
index 2cff009..0b40c81 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AddSshKey.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AddSshKey.java
@@ -19,9 +19,7 @@
 import com.google.gerrit.common.errors.InvalidSshKeyException;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.BadRequestException;
-import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
 import com.google.gerrit.extensions.restapi.RawInput;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.reviewdb.client.AccountSshKey;
@@ -57,8 +55,7 @@
 
   @Override
   public Response<SshKeyInfo> apply(AccountResource rsrc, Input input)
-      throws AuthException, MethodNotAllowedException, BadRequestException,
-      ResourceConflictException, OrmException, IOException {
+      throws AuthException, BadRequestException, OrmException, IOException {
     if (self.get() != rsrc.getUser()
         && !self.get().getCapabilities().canAdministrateServer()) {
       throw new AuthException("not allowed to add SSH keys");
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/CreateAccount.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/CreateAccount.java
index 340746e..3b03c3a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/CreateAccount.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/CreateAccount.java
@@ -89,7 +89,7 @@
   }
 
   @Override
-  public Object apply(TopLevelResource rsrc, Input input)
+  public Response<AccountInfo> apply(TopLevelResource rsrc, Input input)
       throws BadRequestException, ResourceConflictException,
       UnprocessableEntityException, OrmException {
     if (input == null) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/CreateEmail.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/CreateEmail.java
index 4fda74c..9a5a864 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/CreateEmail.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/CreateEmail.java
@@ -78,8 +78,8 @@
   }
 
   @Override
-  public Object apply(AccountResource rsrc, Input input) throws AuthException,
-      BadRequestException, ResourceConflictException,
+  public Response<EmailInfo> apply(AccountResource rsrc, Input input)
+      throws AuthException, BadRequestException, ResourceConflictException,
       ResourceNotFoundException, OrmException, EmailException,
       MethodNotAllowedException {
     if (self.get() != rsrc.getUser()
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/DeleteActive.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/DeleteActive.java
index d44bc2c..4382655 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/DeleteActive.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/DeleteActive.java
@@ -43,7 +43,7 @@
   }
 
   @Override
-  public Object apply(AccountResource rsrc, Input input)
+  public Response<?> apply(AccountResource rsrc, Input input)
       throws ResourceNotFoundException, OrmException {
     Account a = dbProvider.get().accounts().get(rsrc.getUser().getAccountId());
     if (a == null) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/DeleteEmail.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/DeleteEmail.java
index 4b38b9f..b38c49b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/DeleteEmail.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/DeleteEmail.java
@@ -48,7 +48,7 @@
   }
 
   @Override
-  public Object apply(AccountResource.Email rsrc, Input input)
+  public Response<?> apply(AccountResource.Email rsrc, Input input)
       throws AuthException, ResourceNotFoundException,
       ResourceConflictException, MethodNotAllowedException, OrmException {
     if (self.get() != rsrc.getUser()
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/DeleteSshKey.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/DeleteSshKey.java
index cf60df1..bbba48a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/DeleteSshKey.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/DeleteSshKey.java
@@ -40,7 +40,7 @@
   }
 
   @Override
-  public Object apply(AccountResource.SshKey rsrc, Input input)
+  public Response<?> apply(AccountResource.SshKey rsrc, Input input)
       throws OrmException {
     dbProvider.get().accountSshKeys()
         .deleteKeys(Collections.singleton(rsrc.getSshKey().getKey()));
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GetCapabilities.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GetCapabilities.java
index 615d09e..03ba94f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GetCapabilities.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GetCapabilities.java
@@ -36,7 +36,6 @@
 import com.google.gerrit.extensions.config.CapabilityDefinition;
 import com.google.gerrit.extensions.registration.DynamicMap;
 import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.BinaryResult;
 import com.google.gerrit.extensions.restapi.RestReadView;
 import com.google.gerrit.server.CurrentUser;
@@ -59,7 +58,7 @@
   @Option(name = "--format", usage = "(deprecated) output format")
   private OutputFormat format;
 
-  @Option(name = "-q", metaVar = "CAP", multiValued = true, usage = "Capability to inspect")
+  @Option(name = "-q", metaVar = "CAP", usage = "Capability to inspect")
   void addQuery(String name) {
     if (query == null) {
       query = Sets.newHashSet();
@@ -79,8 +78,7 @@
   }
 
   @Override
-  public Object apply(AccountResource resource)
-      throws BadRequestException, Exception {
+  public Object apply(AccountResource resource) throws AuthException {
     if (self.get() != resource.getUser()
         && !self.get().getCapabilities().canAdministrateServer()) {
       throw new AuthException("restricted to administrator");
@@ -178,7 +176,7 @@
 
   static class CheckOne implements RestReadView<AccountResource.Capability> {
     @Override
-    public Object apply(Capability resource) {
+    public BinaryResult apply(Capability resource) {
       return BinaryResult.create("ok\n");
     }
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/GetHttpPassword.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/GetHttpPassword.java
index 8eaf4b3..7fc82f9 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/GetHttpPassword.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/GetHttpPassword.java
@@ -18,7 +18,6 @@
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.RestReadView;
 import com.google.gerrit.server.CurrentUser;
-import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
@@ -33,7 +32,7 @@
 
   @Override
   public String apply(AccountResource rsrc) throws AuthException,
-      ResourceNotFoundException, OrmException {
+      ResourceNotFoundException {
     if (self.get() != rsrc.getUser()
         && !self.get().getCapabilities().canAdministrateServer()) {
       throw new AuthException("not allowed to get http password");
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/PutActive.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/PutActive.java
index a860fda..f1b5151 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/PutActive.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/PutActive.java
@@ -43,7 +43,7 @@
   }
 
   @Override
-  public Object apply(AccountResource rsrc, Input input)
+  public Response<String> apply(AccountResource rsrc, Input input)
       throws ResourceNotFoundException, OrmException {
     Account a = dbProvider.get().accounts().get(rsrc.getUser().getAccountId());
     if (a == null) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/PutEmail.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/PutEmail.java
index b79d8dc4..ba12bbf 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/PutEmail.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/PutEmail.java
@@ -15,12 +15,13 @@
 package com.google.gerrit.server.account;
 
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.server.account.CreateEmail.Input;
 
 public class PutEmail implements RestModifyView<AccountResource.Email, Input> {
   @Override
-  public Object apply(AccountResource.Email rsrc, Input input)
+  public Response<?> apply(AccountResource.Email rsrc, Input input)
       throws ResourceConflictException {
     throw new ResourceConflictException("email exists");
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/StarredChanges.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/StarredChanges.java
index b560911..b8984ab 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/StarredChanges.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/StarredChanges.java
@@ -157,7 +157,7 @@
 
     @Override
     public Response<?> apply(AccountResource.StarredChange rsrc, EmptyInput in)
-        throws AuthException, OrmException {
+        throws AuthException {
       if (self.get() != rsrc.getUser()) {
         throw new AuthException("not allowed update starred changes");
       }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
index bbc147f..855b0c1 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/api/changes/ChangeApiImpl.java
@@ -28,7 +28,6 @@
 import com.google.gerrit.server.change.Restore;
 import com.google.gerrit.server.change.Revert;
 import com.google.gerrit.server.change.Revisions;
-import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
@@ -138,8 +137,6 @@
       throw new RestApiException("Cannot revert change", e);
     } catch (IOException e) {
       throw new RestApiException("Cannot revert change", e);
-    } catch (NoSuchChangeException e) {
-      throw new RestApiException("Cannot revert change", e);
     }
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Abandon.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Abandon.java
index 1218de8..de0438b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Abandon.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Abandon.java
@@ -19,7 +19,6 @@
 import com.google.gerrit.common.ChangeHooks;
 import com.google.gerrit.extensions.api.changes.AbandonInput;
 import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.extensions.webui.UiAction;
@@ -69,9 +68,9 @@
   }
 
   @Override
-  public Object apply(ChangeResource req, AbandonInput input)
-      throws BadRequestException, AuthException,
-      ResourceConflictException, OrmException, IOException {
+  public ChangeInfo apply(ChangeResource req, AbandonInput input)
+      throws AuthException, ResourceConflictException, OrmException,
+      IOException {
     ChangeControl control = req.getControl();
     IdentifiedUser caller = (IdentifiedUser) control.getCurrentUser();
     Change change = req.getChange();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPick.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPick.java
index 18f45bb..ce0d33e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPick.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPick.java
@@ -14,22 +14,29 @@
 
 package com.google.gerrit.server.change;
 
+import com.google.gerrit.common.errors.EmailException;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.extensions.webui.UiAction;
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.PatchSet;
 import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.change.ChangeJson.ChangeInfo;
 import com.google.gerrit.server.change.CherryPick.Input;
 import com.google.gerrit.server.git.MergeException;
 import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.InvalidChangeOperationException;
+import com.google.gerrit.server.project.NoSuchChangeException;
 import com.google.gerrit.server.project.RefControl;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
+import java.io.IOException;
+
 class CherryPick implements RestModifyView<RevisionResource, Input>,
     UiAction<RevisionResource> {
   private final Provider<ReviewDb> dbProvider;
@@ -51,9 +58,9 @@
   }
 
   @Override
-  public Object apply(RevisionResource revision, Input input)
+  public ChangeInfo apply(RevisionResource revision, Input input)
       throws AuthException, BadRequestException, ResourceConflictException,
-      Exception {
+      ResourceNotFoundException, OrmException, IOException, EmailException {
     final ChangeControl control = revision.getControl();
 
     if (input.message == null || input.message.trim().isEmpty()) {
@@ -89,6 +96,8 @@
       throw new BadRequestException(e.getMessage());
     } catch (MergeException  e) {
       throw new ResourceConflictException(e.getMessage());
+    } catch (NoSuchChangeException e) {
+      throw new ResourceNotFoundException(e.getMessage());
     }
   }
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateDraft.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateDraft.java
index 229e072..afd0b85 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateDraft.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/CreateDraft.java
@@ -16,9 +16,7 @@
 
 import com.google.common.base.Strings;
 import com.google.gerrit.common.changes.Side;
-import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.BadRequestException;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.extensions.restapi.Url;
@@ -44,7 +42,7 @@
 
   @Override
   public Response<CommentInfo> apply(RevisionResource rsrc, Input in)
-      throws AuthException, BadRequestException, ResourceConflictException, OrmException {
+      throws BadRequestException, OrmException {
     if (Strings.isNullOrEmpty(in.path)) {
       throw new BadRequestException("path must be non-empty");
     } else if (in.message == null || in.message.trim().isEmpty()) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraft.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraft.java
index 0d5898e..588c372 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraft.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraft.java
@@ -36,7 +36,8 @@
   }
 
   @Override
-  public Object apply(DraftResource rsrc, Input input) throws OrmException {
+  public Response<CommentInfo> apply(DraftResource rsrc, Input input)
+      throws OrmException {
     db.get().patchComments().delete(Collections.singleton(rsrc.getComment()));
     return Response.none();
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftChange.java
index 767d5ee..efdb9cb 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftChange.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftChange.java
@@ -58,7 +58,7 @@
   }
 
   @Override
-  public Object apply(ChangeResource rsrc, Input input)
+  public Response<?> apply(ChangeResource rsrc, Input input)
       throws ResourceConflictException, AuthException,
       ResourceNotFoundException, OrmException, IOException {
     if (rsrc.getChange().getStatus() != Status.DRAFT) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftPatchSet.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftPatchSet.java
index 3265c81..ce86721 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftPatchSet.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteDraftPatchSet.java
@@ -64,9 +64,9 @@
   }
 
   @Override
-  public Object apply(RevisionResource rsrc, Input input)
-      throws ResourceNotFoundException, AuthException, OrmException,
-      IOException, ResourceConflictException {
+  public Response<?> apply(RevisionResource rsrc, Input input)
+      throws AuthException, ResourceNotFoundException,
+      ResourceConflictException, OrmException, IOException {
     PatchSet patchSet = rsrc.getPatchSet();
     PatchSet.Id patchSetId = patchSet.getId();
     Change change = rsrc.getChange();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java
index c58fc6c..bc726aa 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/DeleteReviewer.java
@@ -50,7 +50,7 @@
   }
 
   @Override
-  public Object apply(ReviewerResource rsrc, Input input)
+  public Response<?> apply(ReviewerResource rsrc, Input input)
       throws AuthException, ResourceNotFoundException, OrmException,
       IOException {
     ChangeControl control = rsrc.getControl();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/EditMessage.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/EditMessage.java
index a634b7c..8bc7a0e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/EditMessage.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/EditMessage.java
@@ -78,8 +78,8 @@
 
   @Override
   public ChangeInfo apply(RevisionResource rsrc, Input input)
-      throws BadRequestException, ResourceConflictException, EmailException,
-      OrmException, ResourceNotFoundException, IOException {
+      throws BadRequestException, ResourceConflictException,
+      ResourceNotFoundException, EmailException, OrmException, IOException {
     if (Strings.isNullOrEmpty(input.message)) {
       throw new BadRequestException("message must be non-empty");
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Files.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Files.java
index 98e2ee9..b440ee0 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Files.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Files.java
@@ -117,13 +117,12 @@
     }
 
     @Override
-    public Object apply(RevisionResource resource)
-        throws ResourceNotFoundException, OrmException,
-        PatchListNotAvailableException, BadRequestException, AuthException {
+    public Response<?> apply(RevisionResource resource) throws AuthException,
+        BadRequestException, ResourceNotFoundException, OrmException {
       if (base != null && reviewed) {
         throw new BadRequestException("cannot combine base and reviewed");
       } else if (reviewed) {
-        return reviewed(resource);
+        return Response.ok(reviewed(resource));
       }
 
       PatchSet basePatchSet = null;
@@ -132,17 +131,21 @@
             resource.getChangeResource(), IdString.fromDecoded(base));
         basePatchSet = baseResource.getPatchSet();
       }
-      Response<Map<String, FileInfo>> r = Response.ok(fileInfoJson.toFileInfoMap(
-          resource.getChange(),
-          resource.getPatchSet(),
-          basePatchSet));
-      if (resource.isCacheable()) {
-        r.caching(CacheControl.PRIVATE(7, TimeUnit.DAYS));
+      try {
+        Response<Map<String, FileInfo>> r = Response.ok(fileInfoJson.toFileInfoMap(
+            resource.getChange(),
+            resource.getPatchSet(),
+            basePatchSet));
+        if (resource.isCacheable()) {
+          r.caching(CacheControl.PRIVATE(7, TimeUnit.DAYS));
+        }
+        return r;
+      } catch (PatchListNotAvailableException e) {
+        throw new ResourceNotFoundException(e.getMessage());
       }
-      return r;
     }
 
-    private Object reviewed(RevisionResource resource)
+    private List<String> reviewed(RevisionResource resource)
         throws AuthException, OrmException {
       CurrentUser user = self.get();
       if (!(user.isIdentifiedUser())) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetChange.java
index 7213a94..8b794f5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetChange.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetChange.java
@@ -18,6 +18,7 @@
 import com.google.gerrit.extensions.restapi.CacheControl;
 import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestReadView;
+import com.google.gerrit.server.change.ChangeJson.ChangeInfo;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 
@@ -28,7 +29,7 @@
 public class GetChange implements RestReadView<ChangeResource> {
   private final ChangeJson json;
 
-  @Option(name = "-o", multiValued = true, usage = "Output options")
+  @Option(name = "-o", usage = "Output options")
   void addOption(ListChangesOption o) {
     json.addOption(o);
   }
@@ -44,15 +45,15 @@
   }
 
   @Override
-  public Object apply(ChangeResource rsrc) throws OrmException {
+  public Response<ChangeInfo> apply(ChangeResource rsrc) throws OrmException {
     return cache(json.format(rsrc));
   }
 
-  Object apply(RevisionResource rsrc) throws OrmException {
+  Response<ChangeInfo> apply(RevisionResource rsrc) throws OrmException {
     return cache(json.format(rsrc));
   }
 
-  private Object cache(Object res) {
+  private Response<ChangeInfo> cache(ChangeInfo res) {
     return Response.ok(res)
         .caching(CacheControl.PRIVATE(0, TimeUnit.SECONDS).setMustRevalidate());
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetComment.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetComment.java
index 68b0435..3606eed 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetComment.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetComment.java
@@ -29,7 +29,7 @@
   }
 
   @Override
-  public Object apply(CommentResource rsrc) throws OrmException {
+  public CommentInfo apply(CommentResource rsrc) throws OrmException {
     AccountInfo.Loader accountLoader = accountLoaderFactory.create(true);
     CommentInfo ci = new CommentInfo(rsrc.getComment(), accountLoader);
     accountLoader.fill();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetCommit.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetCommit.java
index 7d29449..b17e406 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetCommit.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetCommit.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.server.change;
 
 import com.google.gerrit.extensions.restapi.CacheControl;
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestReadView;
 import com.google.gerrit.server.change.ChangeJson.CommitInfo;
@@ -34,11 +35,16 @@
 
   @Override
   public Response<CommitInfo> apply(RevisionResource resource)
-      throws OrmException, PatchSetInfoNotAvailableException {
-    Response<CommitInfo> r = Response.ok(json.toCommit(resource.getPatchSet()));
-    if (resource.isCacheable()) {
-      r.caching(CacheControl.PRIVATE(7, TimeUnit.DAYS));
+      throws ResourceNotFoundException, OrmException {
+    try {
+      Response<CommitInfo> r =
+          Response.ok(json.toCommit(resource.getPatchSet()));
+      if (resource.isCacheable()) {
+        r.caching(CacheControl.PRIVATE(7, TimeUnit.DAYS));
+      }
+      return r;
+    } catch (PatchSetInfoNotAvailableException e) {
+      throw new ResourceNotFoundException(e.getMessage());
     }
-    return r;
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDetail.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDetail.java
index 936edd6..520a09f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDetail.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDetail.java
@@ -15,7 +15,9 @@
 package com.google.gerrit.server.change;
 
 import com.google.gerrit.common.changes.ListChangesOption;
+import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestReadView;
+import com.google.gerrit.server.change.ChangeJson.ChangeInfo;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 
@@ -24,7 +26,7 @@
 public class GetDetail implements RestReadView<ChangeResource> {
   private final GetChange delegate;
 
-  @Option(name = "-o", multiValued = true, usage = "Output options")
+  @Option(name = "-o", usage = "Output options")
   void addOption(ListChangesOption o) {
     delegate.addOption(o);
   }
@@ -44,7 +46,7 @@
   }
 
   @Override
-  public Object apply(ChangeResource rsrc) throws OrmException {
+  public Response<ChangeInfo> apply(ChangeResource rsrc) throws OrmException {
     return delegate.apply(rsrc);
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDiff.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDiff.java
index 43504fa..04136bd 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDiff.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDiff.java
@@ -24,6 +24,7 @@
 import com.google.gerrit.common.data.PatchScript.FileMode;
 import com.google.gerrit.extensions.restapi.CacheControl;
 import com.google.gerrit.extensions.restapi.IdString;
+import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestReadView;
@@ -38,6 +39,7 @@
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
+
 import org.eclipse.jgit.diff.Edit;
 import org.eclipse.jgit.diff.ReplaceEdit;
 import org.kohsuke.args4j.CmdLineException;
@@ -76,8 +78,8 @@
   }
 
   @Override
-  public Object apply(FileResource resource)
-      throws OrmException, NoSuchChangeException, LargeObjectException, ResourceNotFoundException {
+  public Response<Result> apply(FileResource resource)
+      throws ResourceConflictException, ResourceNotFoundException, OrmException {
     PatchSet.Id basePatchSet = null;
     if (base != null) {
       RevisionResource baseResource = revisions.get().parse(
@@ -89,74 +91,80 @@
     prefs.setContext(context);
     prefs.setIntralineDifference(intraline);
 
-    PatchScript ps = patchScriptFactoryFactory.create(
-        resource.getRevision().getControl(),
-        resource.getPatchKey().getFileName(),
-        basePatchSet,
-        resource.getPatchKey().getParentKey(),
-        prefs)
-          .call();
+    try {
+      PatchScript ps = patchScriptFactoryFactory.create(
+          resource.getRevision().getControl(),
+          resource.getPatchKey().getFileName(),
+          basePatchSet,
+          resource.getPatchKey().getParentKey(),
+          prefs)
+            .call();
 
-    Content content = new Content(ps);
-    for (Edit edit : ps.getEdits()) {
-      if (edit.getType() == Edit.Type.EMPTY) {
-        continue;
+      Content content = new Content(ps);
+      for (Edit edit : ps.getEdits()) {
+        if (edit.getType() == Edit.Type.EMPTY) {
+          continue;
+        }
+        content.addCommon(edit.getBeginA());
+
+        checkState(content.nextA == edit.getBeginA(),
+            "nextA = %d; want %d", content.nextA, edit.getBeginA());
+        checkState(content.nextB == edit.getBeginB(),
+            "nextB = %d; want %d", content.nextB, edit.getBeginB());
+        switch (edit.getType()) {
+          case DELETE:
+          case INSERT:
+          case REPLACE:
+            List<Edit> internalEdit = edit instanceof ReplaceEdit
+              ? ((ReplaceEdit) edit).getInternalEdits()
+              : null;
+            content.addDiff(edit.getEndA(), edit.getEndB(), internalEdit);
+            break;
+          case EMPTY:
+          default:
+            throw new IllegalStateException();
+        }
       }
-      content.addCommon(edit.getBeginA());
+      content.addCommon(ps.getA().size());
 
-      checkState(content.nextA == edit.getBeginA(),
-          "nextA = %d; want %d", content.nextA, edit.getBeginA());
-      checkState(content.nextB == edit.getBeginB(),
-          "nextB = %d; want %d", content.nextB, edit.getBeginB());
-      switch (edit.getType()) {
-        case DELETE:
-        case INSERT:
-        case REPLACE:
-          List<Edit> internalEdit = edit instanceof ReplaceEdit
-            ? ((ReplaceEdit) edit).getInternalEdits()
-            : null;
-          content.addDiff(edit.getEndA(), edit.getEndB(), internalEdit);
-          break;
-        case EMPTY:
-        default:
-          throw new IllegalStateException();
+      Result result = new Result();
+      if (ps.getDisplayMethodA() != DisplayMethod.NONE) {
+        result.metaA = new FileMeta();
+        result.metaA.name = Objects.firstNonNull(ps.getOldName(), ps.getNewName());
+        result.metaA.setContentType(ps.getFileModeA(), ps.getMimeTypeA());
       }
-    }
-    content.addCommon(ps.getA().size());
 
-    Result result = new Result();
-    if (ps.getDisplayMethodA() != DisplayMethod.NONE) {
-      result.metaA = new FileMeta();
-      result.metaA.name = Objects.firstNonNull(ps.getOldName(), ps.getNewName());
-      result.metaA.setContentType(ps.getFileModeA(), ps.getMimeTypeA());
-    }
-
-    if (ps.getDisplayMethodB() != DisplayMethod.NONE) {
-      result.metaB = new FileMeta();
-      result.metaB.name = ps.getNewName();
-      result.metaB.setContentType(ps.getFileModeB(), ps.getMimeTypeB());
-    }
-
-    if (intraline) {
-      if (ps.hasIntralineTimeout()) {
-        result.intralineStatus = IntraLineStatus.TIMEOUT;
-      } else if (ps.hasIntralineFailure()) {
-        result.intralineStatus = IntraLineStatus.FAILURE;
-      } else {
-        result.intralineStatus = IntraLineStatus.OK;
+      if (ps.getDisplayMethodB() != DisplayMethod.NONE) {
+        result.metaB = new FileMeta();
+        result.metaB.name = ps.getNewName();
+        result.metaB.setContentType(ps.getFileModeB(), ps.getMimeTypeB());
       }
-    }
 
-    result.changeType = ps.getChangeType();
-    if (ps.getPatchHeader().size() > 0) {
-      result.diffHeader = ps.getPatchHeader();
+      if (intraline) {
+        if (ps.hasIntralineTimeout()) {
+          result.intralineStatus = IntraLineStatus.TIMEOUT;
+        } else if (ps.hasIntralineFailure()) {
+          result.intralineStatus = IntraLineStatus.FAILURE;
+        } else {
+          result.intralineStatus = IntraLineStatus.OK;
+        }
+      }
+
+      result.changeType = ps.getChangeType();
+      if (ps.getPatchHeader().size() > 0) {
+        result.diffHeader = ps.getPatchHeader();
+      }
+      result.content = content.lines;
+      Response<Result> r = Response.ok(result);
+      if (resource.isCacheable()) {
+        r.caching(CacheControl.PRIVATE(7, TimeUnit.DAYS));
+      }
+      return r;
+    } catch (NoSuchChangeException e) {
+      throw new ResourceNotFoundException(e.getMessage());
+    } catch (LargeObjectException e) {
+      throw new ResourceConflictException(e.getMessage());
     }
-    result.content = content.lines;
-    Response<Result> r = Response.ok(result);
-    if (resource.isCacheable()) {
-      r.caching(CacheControl.PRIVATE(7, TimeUnit.DAYS));
-    }
-    return r;
   }
 
   static class Result {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDraft.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDraft.java
index 6b36048..c8a2d43 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDraft.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetDraft.java
@@ -14,15 +14,11 @@
 
 package com.google.gerrit.server.change;
 
-import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.BadRequestException;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.RestReadView;
 
 class GetDraft implements RestReadView<DraftResource> {
   @Override
-  public Object apply(DraftResource rsrc) throws AuthException,
-      BadRequestException, ResourceConflictException, Exception {
+  public CommentInfo apply(DraftResource rsrc) {
     return new CommentInfo(rsrc.getComment(), null);
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRelated.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRelated.java
index 3776b74..325c932 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRelated.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetRelated.java
@@ -70,7 +70,7 @@
   }
 
   @Override
-  public Object apply(RevisionResource rsrc)
+  public RelatedInfo apply(RevisionResource rsrc)
       throws RepositoryNotFoundException, IOException, OrmException {
     Repository git = gitMgr.openRepository(rsrc.getChange().getProject());
     try {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetReview.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetReview.java
index 3676a1e..3440dca 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetReview.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetReview.java
@@ -15,7 +15,9 @@
 package com.google.gerrit.server.change;
 
 import com.google.gerrit.common.changes.ListChangesOption;
+import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestReadView;
+import com.google.gerrit.server.change.ChangeJson.ChangeInfo;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 
@@ -30,7 +32,7 @@
   }
 
   @Override
-  public Object apply(RevisionResource rsrc) throws OrmException {
+  public Response<ChangeInfo> apply(RevisionResource rsrc) throws OrmException {
     return delegate.apply(rsrc);
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetReviewer.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetReviewer.java
index 8c41be8..fac4618 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetReviewer.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetReviewer.java
@@ -15,9 +15,12 @@
 package com.google.gerrit.server.change;
 
 import com.google.gerrit.extensions.restapi.RestReadView;
+import com.google.gerrit.server.change.ReviewerJson.ReviewerInfo;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 
+import java.util.List;
+
 public class GetReviewer implements RestReadView<ReviewerResource> {
   private final ReviewerJson json;
 
@@ -27,7 +30,7 @@
   }
 
   @Override
-  public Object apply(ReviewerResource rsrc) throws OrmException {
+  public List<ReviewerInfo> apply(ReviewerResource rsrc) throws OrmException {
     return json.format(rsrc);
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetTopic.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetTopic.java
index 96a5c76..53f71fd 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/GetTopic.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/GetTopic.java
@@ -16,11 +16,10 @@
 
 import com.google.common.base.Strings;
 import com.google.gerrit.extensions.restapi.RestReadView;
-import com.google.gwtorm.server.OrmException;
 
 class GetTopic implements RestReadView<ChangeResource> {
   @Override
-  public Object apply(ChangeResource rsrc) throws OrmException {
+  public String apply(ChangeResource rsrc) {
     return Strings.nullToEmpty(rsrc.getChange().getTopic());
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/IncludedIn.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/IncludedIn.java
index 26e7846..8df6957 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/IncludedIn.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/IncludedIn.java
@@ -47,8 +47,8 @@
   }
 
   @Override
-  public Object apply(ChangeResource rsrc) throws OrmException, IOException,
-      BadRequestException, ResourceConflictException {
+  public IncludedInInfo apply(ChangeResource rsrc) throws BadRequestException,
+      ResourceConflictException, OrmException, IOException {
     ChangeControl ctl = rsrc.getControl();
     PatchSet ps =
         db.patchSets().get(ctl.getChange().currentPatchSetId());
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Index.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Index.java
index 6ecc544..77b8e5f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Index.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Index.java
@@ -37,7 +37,7 @@
   }
 
   @Override
-  public Object apply(ChangeResource rsrc, Input input) throws IOException {
+  public Response<?> apply(ChangeResource rsrc, Input input) throws IOException {
     indexer.index(rsrc.getChange());
     return Response.none();
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ListDrafts.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ListDrafts.java
index 97c7694..cb03724 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ListDrafts.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ListDrafts.java
@@ -19,9 +19,6 @@
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
 import com.google.gerrit.common.changes.Side;
-import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.BadRequestException;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.RestReadView;
 import com.google.gerrit.reviewdb.client.PatchLineComment;
 import com.google.gerrit.reviewdb.server.ReviewDb;
@@ -58,8 +55,8 @@
   }
 
   @Override
-  public Object apply(RevisionResource rsrc) throws AuthException,
-      BadRequestException, ResourceConflictException, Exception {
+  public Map<String, List<CommentInfo>> apply(RevisionResource rsrc)
+      throws OrmException {
     Map<String, List<CommentInfo>> out = Maps.newTreeMap();
     AccountInfo.Loader accountLoader =
         includeAuthorInfo() ? accountLoaderFactory.create(true) : null;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/ListReviewers.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/ListReviewers.java
index 68cc1b4..7022701 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/ListReviewers.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/ListReviewers.java
@@ -15,16 +15,17 @@
 package com.google.gerrit.server.change;
 
 import com.google.common.collect.Maps;
-import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.RestReadView;
 import com.google.gerrit.reviewdb.client.Account;
 import com.google.gerrit.reviewdb.client.Change;
 import com.google.gerrit.reviewdb.client.PatchSetApproval;
 import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.change.ReviewerJson.ReviewerInfo;
 import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
+import java.util.List;
 import java.util.Map;
 
 class ListReviewers implements RestReadView<ChangeResource> {
@@ -42,8 +43,7 @@
   }
 
   @Override
-  public Object apply(ChangeResource rsrc) throws BadRequestException,
-      OrmException {
+  public List<ReviewerInfo> apply(ChangeResource rsrc) throws OrmException {
     Map<Account.Id, ReviewerResource> reviewers = Maps.newLinkedHashMap();
     ReviewDb db = dbProvider.get();
     Change.Id changeId = rsrc.getChange().getId();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Mergeable.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Mergeable.java
index 595e1c8..852b379 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Mergeable.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Mergeable.java
@@ -35,7 +35,6 @@
 
 import org.eclipse.jgit.errors.IncorrectObjectTypeException;
 import org.eclipse.jgit.errors.MissingObjectException;
-import org.eclipse.jgit.errors.RepositoryNotFoundException;
 import org.eclipse.jgit.lib.AnyObjectId;
 import org.eclipse.jgit.lib.Constants;
 import org.eclipse.jgit.lib.ObjectId;
@@ -80,9 +79,8 @@
   }
 
   @Override
-  public MergeableInfo apply(RevisionResource resource)
-      throws ResourceConflictException, BadRequestException, AuthException,
-      OrmException, RepositoryNotFoundException, IOException {
+  public MergeableInfo apply(RevisionResource resource) throws AuthException,
+      ResourceConflictException, BadRequestException, OrmException, IOException {
     Change change = resource.getChange();
     PatchSet ps = resource.getPatchSet();
     MergeableInfo result = new MergeableInfo();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReview.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReview.java
index 8e9e494..6236dee 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReview.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReview.java
@@ -98,9 +98,9 @@
   }
 
   @Override
-  public Object apply(RevisionResource revision, ReviewInput input)
-      throws AuthException, BadRequestException, OrmException,
-      UnprocessableEntityException, IOException {
+  public Output apply(RevisionResource revision, ReviewInput input)
+      throws AuthException, BadRequestException, UnprocessableEntityException,
+      OrmException, IOException {
     if (input.onBehalfOf != null) {
       revision = onBehalfOf(revision, input);
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReviewers.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReviewers.java
index 13deeb0..de6c123 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReviewers.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PostReviewers.java
@@ -28,7 +28,6 @@
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.DefaultInput;
-import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
 import com.google.gerrit.reviewdb.client.Account;
@@ -132,8 +131,8 @@
 
   @Override
   public PostResult apply(ChangeResource rsrc, Input input)
-      throws BadRequestException, ResourceNotFoundException, AuthException,
-      UnprocessableEntityException, OrmException, EmailException, IOException {
+      throws AuthException, BadRequestException, UnprocessableEntityException,
+      OrmException, EmailException, IOException {
     if (input.reviewer == null) {
       throw new BadRequestException("missing reviewer field");
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Publish.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Publish.java
index 8b0fe99..f28f342 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Publish.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Publish.java
@@ -59,9 +59,9 @@
   }
 
   @Override
-  public Object apply(RevisionResource rsrc, Input input) throws IOException,
-      ResourceNotFoundException, ResourceConflictException,
-      OrmException, AuthException {
+  public Response<?> apply(RevisionResource rsrc, Input input)
+      throws AuthException, ResourceNotFoundException,
+      ResourceConflictException, OrmException, IOException {
     if (!rsrc.getPatchSet().isDraft()) {
       throw new ResourceConflictException("Patch set is not a draft");
     }
@@ -148,9 +148,9 @@
     }
 
     @Override
-    public Object apply(ChangeResource rsrc, Input input) throws AuthException,
-        ResourceConflictException, ResourceConflictException, IOException,
-        OrmException, ResourceNotFoundException, AuthException {
+    public Response<?> apply(ChangeResource rsrc, Input input)
+        throws AuthException, ResourceConflictException,
+        ResourceNotFoundException, IOException, OrmException {
       PatchSet ps = dbProvider.get().patchSets()
         .get(rsrc.getChange().currentPatchSetId());
       if (ps == null) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PutDraft.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PutDraft.java
index 803af17..f2285f0 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PutDraft.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PutDraft.java
@@ -15,15 +15,14 @@
 package com.google.gerrit.server.change;
 
 import com.google.gerrit.common.changes.Side;
-import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.DefaultInput;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.extensions.restapi.Url;
+import com.google.gerrit.reviewdb.client.CommentRange;
 import com.google.gerrit.reviewdb.client.Patch;
 import com.google.gerrit.reviewdb.client.PatchLineComment;
-import com.google.gerrit.reviewdb.client.CommentRange;
 import com.google.gerrit.reviewdb.server.ReviewDb;
 import com.google.gerrit.server.change.PutDraft.Input;
 import com.google.gerrit.server.util.TimeUtil;
@@ -59,8 +58,8 @@
   }
 
   @Override
-  public Object apply(DraftResource rsrc, Input in) throws AuthException,
-      BadRequestException, ResourceConflictException, OrmException {
+  public Response<CommentInfo> apply(DraftResource rsrc, Input in) throws
+      BadRequestException, OrmException {
     PatchLineComment c = rsrc.getComment();
     if (in == null || in.message == null || in.message.trim().isEmpty()) {
       return delete.get().apply(rsrc, null);
@@ -90,7 +89,7 @@
     } else {
       db.get().patchComments().update(Collections.singleton(update(c, in)));
     }
-    return new CommentInfo(c, null);
+    return Response.ok(new CommentInfo(c, null));
   }
 
   private PatchLineComment update(PatchLineComment e, Input in) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/PutTopic.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/PutTopic.java
index acf96e6..84ace98 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/PutTopic.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/PutTopic.java
@@ -18,9 +18,7 @@
 import com.google.common.util.concurrent.CheckedFuture;
 import com.google.gerrit.common.ChangeHooks;
 import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.DefaultInput;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.extensions.webui.UiAction;
@@ -34,6 +32,7 @@
 import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.util.TimeUtil;
 import com.google.gwtorm.server.AtomicUpdate;
+import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
@@ -61,9 +60,8 @@
   }
 
   @Override
-  public Object apply(ChangeResource req, Input input)
-      throws BadRequestException, AuthException,
-      ResourceConflictException, Exception {
+  public Response<String> apply(ChangeResource req, Input input)
+      throws AuthException, OrmException, IOException {
     if (input == null) {
       input = new Input();
     }
@@ -123,8 +121,8 @@
       indexFuture.checkedGet();
     }
     return Strings.isNullOrEmpty(newTopicName)
-        ? Response.none()
-        : newTopicName;
+        ? Response.<String>none()
+        : Response.ok(newTopicName);
   }
 
   @Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Restore.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Restore.java
index a055993..58494c4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Restore.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Restore.java
@@ -69,9 +69,9 @@
   }
 
   @Override
-  public Object apply(ChangeResource req, RestoreInput input)
-      throws OrmException, IOException, AuthException,
-      ResourceConflictException {
+  public ChangeInfo apply(ChangeResource req, RestoreInput input)
+      throws AuthException, ResourceConflictException, OrmException,
+      IOException {
     ChangeControl control = req.getControl();
     IdentifiedUser caller = (IdentifiedUser) control.getCurrentUser();
     Change change = req.getChange();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Revert.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Revert.java
index 74bc68f..5d2ddde 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Revert.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Revert.java
@@ -21,6 +21,7 @@
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.extensions.webui.UiAction;
 import com.google.gerrit.reviewdb.client.Change;
@@ -82,8 +83,8 @@
 
   @Override
   public ChangeInfo apply(ChangeResource req, RevertInput input)
-      throws AuthException, ResourceConflictException, IOException,
-      NoSuchChangeException, EmailException, OrmException, BadRequestException {
+      throws AuthException, BadRequestException, ResourceConflictException,
+      ResourceNotFoundException, IOException, OrmException, EmailException {
     ChangeControl control = req.getControl();
     Change change = req.getChange();
     if (!control.canAddPatchSet()) {
@@ -108,6 +109,8 @@
       return json.format(revertedChangeId);
     } catch (InvalidChangeOperationException e) {
       throw new BadRequestException(e.getMessage());
+    } catch (NoSuchChangeException e) {
+      throw new ResourceNotFoundException(e.getMessage());
     } finally {
       git.close();
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Reviewed.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Reviewed.java
index 022f178..dd27139 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Reviewed.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Reviewed.java
@@ -38,7 +38,7 @@
     }
 
     @Override
-    public Object apply(FileResource resource, Input input)
+    public Response<String> apply(FileResource resource, Input input)
         throws OrmException {
       ReviewDb db = dbProvider.get();
       AccountPatchReview apr = getExisting(db, resource);
@@ -66,7 +66,7 @@
     }
 
     @Override
-    public Object apply(FileResource resource, Input input)
+    public Response<?> apply(FileResource resource, Input input)
         throws OrmException {
       ReviewDb db = dbProvider.get();
       AccountPatchReview apr = getExisting(db, resource);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java
index 2dc066c..3851265 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Submit.java
@@ -35,6 +35,7 @@
 import com.google.gerrit.server.ChangeUtil;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.ProjectUtil;
+import com.google.gerrit.server.change.ChangeJson.ChangeInfo;
 import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.git.MergeQueue;
 import com.google.gerrit.server.index.ChangeIndexer;
@@ -332,7 +333,7 @@
     }
 
     @Override
-    public Object apply(ChangeResource rsrc, SubmitInput input)
+    public ChangeInfo apply(ChangeResource rsrc, SubmitInput input)
         throws AuthException, ResourceConflictException,
         RepositoryNotFoundException, IOException, OrmException {
       PatchSet ps = dbProvider.get().patchSets()
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/TestSubmitRule.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/TestSubmitRule.java
index 85206e5..ab16360 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/TestSubmitRule.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/TestSubmitRule.java
@@ -72,8 +72,8 @@
   }
 
   @Override
-  public Object apply(RevisionResource rsrc, Input input) throws OrmException,
-      BadRequestException, AuthException {
+  public List<Record> apply(RevisionResource rsrc, Input input)
+      throws AuthException, BadRequestException, OrmException {
     if (input == null) {
       input = new Input();
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/TestSubmitType.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/TestSubmitType.java
index 5a4f9e2..f8c1d80 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/TestSubmitType.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/TestSubmitType.java
@@ -28,7 +28,6 @@
 import com.google.gerrit.server.project.RuleEvalException;
 import com.google.gerrit.server.project.SubmitRuleEvaluator;
 import com.google.gerrit.server.query.change.ChangeData;
-import com.google.gwtorm.server.OrmException;
 import com.google.inject.Inject;
 
 import com.googlecode.prolog_cafe.lang.SymbolTerm;
@@ -54,7 +53,7 @@
 
   @Override
   public SubmitType apply(RevisionResource rsrc, Input input)
-      throws OrmException, BadRequestException, AuthException {
+      throws AuthException, BadRequestException {
     if (input == null) {
       input = new Input();
     }
@@ -120,7 +119,7 @@
 
     @Override
     public SubmitType apply(RevisionResource resource)
-        throws BadRequestException, OrmException, AuthException {
+        throws AuthException, BadRequestException {
       return test.apply(resource, null);
     }
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/ListCapabilities.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/ListCapabilities.java
index c64f786..88616e1 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/ListCapabilities.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/ListCapabilities.java
@@ -19,9 +19,6 @@
 import com.google.gerrit.common.data.GlobalCapability;
 import com.google.gerrit.extensions.config.CapabilityDefinition;
 import com.google.gerrit.extensions.registration.DynamicMap;
-import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.BadRequestException;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.RestReadView;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
@@ -43,9 +40,7 @@
 
   @Override
   public Map<String, CapabilityInfo> apply(ConfigResource resource)
-      throws AuthException, BadRequestException, ResourceConflictException,
-      IllegalArgumentException, SecurityException, IllegalAccessException,
-      NoSuchFieldException {
+      throws IllegalAccessException, NoSuchFieldException {
     Map<String, CapabilityInfo> output = Maps.newTreeMap();
     collectCoreCapabilities(output);
     collectPluginCapabilities(output);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/ListTopMenus.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/ListTopMenus.java
index 68ae5c1..c8e9d1e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/ListTopMenus.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/ListTopMenus.java
@@ -31,7 +31,7 @@
   }
 
   @Override
-  public Object apply(ConfigResource resource) {
+  public List<TopMenu.MenuEntry> apply(ConfigResource resource) {
     List<TopMenu.MenuEntry> entries = Lists.newArrayList();
     for (TopMenu extension : extensions) {
       entries.addAll(extension.getEntries());
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/RebaseSorter.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/RebaseSorter.java
index ac1929b..09c970e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/RebaseSorter.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/RebaseSorter.java
@@ -64,7 +64,7 @@
             n.statusCode = CommitMergeStatus.MISSING_DEPENDENCY;
             n.missing = new ArrayList<CodeReviewCommit>();
           }
-          n.missing.add((CodeReviewCommit) c);
+          n.missing.add(c);
         } else {
           contents.add(c);
         }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/group/AddIncludedGroups.java b/gerrit-server/src/main/java/com/google/gerrit/server/group/AddIncludedGroups.java
index 195ea1c..c417dfc 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/group/AddIncludedGroups.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/group/AddIncludedGroups.java
@@ -20,7 +20,6 @@
 import com.google.common.collect.Maps;
 import com.google.gerrit.common.data.GroupDescription;
 import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.DefaultInput;
 import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
 import com.google.gerrit.extensions.restapi.RestModifyView;
@@ -87,7 +86,7 @@
 
   @Override
   public List<GroupInfo> apply(GroupResource resource, Input input)
-      throws MethodNotAllowedException, AuthException, BadRequestException,
+      throws MethodNotAllowedException, AuthException,
       UnprocessableEntityException, OrmException {
     AccountGroup group = resource.toAccountGroup();
     if (group == null) {
@@ -149,7 +148,7 @@
 
     @Override
     public GroupInfo apply(GroupResource resource, Input input)
-        throws MethodNotAllowedException, AuthException, BadRequestException,
+        throws AuthException, MethodNotAllowedException,
         UnprocessableEntityException, OrmException {
       AddIncludedGroups.Input in = new AddIncludedGroups.Input();
       in.groups = ImmutableList.of(id);
@@ -173,8 +172,8 @@
     }
 
     @Override
-    public Object apply(IncludedGroupResource resource,
-        PutIncludedGroup.Input input) throws MethodNotAllowedException, OrmException {
+    public GroupInfo apply(IncludedGroupResource resource,
+        PutIncludedGroup.Input input) throws OrmException {
       // Do nothing, the group is already included.
       return get.get().apply(resource);
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/group/AddMembers.java b/gerrit-server/src/main/java/com/google/gerrit/server/group/AddMembers.java
index 5ebf504..8ec6a3f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/group/AddMembers.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/group/AddMembers.java
@@ -200,7 +200,7 @@
     }
 
     @Override
-    public Object apply(GroupResource resource, PutMember.Input input)
+    public AccountInfo apply(GroupResource resource, PutMember.Input input)
         throws AuthException, MethodNotAllowedException,
         UnprocessableEntityException, OrmException {
       AddMembers.Input in = new AddMembers.Input();
@@ -225,7 +225,7 @@
     }
 
     @Override
-    public Object apply(MemberResource resource, PutMember.Input input)
+    public AccountInfo apply(MemberResource resource, PutMember.Input input)
         throws OrmException {
       // Do nothing, the user is already a member.
       return get.get().apply(resource);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/group/CreateGroup.java b/gerrit-server/src/main/java/com/google/gerrit/server/group/CreateGroup.java
index 6914cf2..cf8d9d0 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/group/CreateGroup.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/group/CreateGroup.java
@@ -24,6 +24,7 @@
 import com.google.gerrit.extensions.annotations.RequiresCapability;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.BadRequestException;
+import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.extensions.restapi.TopLevelResource;
 import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
@@ -79,7 +80,7 @@
   @Override
   public GroupInfo apply(TopLevelResource resource, Input input)
       throws AuthException, BadRequestException, UnprocessableEntityException,
-      NameAlreadyUsedException, OrmException {
+      ResourceConflictException, OrmException {
     if (input == null) {
       input = new Input();
     }
@@ -101,6 +102,8 @@
           null);
     } catch (PermissionDeniedException e) {
       throw new AuthException(e.getMessage());
+    } catch (NameAlreadyUsedException e) {
+      throw new ResourceConflictException(e.getMessage());
     }
     return json.format(GroupDescriptions.forAccountGroup(group));
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/group/DeleteIncludedGroups.java b/gerrit-server/src/main/java/com/google/gerrit/server/group/DeleteIncludedGroups.java
index c5d95b0..04dcda3 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/group/DeleteIncludedGroups.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/group/DeleteIncludedGroups.java
@@ -19,7 +19,6 @@
 import com.google.common.collect.Maps;
 import com.google.gerrit.common.data.GroupDescription;
 import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
 import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestModifyView;
@@ -59,8 +58,8 @@
   }
 
   @Override
-  public Object apply(GroupResource resource, Input input)
-      throws MethodNotAllowedException, AuthException, BadRequestException,
+  public Response<?> apply(GroupResource resource, Input input)
+      throws AuthException, MethodNotAllowedException,
       UnprocessableEntityException, OrmException {
     AccountGroup internalGroup = resource.toAccountGroup();
     if (internalGroup == null) {
@@ -143,8 +142,8 @@
     }
 
     @Override
-    public Object apply(IncludedGroupResource resource, Input input)
-        throws MethodNotAllowedException, AuthException, BadRequestException,
+    public Response<?> apply(IncludedGroupResource resource, Input input)
+        throws AuthException, MethodNotAllowedException,
         UnprocessableEntityException, OrmException {
       AddIncludedGroups.Input in = new AddIncludedGroups.Input();
       in.groups = ImmutableList.of(resource.getMember().get());
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/group/DeleteMembers.java b/gerrit-server/src/main/java/com/google/gerrit/server/group/DeleteMembers.java
index 186d4b6..fd1b8f4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/group/DeleteMembers.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/group/DeleteMembers.java
@@ -16,7 +16,6 @@
 
 import com.google.common.collect.Lists;
 import com.google.common.collect.Maps;
-import com.google.gerrit.common.errors.NoSuchGroupException;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
 import com.google.gerrit.extensions.restapi.Response;
@@ -57,7 +56,7 @@
   }
 
   @Override
-  public Object apply(GroupResource resource, Input input)
+  public Response<?> apply(GroupResource resource, Input input)
       throws AuthException, MethodNotAllowedException,
       UnprocessableEntityException, OrmException {
     AccountGroup internalGroup = resource.toAccountGroup();
@@ -141,9 +140,9 @@
     }
 
     @Override
-    public Object apply(MemberResource resource, Input input)
+    public Response<?> apply(MemberResource resource, Input input)
         throws AuthException, MethodNotAllowedException,
-        UnprocessableEntityException, OrmException, NoSuchGroupException {
+        UnprocessableEntityException, OrmException {
       AddMembers.Input in = new AddMembers.Input();
       in._oneMember = resource.getMember().getAccountId().toString();
       return delete.get().apply(resource, in);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/group/ListGroups.java b/gerrit-server/src/main/java/com/google/gerrit/server/group/ListGroups.java
index 03ec067..76e54b6 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/group/ListGroups.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/group/ListGroups.java
@@ -23,9 +23,6 @@
 import com.google.gerrit.common.data.GroupReference;
 import com.google.gerrit.common.errors.NoSuchGroupException;
 import com.google.gerrit.common.groups.ListGroupsOption;
-import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.BadRequestException;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.RestReadView;
 import com.google.gerrit.extensions.restapi.TopLevelResource;
 import com.google.gerrit.extensions.restapi.Url;
@@ -96,7 +93,7 @@
   @Option(name = "-m", metaVar = "MATCH", usage = "match group substring")
   private String matchSubstring;
 
-  @Option(name = "-o", multiValued = true, usage = "Output options per group")
+  @Option(name = "-o", usage = "Output options per group")
   public void addOption(ListGroupsOption o) {
     options.add(o);
   }
@@ -132,8 +129,7 @@
   }
 
   @Override
-  public Object apply(TopLevelResource resource) throws AuthException,
-      BadRequestException, ResourceConflictException, Exception {
+  public Object apply(TopLevelResource resource) throws OrmException {
     final Map<String, GroupInfo> output = Maps.newTreeMap();
     for (GroupInfo info : get()) {
       output.put(Objects.firstNonNull(
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/group/PutDescription.java b/gerrit-server/src/main/java/com/google/gerrit/server/group/PutDescription.java
index dcc0a76..d17a8b6 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/group/PutDescription.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/group/PutDescription.java
@@ -15,7 +15,6 @@
 package com.google.gerrit.server.group;
 
 import com.google.common.base.Strings;
-import com.google.gerrit.common.errors.NoSuchGroupException;
 import com.google.gerrit.extensions.restapi.AuthException;
 import com.google.gerrit.extensions.restapi.DefaultInput;
 import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
@@ -47,8 +46,8 @@
   }
 
   @Override
-  public Object apply(GroupResource resource, Input input)
-      throws MethodNotAllowedException, AuthException, NoSuchGroupException,
+  public Response<String> apply(GroupResource resource, Input input)
+      throws AuthException, MethodNotAllowedException,
       ResourceNotFoundException, OrmException {
     if (input == null) {
       input = new Input(); // Delete would set description to null.
@@ -71,7 +70,7 @@
     groupCache.evict(group);
 
     return Strings.isNullOrEmpty(input.description)
-        ? Response.none()
-        : input.description;
+        ? Response.<String>none()
+        : Response.ok(input.description);
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/group/PutGroup.java b/gerrit-server/src/main/java/com/google/gerrit/server/group/PutGroup.java
index 9cbed6c..4d3d6be 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/group/PutGroup.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/group/PutGroup.java
@@ -15,12 +15,13 @@
 package com.google.gerrit.server.group;
 
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.server.group.CreateGroup.Input;
 
 public class PutGroup implements RestModifyView<GroupResource, Input> {
   @Override
-  public Object apply(GroupResource resource, Input input)
+  public Response<?> apply(GroupResource resource, Input input)
       throws ResourceConflictException {
     throw new ResourceConflictException("Group already exists");
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineLoader.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineLoader.java
index b95994f..52cba09 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineLoader.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineLoader.java
@@ -248,12 +248,14 @@
           //
           if (ab < ae //
               && (ab == 0 || a.charAt(ab - 1) == '\n') //
-              && ae < a.size() && a.charAt(ae) == '\n') {
+              && ae < a.size() && a.charAt(ae - 1) != '\n'
+              && a.charAt(ae) == '\n') {
             ae++;
           }
           if (bb < be //
               && (bb == 0 || b.charAt(bb - 1) == '\n') //
-              && be < b.size() && b.charAt(be) == '\n') {
+              && be < b.size() && b.charAt(be - 1) != '\n'
+              && b.charAt(be) == '\n') {
             be++;
           }
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/DisablePlugin.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/DisablePlugin.java
index cae5ce6..d6dfa3c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/DisablePlugin.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/DisablePlugin.java
@@ -19,6 +19,7 @@
 import com.google.gerrit.extensions.annotations.RequiresCapability;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.server.plugins.DisablePlugin.Input;
+import com.google.gerrit.server.plugins.ListPlugins.PluginInfo;
 import com.google.inject.Inject;
 
 @RequiresCapability(GlobalCapability.ADMINISTRATE_SERVER)
@@ -34,9 +35,9 @@
   }
 
   @Override
-  public Object apply(PluginResource resource, Input input) {
+  public PluginInfo apply(PluginResource resource, Input input) {
     String name = resource.getName();
     loader.disablePlugins(ImmutableSet.of(name));
-    return new ListPlugins.PluginInfo(loader.get(name));
+    return new PluginInfo(loader.get(name));
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/EnablePlugin.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/EnablePlugin.java
index f33d814..ebe6d1a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/EnablePlugin.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/EnablePlugin.java
@@ -20,6 +20,7 @@
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.server.plugins.EnablePlugin.Input;
+import com.google.gerrit.server.plugins.ListPlugins.PluginInfo;
 import com.google.inject.Inject;
 
 import java.io.PrintWriter;
@@ -38,7 +39,7 @@
   }
 
   @Override
-  public Object apply(PluginResource resource, Input input)
+  public PluginInfo apply(PluginResource resource, Input input)
       throws ResourceConflictException {
     String name = resource.getName();
     try {
@@ -51,6 +52,6 @@
       pw.flush();
       throw new ResourceConflictException(buf.toString());
     }
-    return new ListPlugins.PluginInfo(loader.get(name));
+    return new PluginInfo(loader.get(name));
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/GetStatus.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/GetStatus.java
index 2207d34..7651506 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/GetStatus.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/GetStatus.java
@@ -15,10 +15,11 @@
 package com.google.gerrit.server.plugins;
 
 import com.google.gerrit.extensions.restapi.RestReadView;
+import com.google.gerrit.server.plugins.ListPlugins.PluginInfo;
 
 class GetStatus implements RestReadView<PluginResource> {
   @Override
-  public Object apply(PluginResource resource) {
-    return new ListPlugins.PluginInfo(resource.getPlugin());
+  public PluginInfo apply(PluginResource resource) {
+    return new PluginInfo(resource.getPlugin());
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/InstallPlugin.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/InstallPlugin.java
index 6684bfb..f9bdb48 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/InstallPlugin.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/InstallPlugin.java
@@ -23,6 +23,7 @@
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.extensions.restapi.TopLevelResource;
 import com.google.gerrit.server.plugins.InstallPlugin.Input;
+import com.google.gerrit.server.plugins.ListPlugins.PluginInfo;
 import com.google.inject.Inject;
 
 import java.io.IOException;
@@ -52,7 +53,7 @@
   }
 
   @Override
-  public Response<ListPlugins.PluginInfo> apply(TopLevelResource resource,
+  public Response<PluginInfo> apply(TopLevelResource resource,
       Input input) throws BadRequestException, IOException {
     try {
       InputStream in;
@@ -101,7 +102,7 @@
     }
 
     @Override
-    public Response<ListPlugins.PluginInfo> apply(PluginResource resource,
+    public Response<PluginInfo> apply(PluginResource resource,
         Input input) throws BadRequestException, IOException {
       return new InstallPlugin(loader, resource.getName(), false)
         .apply(TopLevelResource.INSTANCE, input);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ListPlugins.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ListPlugins.java
index ca0f7ae..08c95b2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ListPlugins.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ListPlugins.java
@@ -19,9 +19,6 @@
 import com.google.common.collect.Maps;
 import com.google.gerrit.common.data.GlobalCapability;
 import com.google.gerrit.extensions.annotations.RequiresCapability;
-import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.BadRequestException;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.RestReadView;
 import com.google.gerrit.extensions.restapi.TopLevelResource;
 import com.google.gerrit.extensions.restapi.Url;
@@ -69,8 +66,8 @@
   }
 
   @Override
-  public Object apply(TopLevelResource resource) throws AuthException,
-      BadRequestException, ResourceConflictException, Exception {
+  public Object apply(TopLevelResource resource)
+      throws UnsupportedEncodingException {
     format = OutputFormat.JSON;
     return display(null);
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ReloadPlugin.java b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ReloadPlugin.java
index 9f9ef2db..32e8b24 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ReloadPlugin.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/plugins/ReloadPlugin.java
@@ -19,6 +19,7 @@
 import com.google.gerrit.extensions.annotations.RequiresCapability;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.RestModifyView;
+import com.google.gerrit.server.plugins.ListPlugins.PluginInfo;
 import com.google.gerrit.server.plugins.ReloadPlugin.Input;
 import com.google.inject.Inject;
 
@@ -38,7 +39,7 @@
   }
 
   @Override
-  public Object apply(PluginResource resource, Input input) throws ResourceConflictException {
+  public PluginInfo apply(PluginResource resource, Input input) throws ResourceConflictException {
     String name = resource.getName();
     try {
       loader.reload(ImmutableList.of(name));
@@ -52,6 +53,6 @@
       pw.flush();
       throw new ResourceConflictException(buf.toString());
     }
-    return new ListPlugins.PluginInfo(loader.get(name));
+    return new PluginInfo(loader.get(name));
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java
index 0d4f336..58f6b15 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/CreateProject.java
@@ -32,6 +32,7 @@
 import com.google.gerrit.server.git.ProjectConfig;
 import com.google.gerrit.server.group.GroupsCollection;
 import com.google.gerrit.server.project.CreateProject.Input;
+import com.google.gerrit.server.project.ProjectJson.ProjectInfo;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 import com.google.inject.assistedinject.Assisted;
@@ -82,7 +83,7 @@
   }
 
   @Override
-  public Object apply(TopLevelResource resource, Input input)
+  public Response<ProjectInfo> apply(TopLevelResource resource, Input input)
       throws BadRequestException, UnprocessableEntityException,
       ProjectCreationFailedException, IOException {
     if (input == null) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteBranch.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteBranch.java
index a41c197..600f65d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteBranch.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteBranch.java
@@ -59,7 +59,7 @@
   }
 
   @Override
-  public Object apply(BranchResource rsrc, Input input) throws AuthException,
+  public Response<?> apply(BranchResource rsrc, Input input) throws AuthException,
       ResourceConflictException, OrmException, IOException {
     if (!rsrc.getControl().controlForRef(rsrc.getBranchKey()).canDelete()) {
       throw new AuthException("Cannot delete branch");
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteDashboard.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteDashboard.java
index da1e46b..669f024 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteDashboard.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/DeleteDashboard.java
@@ -18,11 +18,16 @@
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
+import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestModifyView;
+import com.google.gerrit.server.project.DashboardsCollection.DashboardInfo;
 import com.google.gerrit.server.project.DeleteDashboard.Input;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
+import java.io.IOException;
+
 class DeleteDashboard implements RestModifyView<DashboardResource, Input> {
   static class Input {
     String commitMessage;
@@ -36,9 +41,9 @@
   }
 
   @Override
-  public Object apply(DashboardResource resource, Input input)
+  public Response<DashboardInfo> apply(DashboardResource resource, Input input)
       throws AuthException, BadRequestException, ResourceConflictException,
-      Exception {
+      ResourceNotFoundException, MethodNotAllowedException, IOException {
     if (resource.isProjectDefault()) {
       SetDashboard.Input in = new SetDashboard.Input();
       in.commitMessage = input != null ? input.commitMessage : null;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/GarbageCollect.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/GarbageCollect.java
index ca7f6f0..b98cb8b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/GarbageCollect.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/GarbageCollect.java
@@ -20,6 +20,7 @@
 import com.google.gerrit.extensions.annotations.RequiresCapability;
 import com.google.gerrit.extensions.restapi.BinaryResult;
 import com.google.gerrit.extensions.restapi.RestModifyView;
+import com.google.gerrit.extensions.webui.UiAction;
 import com.google.gerrit.server.git.GarbageCollection;
 import com.google.gerrit.server.project.GarbageCollect.Input;
 import com.google.inject.Inject;
@@ -31,8 +32,10 @@
 import java.util.Collections;
 
 @RequiresCapability(GlobalCapability.RUN_GC)
-public class GarbageCollect implements RestModifyView<ProjectResource, Input> {
+public class GarbageCollect implements RestModifyView<ProjectResource, Input>,
+    UiAction<ProjectResource> {
   public static class Input {
+    public boolean showProgress;
   }
 
   private GarbageCollection.Factory garbageCollectionFactory;
@@ -43,7 +46,7 @@
   }
 
   @Override
-  public BinaryResult apply(final ProjectResource rsrc, Input input) {
+  public BinaryResult apply(final ProjectResource rsrc, final Input input) {
     return new BinaryResult() {
       @Override
       public void writeTo(OutputStream out) throws IOException {
@@ -56,10 +59,10 @@
         };
         try {
           GarbageCollectionResult result = garbageCollectionFactory.create().run(
-              Collections.singletonList(rsrc.getNameKey()), writer);
+              Collections.singletonList(rsrc.getNameKey()), input.showProgress ? writer : null);
+          String msg = "garbage collection was successfully done";
           if (result.hasErrors()) {
             for (GarbageCollectionResult.Error e : result.getErrors()) {
-              String msg;
               switch (e.getType()) {
                 case REPOSITORY_NOT_FOUND:
                   msg = "error: project \"" + e.getProjectName() + "\" not found";
@@ -76,9 +79,9 @@
                   msg = "error: garbage collection for project \"" + e.getProjectName()
                       + "\" failed: " + e.getType();
               }
-              writer.println(msg);
             }
           }
+          writer.println(msg);
         } finally {
           writer.flush();
         }
@@ -87,4 +90,11 @@
      .setCharacterEncoding(Charsets.UTF_8.name())
      .disableGzip();
   }
+
+  @Override
+  public UiAction.Description getDescription(ProjectResource rsrc) {
+    return new UiAction.Description()
+        .setLabel("Run GC")
+        .setTitle("Triggers the Git Garbage Collection for this project.");
+  }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetDashboard.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetDashboard.java
index 51d6191..fcd2284 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetDashboard.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetDashboard.java
@@ -20,6 +20,7 @@
 import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 import com.google.gerrit.extensions.restapi.IdString;
+import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.RestReadView;
 import com.google.gerrit.extensions.restapi.Url;
@@ -45,7 +46,7 @@
 
   @Override
   public DashboardInfo apply(DashboardResource resource)
-      throws ResourceNotFoundException, IOException, ConfigInvalidException {
+      throws ResourceNotFoundException, ResourceConflictException, IOException {
     if (inherited && !resource.isProjectDefault()) {
       // inherited flag can only be used with default.
       throw new ResourceNotFoundException("inherited");
@@ -54,7 +55,11 @@
     String project = resource.getControl().getProject().getName();
     if (resource.isProjectDefault()) {
       // The default is not resolved to a definition yet.
-      resource = defaultOf(resource.getControl());
+      try {
+        resource = defaultOf(resource.getControl());
+      } catch (ConfigInvalidException e) {
+        throw new ResourceConflictException(e.getMessage());
+      }
     }
 
     return DashboardsCollection.parse(
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetDescription.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetDescription.java
index d8fabab..aeff72f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetDescription.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetDescription.java
@@ -20,7 +20,7 @@
 
 class GetDescription implements RestReadView<ProjectResource> {
   @Override
-  public Object apply(ProjectResource resource) {
+  public String apply(ProjectResource resource) {
     Project project = resource.getControl().getProject();
     return Strings.nullToEmpty(project.getDescription());
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetParent.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetParent.java
index 1cebd87..f790b7e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetParent.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetParent.java
@@ -28,7 +28,7 @@
   }
 
   @Override
-  public Object apply(ProjectResource resource) {
+  public String apply(ProjectResource resource) {
     Project project = resource.getControl().getProject();
     Project.NameKey parentName = project.getParent(allProjectsName);
     return parentName != null ? parentName.get() : "";
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetProject.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetProject.java
index a482278..961f7b2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/GetProject.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/GetProject.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.server.project;
 
 import com.google.gerrit.extensions.restapi.RestReadView;
+import com.google.gerrit.server.project.ProjectJson.ProjectInfo;
 import com.google.inject.Inject;
 
 class GetProject implements RestReadView<ProjectResource> {
@@ -27,7 +28,7 @@
   }
 
   @Override
-  public Object apply(ProjectResource rsrc) {
+  public ProjectInfo apply(ProjectResource rsrc) {
     return json.format(rsrc);
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ListDashboards.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListDashboards.java
index c063618..e3247fc 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ListDashboards.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListDashboards.java
@@ -53,7 +53,7 @@
   }
 
   @Override
-  public Object apply(ProjectResource resource)
+  public List<?> apply(ProjectResource resource)
       throws ResourceNotFoundException, IOException {
     ProjectControl ctl = resource.getControl();
     String project = ctl.getProject().getName();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ListProjects.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListProjects.java
index f777039..e79912e 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ListProjects.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ListProjects.java
@@ -109,7 +109,7 @@
   @Option(name = "--format", usage = "(deprecated) output format")
   private OutputFormat format = OutputFormat.TEXT;
 
-  @Option(name = "--show-branch", aliases = {"-b"}, multiValued = true,
+  @Option(name = "--show-branch", aliases = {"-b"},
       usage = "displays the sha of each project in the specified branch")
   public void addShowBranch(String branch) {
     showBranch.add(branch);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java
index f98822f..8ab3311 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectControl.java
@@ -496,14 +496,18 @@
       try {
         Map<String, Ref> allRefs = repo.getRefDatabase().getRefs(ALL);
         for (Entry<String, Ref> entry : allRefs.entrySet()) {
+          String refName = entry.getKey();
+          if (!refName.startsWith("refs/heads") && !refName.startsWith("refs/tags")) {
+            continue;
+          }
           RevCommit tip;
           try {
             tip = rw.parseCommit(entry.getValue().getObjectId());
           } catch (IncorrectObjectTypeException e) {
             continue;
           }
-          if (rw.isMergedInto(commit, tip)
-              && controlForRef(entry.getKey()).canPerform(Permission.READ)) {
+          if (controlForRef(entry.getKey()).canPerform(Permission.READ)
+              && rw.isMergedInto(commit, tip)) {
             return true;
           }
         }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/PutDescription.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/PutDescription.java
index f7dd3cb..58db203 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/PutDescription.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/PutDescription.java
@@ -17,7 +17,6 @@
 import com.google.common.base.Objects;
 import com.google.common.base.Strings;
 import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.DefaultInput;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
@@ -57,8 +56,8 @@
   }
 
   @Override
-  public Object apply(ProjectResource resource, Input input)
-      throws AuthException, BadRequestException, ResourceConflictException,
+  public Response<String> apply(ProjectResource resource, Input input)
+      throws AuthException, ResourceConflictException,
       ResourceNotFoundException, IOException {
     if (input == null) {
       input = new Input(); // Delete would set description to null.
@@ -92,8 +91,8 @@
             project.getDescription());
 
         return Strings.isNullOrEmpty(project.getDescription())
-            ? Response.none()
-            : project.getDescription();
+            ? Response.<String>none()
+            : Response.ok(project.getDescription());
       } finally {
         md.close();
       }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/PutProject.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/PutProject.java
index 0a96cb5..836899a2 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/PutProject.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/PutProject.java
@@ -15,12 +15,13 @@
 package com.google.gerrit.server.project;
 
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.Response;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.server.project.CreateProject.Input;
 
 public class PutProject implements RestModifyView<ProjectResource, Input> {
   @Override
-  public Object apply(ProjectResource resource, Input input)
+  public Response<?> apply(ProjectResource resource, Input input)
       throws ResourceConflictException {
     throw new ResourceConflictException("Project \"" + resource.getName()
         + "\" already exists");
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/SetDashboard.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetDashboard.java
index 930da12..8319bbd 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/SetDashboard.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetDashboard.java
@@ -19,11 +19,14 @@
 import com.google.gerrit.extensions.restapi.DefaultInput;
 import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
+import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
 import com.google.gerrit.extensions.restapi.RestModifyView;
 import com.google.gerrit.server.project.SetDashboard.Input;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
+import java.io.IOException;
+
 class SetDashboard implements RestModifyView<DashboardResource, Input> {
   static class Input {
     @DefaultInput
@@ -41,7 +44,7 @@
   @Override
   public Object apply(DashboardResource resource, Input input)
       throws AuthException, BadRequestException, ResourceConflictException,
-      Exception {
+      MethodNotAllowedException, ResourceNotFoundException, IOException {
     if (resource.isProjectDefault()) {
       return defaultSetter.get().apply(resource, input);
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/SetDefaultDashboard.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetDefaultDashboard.java
index 3f70bc2..a323ec8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/SetDefaultDashboard.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetDefaultDashboard.java
@@ -36,6 +36,8 @@
 import org.eclipse.jgit.errors.RepositoryNotFoundException;
 import org.kohsuke.args4j.Option;
 
+import java.io.IOException;
+
 class SetDefaultDashboard implements RestModifyView<DashboardResource, Input> {
   private final ProjectCache cache;
   private final MetaDataUpdate.Server updateFactory;
@@ -57,9 +59,9 @@
   }
 
   @Override
-  public Object apply(DashboardResource resource, Input input)
+  public Response<DashboardInfo> apply(DashboardResource resource, Input input)
       throws AuthException, BadRequestException, ResourceConflictException,
-      Exception {
+      ResourceNotFoundException, IOException {
     if (input == null) {
       input = new Input(); // Delete would set input to null.
     }
@@ -79,6 +81,8 @@
             IdString.fromUrl(input.id));
       } catch (ResourceNotFoundException e) {
         throw new BadRequestException("dashboard " + input.id + " not found");
+      } catch (ConfigInvalidException e) {
+        throw new ResourceConflictException(e.getMessage());
       }
     }
 
@@ -109,7 +113,7 @@
         if (target != null) {
           DashboardInfo info = get.get().apply(target);
           info.isDefault = true;
-          return info;
+          return Response.ok(info);
         }
         return Response.none();
       } finally {
@@ -136,14 +140,13 @@
     }
 
     @Override
-    public Object apply(ProjectResource resource, Input input)
+    public Response<DashboardInfo> apply(ProjectResource resource, Input input)
         throws AuthException, BadRequestException, ResourceConflictException,
-        Exception {
+        ResourceNotFoundException, IOException {
       SetDefaultDashboard set = setDefault.get();
       set.inherited = inherited;
-      return Response.created(set.apply(
-          DashboardResource.projectDefault(resource.getControl()),
-          input));
+      return set.apply(
+          DashboardResource.projectDefault(resource.getControl()), input);
     }
   }
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/SetParent.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetParent.java
index 28175e2..337c6f4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/SetParent.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/SetParent.java
@@ -19,7 +19,6 @@
 import com.google.common.base.Strings;
 import com.google.common.collect.Iterables;
 import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.DefaultInput;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
@@ -59,8 +58,8 @@
   }
 
   @Override
-  public String apply(final ProjectResource rsrc, Input input) throws AuthException,
-      BadRequestException, ResourceConflictException,
+  public String apply(final ProjectResource rsrc, Input input)
+      throws AuthException, ResourceConflictException,
       ResourceNotFoundException, UnprocessableEntityException, IOException {
     ProjectControl ctl = rsrc.getControl();
     validateParentUpdate(ctl, input.parent);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsVisibleToPredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsVisibleToPredicate.java
index 8992318..27b4994 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsVisibleToPredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/IsVisibleToPredicate.java
@@ -30,7 +30,7 @@
       return ((IdentifiedUser) user).getAccountId().toString();
     }
     if (user instanceof SingleGroupUser) {
-      return "group:" + ((SingleGroupUser) user).getEffectiveGroups().getKnownGroups() //
+      return "group:" + user.getEffectiveGroups().getKnownGroups() //
           .iterator().next().toString();
     }
     return user.toString();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryChanges.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryChanges.java
index 4b6a5a6..6ba9e6d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryChanges.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryChanges.java
@@ -45,7 +45,7 @@
   private boolean reverse;
   private EnumSet<ListChangesOption> options;
 
-  @Option(name = "--query", aliases = {"-q"}, metaVar = "QUERY", multiValued = true, usage = "Query string")
+  @Option(name = "--query", aliases = {"-q"}, metaVar = "QUERY", usage = "Query string")
   private List<String> queries;
 
   @Option(name = "--limit", aliases = {"-n"}, metaVar = "CNT", usage = "Maximum number of results to return")
@@ -53,7 +53,7 @@
     imp.setLimit(limit);
   }
 
-  @Option(name = "-o", multiValued = true, usage = "Output options per change")
+  @Option(name = "-o", usage = "Output options per change")
   public void addOption(ListChangesOption o) {
     options.add(o);
   }
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/CommandModule.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/CommandModule.java
index c885484..12f0db0 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/CommandModule.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/CommandModule.java
@@ -72,7 +72,7 @@
    */
   protected void command(final CommandName parent,
       final Class<? extends BaseCommand> clazz) {
-    CommandMetaData meta = (CommandMetaData)clazz.getAnnotation(CommandMetaData.class);
+    CommandMetaData meta = clazz.getAnnotation(CommandMetaData.class);
     if (meta == null) {
       throw new IllegalStateException("no CommandMetaData annotation found");
     }
@@ -91,7 +91,7 @@
    */
   protected void alias(final CommandName parent, final String name,
       final Class<? extends BaseCommand> clazz) {
-    CommandMetaData meta = (CommandMetaData)clazz.getAnnotation(CommandMetaData.class);
+    CommandMetaData meta = clazz.getAnnotation(CommandMetaData.class);
     if (meta == null) {
       throw new IllegalStateException("no CommandMetaData annotation found");
     }
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ApproveOption.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ApproveOption.java
index 29250d3..fea16cd 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ApproveOption.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ApproveOption.java
@@ -24,8 +24,10 @@
 import org.kohsuke.args4j.spi.OneArgumentOptionHandler;
 import org.kohsuke.args4j.spi.OptionHandler;
 import org.kohsuke.args4j.spi.Setter;
+import org.kohsuke.args4j.spi.FieldSetter;
 
 import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
 
 final class ApproveOption implements Option, Setter<Short> {
   private final String name;
@@ -46,6 +48,16 @@
   }
 
   @Override
+  public String[] depends() {
+    return new String[] {};
+  }
+
+  @Override
+  public boolean hidden() {
+    return false;
+  }
+
+  @Override
   public Class<? extends OptionHandler<Short>> handler() {
     return Handler.class;
   }
@@ -56,11 +68,6 @@
   }
 
   @Override
-  public boolean multiValued() {
-    return false;
-  }
-
-  @Override
   public String name() {
     return name;
   }
@@ -85,6 +92,16 @@
   }
 
   @Override
+  public FieldSetter asFieldSetter() {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
+  public AnnotatedElement asAnnotatedElement() {
+    throw new UnsupportedOperationException();
+  }
+
+  @Override
   public void addValue(final Short val) {
     this.value = val;
   }
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/GarbageCollectionCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/GarbageCollectionCommand.java
index 346bea7..81af0d8 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/GarbageCollectionCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/GarbageCollectionCommand.java
@@ -43,6 +43,9 @@
   @Option(name = "--all", usage = "runs the Git garbage collection for all projects")
   private boolean all;
 
+  @Option(name = "--show-progress", usage = "progress information is shown")
+  private boolean showProgress;
+
   @Argument(index = 0, required = false, multiValued = true, metaVar = "NAME",
       usage = "projects for which the Git garbage collection should be run")
   private List<ProjectControl> projects = new ArrayList<ProjectControl>();
@@ -95,7 +98,7 @@
     }
 
     GarbageCollectionResult result =
-        garbageCollectionFactory.create().run(projectNames, stdout);
+        garbageCollectionFactory.create().run(projectNames, showProgress ? stdout : null);
     if (result.hasErrors()) {
       for (GarbageCollectionResult.Error e : result.getErrors()) {
         String msg;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Receive.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Receive.java
index 31f9301..2a8650a 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Receive.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/Receive.java
@@ -62,12 +62,12 @@
   private final Set<Account.Id> reviewerId = new HashSet<Account.Id>();
   private final Set<Account.Id> ccId = new HashSet<Account.Id>();
 
-  @Option(name = "--reviewer", aliases = {"--re"}, multiValued = true, metaVar = "EMAIL", usage = "request reviewer for change(s)")
+  @Option(name = "--reviewer", aliases = {"--re"}, metaVar = "EMAIL", usage = "request reviewer for change(s)")
   void addReviewer(final Account.Id id) {
     reviewerId.add(id);
   }
 
-  @Option(name = "--cc", aliases = {}, multiValued = true, metaVar = "EMAIL", usage = "CC user on change(s)")
+  @Option(name = "--cc", aliases = {}, metaVar = "EMAIL", usage = "CC user on change(s)")
   void addCC(final Account.Id id) {
     ccId.add(id);
   }
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetAccountCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetAccountCommand.java
index 5736bb6..f634147 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetAccountCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetAccountCommand.java
@@ -70,16 +70,16 @@
   @Option(name = "--inactive", usage = "set account's state to inactive")
   private boolean inactive;
 
-  @Option(name = "--add-email", multiValued = true, metaVar = "EMAIL", usage = "email addresses to add to the account")
+  @Option(name = "--add-email", metaVar = "EMAIL", usage = "email addresses to add to the account")
   private List<String> addEmails = new ArrayList<String>();
 
-  @Option(name = "--delete-email", multiValued = true, metaVar = "EMAIL", usage = "email addresses to delete from the account")
+  @Option(name = "--delete-email", metaVar = "EMAIL", usage = "email addresses to delete from the account")
   private List<String> deleteEmails = new ArrayList<String>();
 
-  @Option(name = "--add-ssh-key", multiValued = true, metaVar = "-|KEY", usage = "public keys to add to the account")
+  @Option(name = "--add-ssh-key", metaVar = "-|KEY", usage = "public keys to add to the account")
   private List<String> addSshKeys = new ArrayList<String>();
 
-  @Option(name = "--delete-ssh-key", multiValued = true, metaVar = "-|KEY", usage = "public keys to delete from the account")
+  @Option(name = "--delete-ssh-key", metaVar = "-|KEY", usage = "public keys to delete from the account")
   private List<String> deleteSshKeys = new ArrayList<String>();
 
   @Option(name = "--http-password", metaVar = "PASSWORD", usage = "password for HTTP authentication for the account")
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetReviewersCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetReviewersCommand.java
index 7fc3a40..ce015b6 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetReviewersCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/SetReviewersCommand.java
@@ -142,8 +142,6 @@
       String error;
       try {
         error = post.apply(changeRsrc, input).error;
-      } catch (ResourceNotFoundException e) {
-        error = String.format("could not add %s: not found", reviewer);
       } catch (Exception e) {
         error = String.format("could not add %s: %s", reviewer, e.getMessage());
       }
diff --git a/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/CmdLineParser.java b/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/CmdLineParser.java
index b75635f..7fc6d6f 100644
--- a/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/CmdLineParser.java
+++ b/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/CmdLineParser.java
@@ -52,10 +52,13 @@
 import org.kohsuke.args4j.spi.EnumOptionHandler;
 import org.kohsuke.args4j.spi.OptionHandler;
 import org.kohsuke.args4j.spi.Setter;
+import org.kohsuke.args4j.spi.FieldSetter;
+
 
 import java.io.StringWriter;
 import java.io.Writer;
 import java.lang.annotation.Annotation;
+import java.lang.reflect.AnnotatedElement;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
@@ -381,6 +384,16 @@
     }
 
     @Override
+    public String[] depends() {
+      return new String[] {};
+    }
+
+    @Override
+    public boolean hidden() {
+      return false;
+    }
+
+    @Override
     public String usage() {
       return "display this help text";
     }
@@ -401,11 +414,6 @@
     }
 
     @Override
-    public boolean multiValued() {
-      return false;
-    }
-
-    @Override
     public boolean required() {
       return false;
     }
@@ -416,13 +424,23 @@
     }
 
     @Override
+    public FieldSetter asFieldSetter() {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public AnnotatedElement asAnnotatedElement() {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
     public Class<Boolean> getType() {
       return Boolean.class;
     }
 
     @Override
     public boolean isMultiValued() {
-      return multiValued();
+      return false;
     }
   }
 }
diff --git a/lib/BUCK b/lib/BUCK
index 5ee1bab..2469692 100644
--- a/lib/BUCK
+++ b/lib/BUCK
@@ -121,8 +121,8 @@
 
 maven_jar(
   name = 'args4j',
-  id = 'args4j:args4j:2.0.16',
-  sha1 = '9f00fb12820743b9e05c686eba543d64dd43f2b1',
+  id = 'args4j:args4j:2.0.26',
+  sha1 = '01ebb18ebb3b379a74207d5af4ea7c8338ebd78b',
   license = 'args4j',
 )
 
diff --git a/lib/jetty/BUCK b/lib/jetty/BUCK
index 6eac1a9..6314f99 100644
--- a/lib/jetty/BUCK
+++ b/lib/jetty/BUCK
@@ -1,12 +1,12 @@
 include_defs('//lib/maven.defs')
 
-VERSION = '8.1.7.v20120910'
+VERSION = '9.0.6.v20130930'
 EXCLUDE = ['about.html']
 
 maven_jar(
   name = 'servlet',
   id = 'org.eclipse.jetty:jetty-servlet:' + VERSION,
-  sha1 = '93da01e3ea26e70449e9a1a0affa5c31436be5a0',
+  sha1 = 'b6953af6f857e78fe3c46935fa96f9c80a9cbefd',
   license = 'Apache2.0',
   deps = [
     ':security',
@@ -18,7 +18,7 @@
 maven_jar(
   name = 'security',
   id = 'org.eclipse.jetty:jetty-security:' + VERSION,
-  sha1 = '8d78beb7a07f4cccee05a3f16a264f1025946258',
+  sha1 = 'b16cd29ad9d3d3cca8176a654adf4b2ddca0eb3e',
   license = 'Apache2.0',
   deps = [':server'],
   exclude = EXCLUDE,
@@ -28,7 +28,7 @@
 maven_jar(
   name = 'server',
   id = 'org.eclipse.jetty:jetty-server:' + VERSION,
-  sha1 = '6c81f733f28713919e99c2f8952e6ca5178033cd',
+  sha1 = 'd89016c2bcd380f548530fa049295e62601dc564',
   license = 'Apache2.0',
   deps = [
     ':continuation',
@@ -41,7 +41,7 @@
 maven_jar(
   name = 'continuation',
   id = 'org.eclipse.jetty:jetty-continuation:' + VERSION,
-  sha1 = 'f60cfe6267038000b459508529c88737601081e4',
+  sha1 = '4f942a52a3e996634ff302ab98f46d224b0db9d2',
   license = 'Apache2.0',
   exclude = EXCLUDE,
 )
@@ -49,7 +49,7 @@
 maven_jar(
   name = 'http',
   id = 'org.eclipse.jetty:jetty-http:' + VERSION,
-  sha1 = '10126433876cd74534695f7f99c4362596555493',
+  sha1 = 'b3a2302717ac1889b4a17ed03e2555f8291121b9',
   license = 'Apache2.0',
   deps = [':io'],
   exclude = EXCLUDE,
@@ -58,7 +58,7 @@
 maven_jar(
   name = 'io',
   id = 'org.eclipse.jetty:jetty-io:' + VERSION,
-  sha1 = 'a81f746ae1b10c37e1bb0a01d1374c202c0bd549',
+  sha1 = 'f3a66e0507d963c51e280243f0472a5b2eadc8b1',
   license = 'Apache2.0',
   deps = [':util'],
   exclude = EXCLUDE,
@@ -68,7 +68,7 @@
 maven_jar(
   name = 'util',
   id = 'org.eclipse.jetty:jetty-util:' + VERSION,
-  sha1 = '7eb2004ab2c22fd3b00095bd9ba0f32a9e88f6a5',
+  sha1 = 'f36c9e61559d1154be9b52803ef4f586e401dac6',
   license = 'Apache2.0',
   exclude = EXCLUDE,
   visibility = [],
diff --git a/plugins/replication b/plugins/replication
index c126e78..5ee79cc 160000
--- a/plugins/replication
+++ b/plugins/replication
@@ -1 +1 @@
-Subproject commit c126e78886cd985edddee66ad1aba0130a4a5819
+Subproject commit 5ee79cc5355e24bee7d38f697aa834e1bd6e0e7d
diff --git a/tools/default.defs b/tools/default.defs
index 4ed5635..b7ef6b4 100644
--- a/tools/default.defs
+++ b/tools/default.defs
@@ -14,6 +14,8 @@
 
 # Rule definitions loaded by default into every BUCK file.
 
+include_defs('//tools/gwt-constants.defs')
+
 def genantlr(
     name,
     srcs,
@@ -128,6 +130,7 @@
     deps = [],
     srcs = [],
     resources = [],
+    gwt_module = None,
     manifest_file = None,
     manifest_entries = [],
     type = 'plugin',
@@ -149,20 +152,47 @@
     srcs = mf_src,
     out = 'MANIFEST.MF',
   )
+  gwt_deps = []
+  static_jars = []
+  if gwt_module:
+    gwt_deps = GWT_PLUGIN_DEPS
+    static_jars = [':%s-static-jar' % name]
   java_library2(
     name = name + '__plugin',
     srcs = srcs,
     resources = resources,
     deps = deps,
-    compile_deps = ['//:%s-lib' % type],
+    compile_deps = ['//:%s-lib' % type] + gwt_deps,
   )
+  if gwt_module:
+    prebuilt_jar(
+      name = '%s-static-jar' % name,
+      binary_jar = genfile('%s-static.zip' % name),
+      deps = [':%s-static' % name],
+    )
+    genrule(
+      name = '%s-static' % name,
+      cmd = 'mkdir -p $TMP/static' +
+        ';unzip -qd $TMP/static $(location %s)' %
+        ':%s__gwt_application' % name +
+        ';cd $TMP' +
+        ';zip -qr $OUT .',
+      out = '%s-static.zip' % name,
+      deps = [':%s__gwt_application' % name]
+    )
+    gwt_application(
+      name = name + '__gwt_application',
+      module_target = gwt_module,
+      compiler_opts = GWT_COMPILER_OPTS,
+      deps = [':%s__plugin' % name] + gwt_deps,
+    )
   java_binary(
     name = name,
     manifest_file = genfile('MANIFEST.MF'),
     deps = [
       ':%s__plugin' % name,
       ':%s__manifest' % name,
-    ],
+    ] + static_jars,
     visibility = visibility,
   )
 
diff --git a/tools/gwt-constants.defs b/tools/gwt-constants.defs
new file mode 100644
index 0000000..56978e7
--- /dev/null
+++ b/tools/gwt-constants.defs
@@ -0,0 +1,13 @@
+GWT_COMPILER_OPTS = [
+  '-strict',
+  '-style', 'OBF',
+  '-optimize', '9',
+  '-XdisableClassMetadata',
+  '-XdisableCastChecking',
+  '-XenableClosureCompiler',
+]
+
+GWT_PLUGIN_DEPS = [
+  '//gerrit-plugin-gwtui:client',
+  '//lib/gwt:user',
+]