// 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.httpd.restapi;

import static com.google.common.base.Preconditions.checkNotNull;
import static java.math.RoundingMode.CEILING;
import static java.nio.charset.StandardCharsets.ISO_8859_1;
import static java.nio.charset.StandardCharsets.UTF_8;
import static javax.servlet.http.HttpServletResponse.SC_BAD_REQUEST;
import static javax.servlet.http.HttpServletResponse.SC_CONFLICT;
import static javax.servlet.http.HttpServletResponse.SC_CREATED;
import static javax.servlet.http.HttpServletResponse.SC_FORBIDDEN;
import static javax.servlet.http.HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
import static javax.servlet.http.HttpServletResponse.SC_METHOD_NOT_ALLOWED;
import static javax.servlet.http.HttpServletResponse.SC_NOT_FOUND;
import static javax.servlet.http.HttpServletResponse.SC_NOT_MODIFIED;
import static javax.servlet.http.HttpServletResponse.SC_OK;
import static javax.servlet.http.HttpServletResponse.SC_PRECONDITION_FAILED;

import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.base.Objects;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.google.common.io.BaseEncoding;
import com.google.common.math.IntMath;
import com.google.common.net.HttpHeaders;
import com.google.gerrit.audit.AuditService;
import com.google.gerrit.audit.HttpAuditEvent;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.AcceptsCreate;
import com.google.gerrit.extensions.restapi.AcceptsPost;
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.CacheControl;
import com.google.gerrit.extensions.restapi.DefaultInput;
import com.google.gerrit.extensions.restapi.IdString;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.PreconditionFailedException;
import com.google.gerrit.extensions.restapi.RawInput;
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.RestApiException;
import com.google.gerrit.extensions.restapi.RestCollection;
import com.google.gerrit.extensions.restapi.RestModifyView;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.extensions.restapi.RestResource;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.extensions.restapi.UnprocessableEntityException;
import com.google.gerrit.httpd.WebSession;
import com.google.gerrit.server.AccessPath;
import com.google.gerrit.server.AnonymousUser;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.OptionUtil;
import com.google.gerrit.server.OutputFormat;
import com.google.gerrit.server.account.CapabilityUtils;
import com.google.gerrit.server.util.TimeUtil;
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.FieldNamingPolicy;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonElement;
import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
import com.google.gson.stream.MalformedJsonException;
import com.google.gwtexpui.server.CacheHeaders;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.util.Providers;

import org.eclipse.jgit.util.TemporaryBuffer;
import org.eclipse.jgit.util.TemporaryBuffer.Heap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.EOFException;
import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.sql.Timestamp;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.zip.GZIPOutputStream;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

public class RestApiServlet extends HttpServlet {
  private static final long serialVersionUID = 1L;
  private static final Logger log = LoggerFactory
      .getLogger(RestApiServlet.class);

  /** MIME type used for a JSON response body. */
  private static final String JSON_TYPE = "application/json";
  private static final String FORM_TYPE = "application/x-www-form-urlencoded";

  /**
   * Garbage prefix inserted before JSON output to prevent XSSI.
   * <p>
   * This prefix is ")]}'\n" and is designed to prevent a web browser from
   * executing the response body if the resource URI were to be referenced using
   * a &lt;script src="...&gt; HTML tag from another web site. Clients using the
   * HTTP interface will need to always strip the first line of response data to
   * remove this magic header.
   */
  public static final byte[] JSON_MAGIC;

  static {
    JSON_MAGIC = ")]}'\n".getBytes(UTF_8);
  }

  public static class Globals {
    final Provider<CurrentUser> currentUser;
    final DynamicItem<WebSession> webSession;
    final Provider<ParameterParser> paramParser;
    final AuditService auditService;

    @Inject
    Globals(Provider<CurrentUser> currentUser,
        DynamicItem<WebSession> webSession,
        Provider<ParameterParser> paramParser,
        AuditService auditService) {
      this.currentUser = currentUser;
      this.webSession = webSession;
      this.paramParser = paramParser;
      this.auditService = auditService;
    }
  }

  private final Globals globals;
  private final Provider<RestCollection<RestResource, RestResource>> members;

