// 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.plugins;

import static com.google.common.net.HttpHeaders.ACCESS_CONTROL_ALLOW_CREDENTIALS;
import static com.google.common.net.HttpHeaders.ACCESS_CONTROL_ALLOW_METHODS;
import static com.google.common.net.HttpHeaders.ACCESS_CONTROL_ALLOW_ORIGIN;
import static com.google.common.net.HttpHeaders.ORIGIN;
import static com.google.common.net.HttpHeaders.VARY;
import static com.google.gerrit.common.FileUtil.lastModified;
import static com.google.gerrit.server.plugins.PluginEntry.ATTR_CHARACTER_ENCODING;
import static com.google.gerrit.server.plugins.PluginEntry.ATTR_CONTENT_TYPE;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.stream.Collectors.toList;

import com.google.common.base.CharMatcher;
import com.google.common.base.Joiner;
import com.google.common.base.Splitter;
import com.google.common.base.Strings;
import com.google.common.cache.Cache;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.io.ByteStreams;
import com.google.common.net.HttpHeaders;
import com.google.gerrit.extensions.registration.RegistrationHandle;
import com.google.gerrit.httpd.resources.Resource;
import com.google.gerrit.httpd.resources.ResourceKey;
import com.google.gerrit.httpd.resources.SmallResource;
import com.google.gerrit.httpd.restapi.RestApiServlet;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.documentation.MarkdownFormatter;
import com.google.gerrit.server.mime.MimeUtilFileTypeRegistry;
import com.google.gerrit.server.plugins.Plugin;
import com.google.gerrit.server.plugins.Plugin.ApiType;
import com.google.gerrit.server.plugins.PluginContentScanner;
import com.google.gerrit.server.plugins.PluginEntry;
import com.google.gerrit.server.plugins.PluginsCollection;
import com.google.gerrit.server.plugins.ReloadPluginListener;
import com.google.gerrit.server.plugins.StartPluginListener;
import com.google.gerrit.server.ssh.SshInfo;
import com.google.gerrit.util.http.RequestUtil;
import com.google.gwtexpui.server.CacheHeaders;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.name.Named;
import com.google.inject.servlet.GuiceFilter;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Predicate;
import java.util.jar.Attributes;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.servlet.FilterChain;
import javax.servlet.ServletConfig;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang.StringUtils;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

@Singleton
class HttpPluginServlet extends HttpServlet implements StartPluginListener, ReloadPluginListener {
  private static final int SMALL_RESOURCE = 128 * 1024;
  private static final long serialVersionUID = 1L;
  private static final Logger log = LoggerFactory.getLogger(HttpPluginServlet.class);

  private final MimeUtilFileTypeRegistry mimeUtil;
  private final Provider<String> webUrl;
  private final Cache<ResourceKey, Resource> resourceCache;
  private final String sshHost;
  private final int sshPort;
  private final RestApiServlet managerApi;

  private List<Plugin> pending = new ArrayList<>();
  private ContextMapper wrapper;
  private final ConcurrentMap<String, PluginHolder> plugins = Maps.newConcurrentMap();
  private final Pattern allowOrigin;

  @Inject
  HttpPluginServlet(
      MimeUtilFileTypeRegistry mimeUtil,
      @CanonicalWebUrl Provider<String> webUrl,
      @Named(HttpPluginModule.PLUGIN_RESOURCES) Cache<ResourceKey, Resource> cache,
      SshInfo sshInfo,
      RestApiServlet.Globals globals,
      PluginsCollection plugins,
      @GerritServerConfig Config cfg) {
    this.mimeUtil = mimeUtil;
    this.webUrl = webUrl;
    this.resourceCache = cache;
    this.managerApi = new RestApiServlet(globals, plugins);

    String sshHost = "review.example.com";
    int sshPort = 29418;
    if (!sshInfo.getHostKeys().isEmpty()) {
      String host = sshInfo.getHostKeys().get(0).getHost();
      int c = host.lastIndexOf(':');
      if (0 <= c) {
        sshHost = host.substring(0, c);
        sshPort = Integer.parseInt(host.substring(c + 1));
      } else {
        sshHost = host;
        sshPort = 22;
      }
    }
    this.sshHost = sshHost;
    this.sshPort = sshPort;
    this.allowOrigin = makeAllowOrigin(cfg);
  }

