Extract MethodNotAllowed as an API exception

This allows views to throw with a proper HTTP error code if
a specific method is not a valid call on a resource.

Change-Id: Iad15024edd66ab3908c5b4e7319b8956b935b8a2
diff --git a/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/restapi/MethodNotAllowedException.java b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/restapi/MethodNotAllowedException.java
new file mode 100644
index 0000000..8b0fdd3
--- /dev/null
+++ b/gerrit-extension-api/src/main/java/com/google/gerrit/extensions/restapi/MethodNotAllowedException.java
@@ -0,0 +1,20 @@
+// Copyright (C) 2012 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.extensions.restapi;
+
+/** Method is not acceptable on the resource (HTTP 405 Method Not Allowed). */
+public class MethodNotAllowedException extends RestApiException {
+  private static final long serialVersionUID = 1L;
+}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
index 0b83b1c..f05f9a6d 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
@@ -41,6 +41,7 @@
 import com.google.gerrit.extensions.restapi.BadRequestException;
 import com.google.gerrit.extensions.restapi.BinaryResult;
 import com.google.gerrit.extensions.restapi.DefaultInput;
+import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
 import com.google.gerrit.extensions.restapi.PutInput;
 import com.google.gerrit.extensions.restapi.ResourceConflictException;
 import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
@@ -247,7 +248,7 @@
       replyError(res, SC_FORBIDDEN, e.getMessage());
     } catch (BadRequestException e) {
       replyError(res, SC_BAD_REQUEST, e.getMessage());
-    } catch (InvalidMethodException e) {
+    } catch (MethodNotAllowedException e) {
       replyError(res, SC_METHOD_NOT_ALLOWED, "Method not allowed");
     } catch (ResourceConflictException e) {
       replyError(res, SC_CONFLICT, e.getMessage());
@@ -265,7 +266,7 @@
   private Object parseRequest(HttpServletRequest req, Class<Object> type)
       throws IOException, BadRequestException, SecurityException,
       IllegalArgumentException, NoSuchMethodException, IllegalAccessException,
-      InstantiationException, InvocationTargetException, InvalidMethodException {
+      InstantiationException, InvocationTargetException, MethodNotAllowedException {
     if (isType(JSON_TYPE, req.getContentType())) {
       BufferedReader br = req.getReader();
       try {
@@ -326,7 +327,7 @@
   private Object parsePutInput(final HttpServletRequest req, Class<Object> type)
       throws SecurityException, NoSuchMethodException,
       IllegalArgumentException, InstantiationException, IllegalAccessException,
-      InvocationTargetException, InvalidMethodException {
+      InvocationTargetException, MethodNotAllowedException {
     Object obj = createInstance(type);
     for (Field f : type.getDeclaredFields()) {
       if (f.getType() == PutInput.class) {
@@ -350,7 +351,7 @@
         return obj;
       }
     }
-    throw new InvalidMethodException();
+    throw new MethodNotAllowedException();
   }
 
   private Object parseString(String value, Class<Object> type)
@@ -513,7 +514,7 @@
   private RestView<RestResource> view(
       RestCollection<RestResource, RestResource> rc,
       String method, List<String> path) throws ResourceNotFoundException,
-      InvalidMethodException, AmbiguousViewException {
+      MethodNotAllowedException, AmbiguousViewException {
     DynamicMap<RestView<RestResource>> views = rc.views();
     final String projection = path.isEmpty() ? "/" : path.remove(0);
     if (!path.isEmpty()) {
@@ -681,10 +682,6 @@
   }
 
   @SuppressWarnings("serial")
-  private static class InvalidMethodException extends Exception {
-  }
-
-  @SuppressWarnings("serial")
   private static class AmbiguousViewException extends Exception {
     AmbiguousViewException(String message) {
       super(message);