  public RestApiServlet(Globals globals,
      RestCollection<? extends RestResource, ? extends RestResource> members) {
    this(globals, Providers.of(members));
  }

  public RestApiServlet(Globals globals,
      Provider<? extends RestCollection<? extends RestResource, ? extends RestResource>> members) {
    @SuppressWarnings("unchecked")
    Provider<RestCollection<RestResource, RestResource>> n =
        (Provider<RestCollection<RestResource, RestResource>>) checkNotNull((Object) members);
    this.globals = globals;
    this.members = n;
  }

  @Override
  protected final void service(HttpServletRequest req, HttpServletResponse res)
      throws ServletException, IOException {
    long auditStartTs = TimeUtil.nowMs();
    res.setHeader("Content-Disposition", "attachment");
    res.setHeader("X-Content-Type-Options", "nosniff");
    int status = SC_OK;
    Object result = null;
    Multimap<String, String> params = LinkedHashMultimap.create();
    Object inputRequestBody = null;

    try {
      checkUserSession(req);

      List<IdString> path = splitPath(req);
      RestCollection<RestResource, RestResource> rc = members.get();
      CapabilityUtils.checkRequiresCapability(globals.currentUser,
          null, rc.getClass());

      RestResource rsrc = TopLevelResource.INSTANCE;
      ViewData viewData = new ViewData(null, null);
      if (path.isEmpty()) {
        if (isGetOrHead(req)) {
          viewData = new ViewData(null, rc.list());
        } else if (rc instanceof AcceptsPost && "POST".equals(req.getMethod())) {
          @SuppressWarnings("unchecked")
          AcceptsPost<RestResource> ac = (AcceptsPost<RestResource>) rc;
          viewData = new ViewData(null, ac.post(rsrc));
        } else {
          throw new MethodNotAllowedException();
        }
      } else {
        IdString id = path.remove(0);
        try {
          rsrc = rc.parse(rsrc, id);
          if (path.isEmpty()) {
            checkPreconditions(req, rsrc);
          }
        } catch (ResourceNotFoundException e) {
          if (rc instanceof AcceptsCreate
              && path.isEmpty()
              && ("POST".equals(req.getMethod())
                  || "PUT".equals(req.getMethod()))) {
            @SuppressWarnings("unchecked")
            AcceptsCreate<RestResource> ac = (AcceptsCreate<RestResource>) rc;
            viewData = new ViewData(null, ac.create(rsrc, id));
            status = SC_CREATED;
          } else {
            throw e;
          }
        }
        if (viewData.view == null) {
          viewData = view(rsrc, rc, req.getMethod(), path);
        }
      }
      checkRequiresCapability(viewData);

      while (viewData.view instanceof RestCollection<?,?>) {
        @SuppressWarnings("unchecked")
        RestCollection<RestResource, RestResource> c =
            (RestCollection<RestResource, RestResource>) viewData.view;

        if (path.isEmpty()) {
          if (isGetOrHead(req)) {
            viewData = new ViewData(null, c.list());
          } else if (c instanceof AcceptsPost && "POST".equals(req.getMethod())) {
            @SuppressWarnings("unchecked")
            AcceptsPost<RestResource> ac = (AcceptsPost<RestResource>) c;
            viewData = new ViewData(null, ac.post(rsrc));
          } else {
            throw new MethodNotAllowedException();
          }
          break;
        } else {
          IdString id = path.remove(0);
          try {
            rsrc = c.parse(rsrc, id);
            checkPreconditions(req, rsrc);
            viewData = new ViewData(null, null);
          } catch (ResourceNotFoundException e) {
            if (c instanceof AcceptsCreate
                && path.isEmpty()
                && ("POST".equals(req.getMethod())
                    || "PUT".equals(req.getMethod()))) {
              @SuppressWarnings("unchecked")
              AcceptsCreate<RestResource> ac = (AcceptsCreate<RestResource>) c;
              viewData = new ViewData(viewData.pluginName, ac.create(rsrc, id));
              status = SC_CREATED;
            } else {
              throw e;
            }
          }
          if (viewData.view == null) {
            viewData = view(rsrc, c, req.getMethod(), path);
          }
        }
        checkRequiresCapability(viewData);
      }

      if (notModified(req, rsrc)) {
        res.sendError(SC_NOT_MODIFIED);
        return;
      }

      Multimap<String, String> config = LinkedHashMultimap.create();
      ParameterParser.splitQueryString(req.getQueryString(), config, params);
      if (!globals.paramParser.get().parse(viewData.view, params, req, res)) {
        return;
      }

      if (viewData.view instanceof RestModifyView<?, ?>) {
        @SuppressWarnings("unchecked")
        RestModifyView<RestResource, Object> m =
            (RestModifyView<RestResource, Object>) viewData.view;

        inputRequestBody = parseRequest(req, inputType(m));
        result = m.apply(rsrc, inputRequestBody);
      } else if (viewData.view instanceof RestReadView<?>) {
        result = ((RestReadView<RestResource>) viewData.view).apply(rsrc);
      } else {
        throw new ResourceNotFoundException();
      }

      if (result instanceof Response) {
        @SuppressWarnings("rawtypes")
        Response<?> r = (Response) result;
        status = r.statusCode();
        configureCaching(req, res, rsrc, r.caching());
      } else if (result instanceof Response.Redirect) {
        CacheHeaders.setNotCacheable(res);
        res.sendRedirect(((Response.Redirect) result).location());
        return;
      } else {
        CacheHeaders.setNotCacheable(res);
      }
      res.setStatus(status);

      if (result != Response.none()) {
        result = Response.unwrap(result);
        if (result instanceof BinaryResult) {
          replyBinaryResult(req, res, (BinaryResult) result);
        } else {
          replyJson(req, res, config, result);
        }
      }
    } catch (AuthException e) {
      replyError(req, res, status = SC_FORBIDDEN, e.getMessage(), e.caching());
    } catch (BadRequestException e) {
      replyError(req, res, status = SC_BAD_REQUEST, e.getMessage(), e.caching());
    } catch (MethodNotAllowedException e) {
      replyError(req, res, status = SC_METHOD_NOT_ALLOWED, "Method not allowed", e.caching());
    } catch (ResourceConflictException e) {
      replyError(req, res, status = SC_CONFLICT, e.getMessage(), e.caching());
    } catch (PreconditionFailedException e) {
      replyError(req, res, status = SC_PRECONDITION_FAILED,
          Objects.firstNonNull(e.getMessage(), "Precondition failed"), e.caching());
    } catch (ResourceNotFoundException e) {
      replyError(req, res, status = SC_NOT_FOUND, "Not found", e.caching());
    } catch (UnprocessableEntityException e) {
      replyError(req, res, status = 422,
          Objects.firstNonNull(e.getMessage(), "Unprocessable Entity"), e.caching());
    } catch (AmbiguousViewException e) {
      replyError(req, res, status = SC_NOT_FOUND, e.getMessage());
    } catch (MalformedJsonException e) {
      replyError(req, res, status = SC_BAD_REQUEST, "Invalid " + JSON_TYPE + " in request");
    } catch (JsonParseException e) {
      replyError(req, res, status = SC_BAD_REQUEST, "Invalid " + JSON_TYPE + " in request");
    } catch (Exception e) {
      status = SC_INTERNAL_SERVER_ERROR;
      handleException(e, req, res);
    } finally {
      globals.auditService.dispatch(new HttpAuditEvent(globals.webSession.get()
          .getSessionId(), globals.currentUser.get(), req.getRequestURI(),
          auditStartTs, params, req.getMethod(), inputRequestBody, status,
          result));
    }
  }