  @Override
  public synchronized void init(ServletConfig config) throws ServletException {
    super.init(config);

    wrapper = new ContextMapper(config.getServletContext().getContextPath());
    for (Plugin plugin : pending) {
      install(plugin);
    }
    pending = null;
  }

  @Override
  public synchronized void onStartPlugin(Plugin plugin) {
    if (pending != null) {
      pending.add(plugin);
    } else {
      install(plugin);
    }
  }

  @Override
  public void onReloadPlugin(Plugin oldPlugin, Plugin newPlugin) {
    install(newPlugin);
  }

  private void install(Plugin plugin) {
    GuiceFilter filter = load(plugin);
    final String name = plugin.getName();
    final PluginHolder holder = new PluginHolder(plugin, filter);
    plugin.add(
        new RegistrationHandle() {
          @Override
          public void remove() {
            plugins.remove(name, holder);
          }
        });
    plugins.put(name, holder);
  }

  private GuiceFilter load(Plugin plugin) {
    if (plugin.getHttpInjector() != null) {
      final String name = plugin.getName();
      final GuiceFilter filter;
      try {
        filter = plugin.getHttpInjector().getInstance(GuiceFilter.class);
      } catch (RuntimeException e) {
        log.warn("Plugin {} cannot load GuiceFilter", name, e);
        return null;
      }

      try {
        ServletContext ctx = PluginServletContext.create(plugin, wrapper.getFullPath(name));
        filter.init(new WrappedFilterConfig(ctx));
      } catch (ServletException e) {
        log.warn("Plugin {} failed to initialize HTTP", name, e);
        return null;
      }

      plugin.add(
          new RegistrationHandle() {
            @Override
            public void remove() {
              filter.destroy();
            }
          });
      return filter;
    }
    return null;
  }

  @Override
  public void service(HttpServletRequest req, HttpServletResponse res)
      throws IOException, ServletException {
    List<String> parts =
        Lists.newArrayList(
            Splitter.on('/')
                .limit(3)
                .omitEmptyStrings()
                .split(Strings.nullToEmpty(RequestUtil.getEncodedPathInfo(req))));

    if (isApiCall(req, parts)) {
      managerApi.service(req, res);
      return;
    }

    String name = parts.get(0);
    final PluginHolder holder = plugins.get(name);
    if (holder == null) {
      CacheHeaders.setNotCacheable(res);
      res.sendError(HttpServletResponse.SC_NOT_FOUND);
      return;
    }

    HttpServletRequest wr = wrapper.create(req, name);
    FilterChain chain =
        new FilterChain() {
          @Override
          public void doFilter(ServletRequest req, ServletResponse res) throws IOException {
            onDefault(holder, (HttpServletRequest) req, (HttpServletResponse) res);
          }
        };
    if (holder.filter != null) {
      holder.filter.doFilter(wr, res, chain);
    } else {
      chain.doFilter(wr, res);
    }
  }

  private static boolean isApiCall(HttpServletRequest req, List<String> parts) {
    String method = req.getMethod();
    int cnt = parts.size();
    return cnt == 0
        || (cnt == 1 && ("PUT".equals(method) || "DELETE".equals(method)))
        || (cnt == 2 && parts.get(1).startsWith("gerrit~"));
  }