  private static boolean notModified(HttpServletRequest req, RestResource rsrc) {
    if (!isGetOrHead(req)) {
      return false;
    }

    if (rsrc instanceof RestResource.HasETag) {
      String have = req.getHeader(HttpHeaders.IF_NONE_MATCH);
      if (have != null) {
        return have.equals(((RestResource.HasETag) rsrc).getETag());
      }
    }

    if (rsrc instanceof RestResource.HasLastModified) {
      Timestamp m = ((RestResource.HasLastModified) rsrc).getLastModified();
      long d = req.getDateHeader(HttpHeaders.IF_MODIFIED_SINCE);

      // HTTP times are in seconds, database may have millisecond precision.
      return d / 1000L == m.getTime() / 1000L;
    }
    return false;
  }

  private static <T> void configureCaching(HttpServletRequest req,
      HttpServletResponse res, RestResource rsrc, CacheControl c) {
    if (isGetOrHead(req)) {
      switch (c.getType()) {
        case NONE:
        default:
          CacheHeaders.setNotCacheable(res);
          break;
        case PRIVATE:
          addResourceStateHeaders(res, rsrc);
          CacheHeaders.setCacheablePrivate(res,
              c.getAge(), c.getUnit(),
              c.isMustRevalidate());
          break;
        case PUBLIC:
          addResourceStateHeaders(res, rsrc);
          CacheHeaders.setCacheable(req, res,
              c.getAge(), c.getUnit(),
              c.isMustRevalidate());
          break;
      }
    } else {
      CacheHeaders.setNotCacheable(res);
    }
  }

  private static void addResourceStateHeaders(
      HttpServletResponse res, RestResource rsrc) {
    if (rsrc instanceof RestResource.HasETag) {
      res.setHeader(
          HttpHeaders.ETAG,
          ((RestResource.HasETag) rsrc).getETag());
    }
    if (rsrc instanceof RestResource.HasLastModified) {
      res.setDateHeader(
          HttpHeaders.LAST_MODIFIED,
          ((RestResource.HasLastModified) rsrc).getLastModified().getTime());
    }
  }

  private void checkPreconditions(HttpServletRequest req, RestResource rsrc)
      throws PreconditionFailedException {
    if ("*".equals(req.getHeader("If-None-Match"))) {
      throw new PreconditionFailedException("Resource already exists");
    }
  }

  private static Type inputType(RestModifyView<RestResource, Object> m) {
    Type inputType = extractInputType(m.getClass());
    if (inputType == null) {
      throw new IllegalStateException(String.format(
          "View %s does not correctly implement %s",
          m.getClass(), RestModifyView.class.getSimpleName()));
    }
    return inputType;
  }

  @SuppressWarnings("rawtypes")
  private static Type extractInputType(Class clazz) {
    for (Type t : clazz.getGenericInterfaces()) {
      if (t instanceof ParameterizedType
          && ((ParameterizedType) t).getRawType() == RestModifyView.class) {
        return ((ParameterizedType) t).getActualTypeArguments()[1];
      }
    }

    if (clazz.getSuperclass() != null) {
      Type i = extractInputType(clazz.getSuperclass());
      if (i != null) {
        return i;
      }
    }

    for (Class t : clazz.getInterfaces()) {
      Type i = extractInputType(t);
      if (i != null) {
        return i;
      }
    }

    return null;
  }

  private Object parseRequest(HttpServletRequest req, Type type)
      throws IOException, BadRequestException, SecurityException,
      IllegalArgumentException, NoSuchMethodException, IllegalAccessException,
      InstantiationException, InvocationTargetException, MethodNotAllowedException {
    if (isType(JSON_TYPE, req.getContentType())) {
      BufferedReader br = req.getReader();
      try {
        JsonReader json = new JsonReader(br);
        json.setLenient(true);

        JsonToken first;
        try {
          first = json.peek();
        } catch (EOFException e) {
          throw new BadRequestException("Expected JSON object");
        }
        if (first == JsonToken.STRING) {
          return parseString(json.nextString(), type);
        }
        return OutputFormat.JSON.newGson().fromJson(json, type);
      } finally {
        br.close();
      }
    } else if (("PUT".equals(req.getMethod()) || "POST".equals(req.getMethod()))
        && acceptsRawInput(type)) {
      return parseRawInput(req, type);
    } else if ("DELETE".equals(req.getMethod()) && hasNoBody(req)) {
      return null;
    } else if (hasNoBody(req)) {
      return createInstance(type);
    } else if (isType("text/plain", req.getContentType())) {
      BufferedReader br = req.getReader();
      try {
        char[] tmp = new char[256];
        StringBuilder sb = new StringBuilder();
        int n;
        while (0 < (n = br.read(tmp))) {
          sb.append(tmp, 0, n);
        }
        return parseString(sb.toString(), type);
      } finally {
        br.close();
      }
    } else if ("POST".equals(req.getMethod())
        && isType(FORM_TYPE, req.getContentType())) {
      return OutputFormat.JSON.newGson().fromJson(
          ParameterParser.formToJson(req),
          type);
    } else {
      throw new BadRequestException("Expected Content-Type: " + JSON_TYPE);
    }
  }