  private void onDefault(PluginHolder holder, HttpServletRequest req, HttpServletResponse res)
      throws IOException {
    if (!"GET".equals(req.getMethod()) && !"HEAD".equals(req.getMethod())) {
      CacheHeaders.setNotCacheable(res);
      res.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
      return;
    }

    String pathInfo = RequestUtil.getEncodedPathInfo(req);
    if (pathInfo.length() < 1) {
      Resource.NOT_FOUND.send(req, res);
      return;
    }

    checkCors(req, res);

    String file = pathInfo.substring(1);
    PluginResourceKey key = PluginResourceKey.create(holder.plugin, file);
    Resource rsc = resourceCache.getIfPresent(key);
    if (rsc != null && req.getHeader(HttpHeaders.IF_MODIFIED_SINCE) == null) {
      rsc.send(req, res);
      return;
    }

    String uri = req.getRequestURI();
    if ("".equals(file)) {
      res.sendRedirect(uri + holder.docPrefix + "index.html");
      return;
    }

    if (file.startsWith(holder.staticPrefix)) {
      if (holder.plugin.getApiType() == ApiType.JS) {
        sendJsPlugin(holder.plugin, key, req, res);
      } else {
        PluginContentScanner scanner = holder.plugin.getContentScanner();
        Optional<PluginEntry> entry = scanner.getEntry(file);
        if (entry.isPresent()) {
          if (hasUpToDateCachedResource(rsc, entry.get().getTime())) {
            rsc.send(req, res);
          } else {
            sendResource(scanner, entry.get(), key, res);
          }
        } else {
          resourceCache.put(key, Resource.NOT_FOUND);
          Resource.NOT_FOUND.send(req, res);
        }
      }
    } else if (file.equals(holder.docPrefix.substring(0, holder.docPrefix.length() - 1))) {
      res.sendRedirect(uri + "/index.html");
    } else if (file.startsWith(holder.docPrefix) && file.endsWith("/")) {
      res.sendRedirect(uri + "index.html");
    } else if (file.startsWith(holder.docPrefix)) {
      PluginContentScanner scanner = holder.plugin.getContentScanner();
      Optional<PluginEntry> entry = scanner.getEntry(file);
      if (!entry.isPresent()) {
        entry = findSource(scanner, file);
      }
      if (!entry.isPresent() && file.endsWith("/index.html")) {
        String pfx = file.substring(0, file.length() - "index.html".length());
        long pluginLastModified = lastModified(holder.plugin.getSrcFile());
        if (hasUpToDateCachedResource(rsc, pluginLastModified)) {
          rsc.send(req, res);
        } else {
          sendAutoIndex(scanner, pfx, holder.plugin.getName(), key, res, pluginLastModified);
        }
      } else if (entry.isPresent() && entry.get().getName().endsWith(".md")) {
        if (hasUpToDateCachedResource(rsc, entry.get().getTime())) {
          rsc.send(req, res);
        } else {
          sendMarkdownAsHtml(scanner, entry.get(), holder.plugin.getName(), key, res);
        }
      } else if (entry.isPresent()) {
        if (hasUpToDateCachedResource(rsc, entry.get().getTime())) {
          rsc.send(req, res);
        } else {
          sendResource(scanner, entry.get(), key, res);
        }
      } else {
        resourceCache.put(key, Resource.NOT_FOUND);
        Resource.NOT_FOUND.send(req, res);
      }
    } else {
      resourceCache.put(key, Resource.NOT_FOUND);
      Resource.NOT_FOUND.send(req, res);
    }
  }

  private static Pattern makeAllowOrigin(Config cfg) {
    String[] allow = cfg.getStringList("site", null, "allowOriginRegex");
    if (allow.length > 0) {
      return Pattern.compile(Joiner.on('|').join(allow));
    }
    return null;
  }

  private void checkCors(HttpServletRequest req, HttpServletResponse res) {
    String origin = req.getHeader(ORIGIN);
    if (!Strings.isNullOrEmpty(origin) && isOriginAllowed(origin)) {
      res.addHeader(VARY, ORIGIN);
      setCorsHeaders(res, origin);
    }
  }

  private void setCorsHeaders(HttpServletResponse res, String origin) {
    res.setHeader(ACCESS_CONTROL_ALLOW_ORIGIN, origin);
    res.setHeader(ACCESS_CONTROL_ALLOW_CREDENTIALS, "true");
    res.setHeader(ACCESS_CONTROL_ALLOW_METHODS, "GET, HEAD");
  }

  private boolean isOriginAllowed(String origin) {
    return allowOrigin == null || allowOrigin.matcher(origin).matches();
  }

  private boolean hasUpToDateCachedResource(Resource cachedResource, long lastUpdateTime) {
    return cachedResource != null && cachedResource.isUnchanged(lastUpdateTime);
  }