  private static boolean hasNoBody(HttpServletRequest req) {
    int len = req.getContentLength();
    String type = req.getContentType();
    return (len <= 0 && type == null)
        || (len == 0 && isType(FORM_TYPE, type));
  }

  @SuppressWarnings("rawtypes")
  private static boolean acceptsRawInput(Type type) {
    if (type instanceof Class) {
      for (Field f : ((Class) type).getDeclaredFields()) {
        if (f.getType() == RawInput.class) {
          return true;
        }
      }
    }
    return false;
  }

  private Object parseRawInput(final HttpServletRequest req, Type type)
      throws SecurityException, NoSuchMethodException,
      IllegalArgumentException, InstantiationException, IllegalAccessException,
      InvocationTargetException, MethodNotAllowedException {
    Object obj = createInstance(type);
    for (Field f : obj.getClass().getDeclaredFields()) {
      if (f.getType() == RawInput.class) {
        f.setAccessible(true);
        f.set(obj, new RawInput() {
          @Override
          public String getContentType() {
            return req.getContentType();
          }

          @Override
          public long getContentLength() {
            return req.getContentLength();
          }

          @Override
          public InputStream getInputStream() throws IOException {
            return req.getInputStream();
          }
        });
        return obj;
      }
    }
    throw new MethodNotAllowedException();
  }

  private Object parseString(String value, Type type)
      throws BadRequestException, SecurityException, NoSuchMethodException,
      IllegalArgumentException, IllegalAccessException, InstantiationException,
      InvocationTargetException {
    if (type == String.class) {
      return value;
    }

    Object obj = createInstance(type);
    Field[] fields = obj.getClass().getDeclaredFields();
    if (fields.length == 0 && Strings.isNullOrEmpty(value)) {
      return obj;
    }
    for (Field f : fields) {
      if (f.getAnnotation(DefaultInput.class) != null
          && f.getType() == String.class) {
        f.setAccessible(true);
        f.set(obj, value);
        return obj;
      }
    }
    throw new BadRequestException("Expected JSON object");
  }

  private static Object createInstance(Type type)
      throws NoSuchMethodException, InstantiationException,
      IllegalAccessException, InvocationTargetException {
    if (type instanceof Class) {
      @SuppressWarnings("unchecked")
      Class<Object> clazz = (Class<Object>) type;
      Constructor<Object> c = clazz.getDeclaredConstructor();
      c.setAccessible(true);
      return c.newInstance();
    }
    throw new InstantiationException("Cannot make " + type);
  }

  public static void replyJson(@Nullable HttpServletRequest req,
      HttpServletResponse res,
      Multimap<String, String> config,
      Object result)
      throws IOException {
    TemporaryBuffer.Heap buf = heap(Integer.MAX_VALUE);
    buf.write(JSON_MAGIC);
    Writer w = new BufferedWriter(new OutputStreamWriter(buf, UTF_8));
    Gson gson = newGson(config, req);
    if (result instanceof JsonElement) {
      gson.toJson((JsonElement) result, w);
    } else {
      gson.toJson(result, w);
    }
    w.write('\n');
    w.flush();
    replyBinaryResult(req, res, asBinaryResult(buf)
      .setContentType(JSON_TYPE)
      .setCharacterEncoding(UTF_8.name()));
  }

  private static Gson newGson(Multimap<String, String> config,
      @Nullable HttpServletRequest req) {
    GsonBuilder gb = OutputFormat.JSON_COMPACT.newGsonBuilder();

    enablePrettyPrint(gb, config, req);
    enablePartialGetFields(gb, config);

    return gb.create();
  }

  private static void enablePrettyPrint(GsonBuilder gb,
      Multimap<String, String> config,
      @Nullable HttpServletRequest req) {
    String pp = Iterables.getFirst(config.get("pp"), null);
    if (pp == null) {
      pp = Iterables.getFirst(config.get("prettyPrint"), null);
      if (pp == null && req != null) {
        pp = acceptsJson(req) ? "0" : "1";
      }
    }
    if ("1".equals(pp) || "true".equals(pp)) {
      gb.setPrettyPrinting();
    }
  }

  private static void enablePartialGetFields(GsonBuilder gb,
      Multimap<String, String> config) {
    final Set<String> want = Sets.newHashSet();
    for (String p : config.get("fields")) {
      Iterables.addAll(want, OptionUtil.splitOptionValue(p));
    }
    if (!want.isEmpty()) {
      gb.addSerializationExclusionStrategy(new ExclusionStrategy() {
        private final Map<String, String> names = Maps.newHashMap();

        @Override
        public boolean shouldSkipField(FieldAttributes field) {
          String name = names.get(field.getName());
          if (name == null) {
            // Names are supplied by Gson in terms of Java source.
            // Translate and cache the JSON lower_case_style used.
            try {
              name =
                  FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES.translateName(//
                      field.getDeclaringClass().getDeclaredField(field.getName()));
              names.put(field.getName(), name);
            } catch (SecurityException e) {
              return true;
            } catch (NoSuchFieldException e) {
              return true;
            }
          }
          return !want.contains(name);
        }

        @Override
        public boolean shouldSkipClass(Class<?> clazz) {
          return false;
        }
      });
    }
  }

  static void replyBinaryResult(
      @Nullable HttpServletRequest req,
      HttpServletResponse res,
      BinaryResult bin) throws IOException {
    final BinaryResult appResult = bin;
    try {
      if (bin.getAttachmentName() != null) {
        res.setHeader(
            "Content-Disposition",
            "attachment; filename=\"" + bin.getAttachmentName() + "\"");
      }
      if (bin.isBase64()) {
        bin = stackBase64(res, bin);
      }
      if (bin.canGzip() && acceptsGzip(req)) {
        bin = stackGzip(res, bin);
      }

      res.setContentType(bin.getContentType());
      long len = bin.getContentLength();
      if (0 <= len && len < Integer.MAX_VALUE) {
        res.setContentLength((int) len);
      } else if (0 <= len) {
        res.setHeader("Content-Length", Long.toString(len));
      }

      if (req == null || !"HEAD".equals(req.getMethod())) {
        OutputStream dst = res.getOutputStream();
        try {
          bin.writeTo(dst);
        } finally {
          dst.close();
        }
      }
    } finally {
      appResult.close();
    }
  }

  private static BinaryResult stackBase64(HttpServletResponse res,
      final BinaryResult src) throws IOException {
    BinaryResult b64;
    long len = src.getContentLength();
    if (0 <= len && len <= (7 << 20)) {
      b64 = base64(src);
    } else {
      b64 = new BinaryResult() {
        @Override
        public void writeTo(OutputStream out) throws IOException {
          try (OutputStreamWriter w = new OutputStreamWriter(
                new FilterOutputStream(out) {
                  @Override
                  public void close() {
                    // Do not close out, but only w and e.
                  }
                }, ISO_8859_1);
              OutputStream e = BaseEncoding.base64().encodingStream(w)) {
            src.writeTo(e);
          }
        }
      };
    }
    res.setHeader("X-FYI-Content-Encoding", "base64");
    res.setHeader("X-FYI-Content-Type", src.getContentType());
    return b64.setContentType("text/plain").setCharacterEncoding("ISO-8859-1");
  }

  private static BinaryResult stackGzip(HttpServletResponse res,
      final BinaryResult src) throws IOException {
    BinaryResult gz;
    long len = src.getContentLength();
    if (256 <= len && len <= (10 << 20)) {
      gz = compress(src);
      if (len <= gz.getContentLength()) {
        return src;
      }
    } else {
      gz = new BinaryResult() {
        @Override
        public void writeTo(OutputStream out) throws IOException {
          GZIPOutputStream gz = new GZIPOutputStream(out);
          src.writeTo(gz);
          gz.finish();
          gz.flush();
        }
      };
    }
    res.setHeader("Content-Encoding", "gzip");
    return gz.setContentType(src.getContentType());
  }