  private void appendEntriesSection(
      PluginContentScanner scanner,
      List<PluginEntry> entries,
      String sectionTitle,
      StringBuilder md,
      String prefix,
      int nameOffset)
      throws IOException {
    if (!entries.isEmpty()) {
      md.append("## ").append(sectionTitle).append(" ##\n");
      for (PluginEntry entry : entries) {
        String rsrc = entry.getName().substring(prefix.length());
        String entryTitle;
        if (rsrc.endsWith(".html")) {
          entryTitle = rsrc.substring(nameOffset, rsrc.length() - 5).replace('-', ' ');
        } else if (rsrc.endsWith(".md")) {
          entryTitle = extractTitleFromMarkdown(scanner, entry);
          if (Strings.isNullOrEmpty(entryTitle)) {
            entryTitle = rsrc.substring(nameOffset, rsrc.length() - 3).replace('-', ' ');
          }
        } else {
          entryTitle = rsrc.substring(nameOffset).replace('-', ' ');
        }
        md.append(String.format("* [%s](%s)\n", entryTitle, rsrc));
      }
      md.append("\n");
    }
  }

  private void sendAutoIndex(
      PluginContentScanner scanner,
      final String prefix,
      final String pluginName,
      PluginResourceKey cacheKey,
      HttpServletResponse res,
      long lastModifiedTime)
      throws IOException {
    List<PluginEntry> cmds = new ArrayList<>();
    List<PluginEntry> servlets = new ArrayList<>();
    List<PluginEntry> restApis = new ArrayList<>();
    List<PluginEntry> docs = new ArrayList<>();
    PluginEntry about = null;

    Predicate<PluginEntry> filter =
        entry -> {
          String name = entry.getName();
          Optional<Long> size = entry.getSize();
          if (name.startsWith(prefix)
              && (name.endsWith(".md") || name.endsWith(".html"))
              && size.isPresent()) {
            if (size.get() <= 0 || size.get() > SMALL_RESOURCE) {
              log.warn(
                  "Plugin {}: {} omitted from document index. Size {} out of range (0,{}).",
                  pluginName,
                  name.substring(prefix.length()),
                  size.get(),
                  SMALL_RESOURCE);
              return false;
            }
            return true;
          }
          return false;
        };

    List<PluginEntry> entries =
        Collections.list(scanner.entries()).stream().filter(filter).collect(toList());
    for (PluginEntry entry : entries) {
      String name = entry.getName().substring(prefix.length());
      if (name.startsWith("cmd-")) {
        cmds.add(entry);
      } else if (name.startsWith("servlet-")) {
        servlets.add(entry);
      } else if (name.startsWith("rest-api-")) {
        restApis.add(entry);
      } else if (name.startsWith("about.")) {
        if (about == null) {
          about = entry;
        } else {
          log.warn(
              "Plugin {}: Multiple 'about' documents found; using {}",
              pluginName,
              about.getName().substring(prefix.length()));
        }
      } else {
        docs.add(entry);
      }
    }

    Collections.sort(cmds, PluginEntry.COMPARATOR_BY_NAME);
    Collections.sort(docs, PluginEntry.COMPARATOR_BY_NAME);

    StringBuilder md = new StringBuilder();
    md.append(String.format("# Plugin %s #\n", pluginName));
    md.append("\n");
    appendPluginInfoTable(md, scanner.getManifest().getMainAttributes());

    if (about != null) {
      InputStreamReader isr = new InputStreamReader(scanner.getInputStream(about), UTF_8);
      StringBuilder aboutContent = new StringBuilder();
      try (BufferedReader reader = new BufferedReader(isr)) {
        String line;
        while ((line = reader.readLine()) != null) {
          line = StringUtils.stripEnd(line, null);
          if (line.isEmpty()) {
            aboutContent.append("\n");
          } else {
            aboutContent.append(line).append("\n");
          }
        }
      }

      // Only append the About section if there was anything in it
      if (aboutContent.toString().trim().length() > 0) {
        md.append("## About ##\n");
        md.append("\n").append(aboutContent);
      }
    }

    appendEntriesSection(scanner, docs, "Documentation", md, prefix, 0);
    appendEntriesSection(scanner, servlets, "Servlets", md, prefix, "servlet-".length());
    appendEntriesSection(scanner, restApis, "REST APIs", md, prefix, "rest-api-".length());
    appendEntriesSection(scanner, cmds, "Commands", md, prefix, "cmd-".length());

    sendMarkdownAsHtml(md.toString(), pluginName, cacheKey, res, lastModifiedTime);
  }