  private ViewData view(
      RestResource rsrc,
      RestCollection<RestResource, RestResource> rc,
      String method, List<IdString> path) throws AmbiguousViewException,
      RestApiException {
    DynamicMap<RestView<RestResource>> views = rc.views();
    final IdString projection = path.isEmpty()
        ? IdString.fromUrl("/")
        : path.remove(0);
    if (!path.isEmpty()) {
      // If there are path components still remaining after this projection
      // is chosen, look for the projection based upon GET as the method as
      // the client thinks it is a nested collection.
      method = "GET";
    } else if ("HEAD".equals(method)) {
      method = "GET";
    }

    List<String> p = splitProjection(projection);
    if (p.size() == 2) {
      String viewname = p.get(1);
      if (Strings.isNullOrEmpty(viewname)) {
        viewname = "/";
      }
      RestView<RestResource> view =
          views.get(p.get(0), method + "." + viewname);
      if (view != null) {
        return new ViewData(p.get(0), view);
      }
      view = views.get(p.get(0), "GET." + viewname);
      if (view != null) {
        if (view instanceof AcceptsPost && "POST".equals(method)) {
          @SuppressWarnings("unchecked")
          AcceptsPost<RestResource> ap = (AcceptsPost<RestResource>) view;
          return new ViewData(p.get(0), ap.post(rsrc));
        }
      }
      throw new ResourceNotFoundException(projection);
    }

    String name = method + "." + p.get(0);
    RestView<RestResource> core = views.get("gerrit", name);
    if (core != null) {
      return new ViewData(null, core);
    } else {
      core = views.get("gerrit", "GET." + p.get(0));
      if (core instanceof AcceptsPost && "POST".equals(method)) {
        @SuppressWarnings("unchecked")
        AcceptsPost<RestResource> ap = (AcceptsPost<RestResource>) core;
        return new ViewData(null, ap.post(rsrc));
      }
    }

    Map<String, RestView<RestResource>> r = Maps.newTreeMap();
    for (String plugin : views.plugins()) {
      RestView<RestResource> action = views.get(plugin, name);
      if (action != null) {
        r.put(plugin, action);
      }
    }

    if (r.size() == 1) {
      Map.Entry<String, RestView<RestResource>> entry =
          Iterables.getOnlyElement(r.entrySet());
      return new ViewData(entry.getKey(), entry.getValue());
    } else if (r.isEmpty()) {
      throw new ResourceNotFoundException(projection);
    } else {
      throw new AmbiguousViewException(String.format(
        "Projection %s is ambiguous: %s",
        name,
        Joiner.on(", ").join(
          Iterables.transform(r.keySet(), new Function<String, String>() {
            @Override
            public String apply(String in) {
              return in + "~" + projection;
            }
          }))));
    }
  }

  private static List<IdString> splitPath(HttpServletRequest req) {
    String path = req.getPathInfo();
    if (Strings.isNullOrEmpty(path)) {
      return Collections.emptyList();
    }
    List<IdString> out = Lists.newArrayList();
    for (String p : Splitter.on('/').split(path)) {
      out.add(IdString.fromUrl(p));
    }
    if (out.size() > 0 && out.get(out.size() - 1).isEmpty()) {
      out.remove(out.size() - 1);
    }
    return out;
  }

  private static List<String> splitProjection(IdString projection) {
    List<String> p = Lists.newArrayListWithCapacity(2);
    Iterables.addAll(p, Splitter.on('~').limit(2).split(projection.get()));
    return p;
  }

  private void checkUserSession(HttpServletRequest req)
      throws AuthException {
    CurrentUser user = globals.currentUser.get();
    if (isStateChange(req)) {
      if (user instanceof AnonymousUser) {
        throw new AuthException("Authentication required");
      } else if (!globals.webSession.get().isAccessPathOk(AccessPath.REST_API)) {
        throw new AuthException("Invalid authentication method. In order to authenticate, prefix the REST endpoint URL with /a/ (e.g. http://example.com/a/projects/).");
      }
    }
    user.setAccessPath(AccessPath.REST_API);
  }

  private static boolean isGetOrHead(HttpServletRequest req) {
    return "GET".equals(req.getMethod()) || "HEAD".equals(req.getMethod());
  }

  private static boolean isStateChange(HttpServletRequest req) {
    return !isGetOrHead(req);
  }