  private void sendMarkdownAsHtml(
      String md,
      String pluginName,
      PluginResourceKey cacheKey,
      HttpServletResponse res,
      long lastModifiedTime)
      throws UnsupportedEncodingException, IOException {
    Map<String, String> macros = new HashMap<>();
    macros.put("PLUGIN", pluginName);
    macros.put("SSH_HOST", sshHost);
    macros.put("SSH_PORT", "" + sshPort);
    String url = webUrl.get();
    if (Strings.isNullOrEmpty(url)) {
      url = "http://review.example.com/";
    }
    macros.put("URL", url);

    Matcher m = Pattern.compile("(\\\\)?@([A-Z_]+)@").matcher(md);
    StringBuffer sb = new StringBuffer();
    while (m.find()) {
      String key = m.group(2);
      String val = macros.get(key);
      if (m.group(1) != null) {
        m.appendReplacement(sb, "@" + key + "@");
      } else if (val != null) {
        m.appendReplacement(sb, val);
      } else {
        m.appendReplacement(sb, "@" + key + "@");
      }
    }
    m.appendTail(sb);

    byte[] html = new MarkdownFormatter().markdownToDocHtml(sb.toString(), UTF_8.name());
    resourceCache.put(
        cacheKey,
        new SmallResource(html)
            .setContentType("text/html")
            .setCharacterEncoding(UTF_8.name())
            .setLastModified(lastModifiedTime));
    res.setContentType("text/html");
    res.setCharacterEncoding(UTF_8.name());
    res.setContentLength(html.length);
    res.setDateHeader("Last-Modified", lastModifiedTime);
    res.getOutputStream().write(html);
  }

  private static void appendPluginInfoTable(StringBuilder html, Attributes main) {
    if (main != null) {
      String t = main.getValue(Attributes.Name.IMPLEMENTATION_TITLE);
      String n = main.getValue(Attributes.Name.IMPLEMENTATION_VENDOR);
      String v = main.getValue(Attributes.Name.IMPLEMENTATION_VERSION);
      String a = main.getValue("Gerrit-ApiVersion");

      html.append("<table class=\"plugin_info\">");
      if (!Strings.isNullOrEmpty(t)) {
        html.append("<tr><th>Name</th><td>").append(t).append("</td></tr>\n");
      }
      if (!Strings.isNullOrEmpty(n)) {
        html.append("<tr><th>Vendor</th><td>").append(n).append("</td></tr>\n");
      }
      if (!Strings.isNullOrEmpty(v)) {
        html.append("<tr><th>Version</th><td>").append(v).append("</td></tr>\n");
      }
      if (!Strings.isNullOrEmpty(a)) {
        html.append("<tr><th>API Version</th><td>").append(a).append("</td></tr>\n");
      }
      html.append("</table>\n");
    }
  }

  private static String extractTitleFromMarkdown(PluginContentScanner scanner, PluginEntry entry)
      throws IOException {
    String charEnc = null;
    Map<Object, String> atts = entry.getAttrs();
    if (atts != null) {
      charEnc = Strings.emptyToNull(atts.get(ATTR_CHARACTER_ENCODING));
    }
    if (charEnc == null) {
      charEnc = UTF_8.name();
    }
    return new MarkdownFormatter()
        .extractTitleFromMarkdown(readWholeEntry(scanner, entry), charEnc);
  }

  private static Optional<PluginEntry> findSource(PluginContentScanner scanner, String file)
      throws IOException {
    if (file.endsWith(".html")) {
      int d = file.lastIndexOf('.');
      return scanner.getEntry(file.substring(0, d) + ".md");
    }
    return Optional.empty();
  }

  private void sendMarkdownAsHtml(
      PluginContentScanner scanner,
      PluginEntry entry,
      String pluginName,
      PluginResourceKey key,
      HttpServletResponse res)
      throws IOException {
    byte[] rawmd = readWholeEntry(scanner, entry);
    String encoding = null;
    Map<Object, String> atts = entry.getAttrs();
    if (atts != null) {
      encoding = Strings.emptyToNull(atts.get(ATTR_CHARACTER_ENCODING));
    }

    String txtmd =
        RawParseUtils.decode(Charset.forName(encoding != null ? encoding : UTF_8.name()), rawmd);
    long time = entry.getTime();
    if (0 < time) {
      res.setDateHeader("Last-Modified", time);
    }
    sendMarkdownAsHtml(txtmd, pluginName, key, res, time);
  }