  private void checkRequiresCapability(ViewData viewData) throws AuthException {
    CapabilityUtils.checkRequiresCapability(globals.currentUser,
        viewData.pluginName, viewData.view.getClass());
  }

  private static void handleException(Throwable err, HttpServletRequest req,
      HttpServletResponse res) throws IOException {
    String uri = req.getRequestURI();
    if (!Strings.isNullOrEmpty(req.getQueryString())) {
      uri += "?" + req.getQueryString();
    }
    log.error(String.format("Error in %s %s", req.getMethod(), uri), err);

    if (!res.isCommitted()) {
      res.reset();
      replyError(req, res, SC_INTERNAL_SERVER_ERROR, "Internal server error");
    }
  }

  public static void replyError(HttpServletRequest req,
      HttpServletResponse res, int statusCode, String msg) throws IOException {
    replyError(req, res, statusCode, msg, CacheControl.NONE);
  }

  public static void replyError(HttpServletRequest req,
      HttpServletResponse res, int statusCode, String msg,
      CacheControl c) throws IOException {
    res.setStatus(statusCode);
    configureCaching(req, res, null, c);
    replyText(req, res, msg);
  }

  static void replyText(@Nullable HttpServletRequest req,
      HttpServletResponse res, String text) throws IOException {
    if ((req == null || isGetOrHead(req)) && isMaybeHTML(text)) {
      replyJson(req, res, ImmutableMultimap.of("pp", "0"), new JsonPrimitive(text));
    } else {
      if (!text.endsWith("\n")) {
        text += "\n";
      }
      replyBinaryResult(req, res,
          BinaryResult.create(text).setContentType("text/plain"));
    }
  }

  private static final Pattern IS_HTML = Pattern.compile("[<&]");
  private static boolean isMaybeHTML(String text) {
    return IS_HTML.matcher(text).find();
  }

  private static boolean acceptsJson(HttpServletRequest req) {
    return req != null && isType(JSON_TYPE, req.getHeader(HttpHeaders.ACCEPT));
  }

  private static boolean acceptsGzip(HttpServletRequest req) {
    if (req != null) {
      String accepts = req.getHeader(HttpHeaders.ACCEPT_ENCODING);
      return accepts != null && accepts.contains("gzip");
    }
    return false;
  }

  private static boolean isType(String expect, String given) {
    if (given == null) {
      return false;
    } else if (expect.equals(given)) {
      return true;
    } else if (given.startsWith(expect + ",")) {
      return true;
    }
    for (String p : given.split("[ ,;][ ,;]*")) {
      if (expect.equals(p)) {
        return true;
      }
    }
    return false;
  }

  private static BinaryResult base64(BinaryResult bin)
      throws IOException {
    int max = 4 * IntMath.divide((int) bin.getContentLength(), 3, CEILING);
    TemporaryBuffer.Heap buf = heap(max);
    OutputStream encoded = BaseEncoding.base64().encodingStream(
        new OutputStreamWriter(buf, ISO_8859_1));
    bin.writeTo(encoded);
    encoded.close();
    return asBinaryResult(buf);
  }

  private static BinaryResult compress(BinaryResult bin)
      throws IOException {
    TemporaryBuffer.Heap buf = heap(20 << 20);
    GZIPOutputStream gz = new GZIPOutputStream(buf);
    bin.writeTo(gz);
    gz.close();
    return asBinaryResult(buf).setContentType(bin.getContentType());
  }

  @SuppressWarnings("resource")
  private static BinaryResult asBinaryResult(final TemporaryBuffer.Heap buf) {
    return new BinaryResult() {
      @Override
      public void writeTo(OutputStream os) throws IOException {
        buf.writeTo(os, null);
      }
    }.setContentLength(buf.length());
  }

  private static Heap heap(int max) {
    return new TemporaryBuffer.Heap(max);
  }

  @SuppressWarnings("serial")
  private static class AmbiguousViewException extends Exception {
    AmbiguousViewException(String message) {
      super(message);
    }
  }

  private static class ViewData {
    String pluginName;
    RestView<RestResource> view;

    ViewData(String pluginName, RestView<RestResource> view) {
      this.pluginName = pluginName;
      this.view = view;
    }
  }
}