  private void sendResource(
      PluginContentScanner scanner,
      PluginEntry entry,
      PluginResourceKey key,
      HttpServletResponse res)
      throws IOException {
    byte[] data = null;
    Optional<Long> size = entry.getSize();
    if (size.isPresent() && size.get() <= SMALL_RESOURCE) {
      data = readWholeEntry(scanner, entry);
    }

    String contentType = null;
    String charEnc = null;
    Map<Object, String> atts = entry.getAttrs();
    if (atts != null) {
      contentType = Strings.emptyToNull(atts.get(ATTR_CONTENT_TYPE));
      charEnc = Strings.emptyToNull(atts.get(ATTR_CHARACTER_ENCODING));
    }
    if (contentType == null) {
      contentType = mimeUtil.getMimeType(entry.getName(), data).toString();
      if ("application/octet-stream".equals(contentType) && entry.getName().endsWith(".js")) {
        contentType = "application/javascript";
      } else if ("application/x-pointplus".equals(contentType)
          && entry.getName().endsWith(".css")) {
        contentType = "text/css";
      }
    }

    long time = entry.getTime();
    if (0 < time) {
      res.setDateHeader("Last-Modified", time);
    }
    if (size.isPresent()) {
      res.setHeader("Content-Length", size.get().toString());
    }
    res.setContentType(contentType);
    if (charEnc != null) {
      res.setCharacterEncoding(charEnc);
    }
    if (data != null) {
      resourceCache.put(
          key,
          new SmallResource(data)
              .setContentType(contentType)
              .setCharacterEncoding(charEnc)
              .setLastModified(time));
      res.getOutputStream().write(data);
    } else {
      writeToResponse(res, scanner.getInputStream(entry));
    }
  }

  private void sendJsPlugin(
      Plugin plugin, PluginResourceKey key, HttpServletRequest req, HttpServletResponse res)
      throws IOException {
    Path path = plugin.getSrcFile();
    if (req.getRequestURI().endsWith(getJsPluginPath(plugin)) && Files.exists(path)) {
      res.setHeader("Content-Length", Long.toString(Files.size(path)));
      if (path.toString().toLowerCase(Locale.US).endsWith(".html")) {
        res.setContentType("text/html");
      } else {
        res.setContentType("application/javascript");
      }
      writeToResponse(res, Files.newInputStream(path));
    } else {
      resourceCache.put(key, Resource.NOT_FOUND);
      Resource.NOT_FOUND.send(req, res);
    }
  }

  private static String getJsPluginPath(Plugin plugin) {
    return String.format(
        "/plugins/%s/static/%s", plugin.getName(), plugin.getSrcFile().getFileName());
  }

  private void writeToResponse(HttpServletResponse res, InputStream inputStream)
      throws IOException {
    try (OutputStream out = res.getOutputStream();
        InputStream in = inputStream) {
      ByteStreams.copy(in, out);
    }
  }

  private static byte[] readWholeEntry(PluginContentScanner scanner, PluginEntry entry)
      throws IOException {
    try (InputStream in = scanner.getInputStream(entry)) {
      return IO.readWholeStream(in, entry.getSize().get().intValue()).array();
    }
  }

  private static class PluginHolder {
    final Plugin plugin;
    final GuiceFilter filter;
    final String staticPrefix;
    final String docPrefix;

    PluginHolder(Plugin plugin, GuiceFilter filter) {
      this.plugin = plugin;
      this.filter = filter;
      this.staticPrefix = getPrefix(plugin, "Gerrit-HttpStaticPrefix", "static/");
      this.docPrefix = getPrefix(plugin, "Gerrit-HttpDocumentationPrefix", "Documentation/");
    }

    private static String getPrefix(Plugin plugin, String attr, String def) {
      Path path = plugin.getSrcFile();
      PluginContentScanner scanner = plugin.getContentScanner();
      if (path == null || scanner == PluginContentScanner.EMPTY) {
        return def;
      }
      try {
        String prefix = scanner.getManifest().getMainAttributes().getValue(attr);
        if (prefix != null) {
          return CharMatcher.is('/').trimFrom(prefix) + "/";
        }
        return def;
      } catch (IOException e) {
        log.warn("Error getting {} for plugin {}, using default", attr, plugin.getName(), e);
        return null;
      }
    }
  }
}
