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

import static com.google.gerrit.extensions.registration.PrivateInternals_DynamicTypes.dynamicItemsOf;
import static com.google.gerrit.extensions.registration.PrivateInternals_DynamicTypes.dynamicMapsOf;
import static com.google.gerrit.extensions.registration.PrivateInternals_DynamicTypes.dynamicSetsOf;
import static java.util.Objects.requireNonNull;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.UsedAt;
import com.google.gerrit.extensions.annotations.RootRelative;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.extensions.registration.DynamicItem;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.registration.PrivateInternals_DynamicMapImpl;
import com.google.gerrit.extensions.registration.PrivateInternals_DynamicTypes;
import com.google.gerrit.extensions.registration.RegistrationHandle;
import com.google.gerrit.extensions.registration.ReloadableRegistrationHandle;
import com.google.gerrit.extensions.systemstatus.ServerInformation;
import com.google.gerrit.extensions.webui.WebUiPlugin;
import com.google.gerrit.index.IndexCollection;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.server.util.PluginRequestContext;
import com.google.gerrit.server.util.RequestContext;
import com.google.gerrit.server.util.ThreadLocalRequestContext;
import com.google.inject.AbstractModule;
import com.google.inject.Binding;
import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Key;
import com.google.inject.Module;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import com.google.inject.TypeLiteral;
import com.google.inject.internal.UniqueAnnotations;
import com.google.inject.util.Modules;
import java.lang.annotation.Annotation;
import java.lang.reflect.ParameterizedType;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * Tracks Guice bindings that should be exposed to loaded plugins.
 *
 * <p>This is an internal implementation detail of how the main server is able to export its
 * explicit Guice bindings to tightly coupled plugins, giving them access to singletons and request
 * scoped resources just like any core code.
 */
@Singleton
public class PluginGuiceEnvironment {
  private final Injector sysInjector;
  private final ServerInformation srvInfo;
  private final ThreadLocalRequestContext local;
  private final CopyConfigModule copyConfigModule;
  private final Set<Key<?>> copyConfigKeys;
  private final List<StartPluginListener> onStart;
  private final List<StopPluginListener> onStop;
  private final List<ReloadPluginListener> onReload;
  private final MetricMaker serverMetrics;

  private Module sysModule;
  private Module sshModule;
  private Module httpModule;
  private Injector apiInjector;

  private Provider<ModuleGenerator> sshGen;
  private Provider<ModuleGenerator> httpGen;

  private Map<TypeLiteral<?>, DynamicItem<?>> sysItems;
  private Map<TypeLiteral<?>, DynamicItem<?>> sshItems;
  private Map<TypeLiteral<?>, DynamicItem<?>> httpItems;
  private Map<TypeLiteral<?>, DynamicItem<?>> apiItems;

  private Map<TypeLiteral<?>, DynamicSet<?>> sysSets;
  private Map<TypeLiteral<?>, DynamicSet<?>> sshSets;
  private Map<TypeLiteral<?>, DynamicSet<?>> httpSets;
  private Map<TypeLiteral<?>, DynamicSet<?>> apiSets;

  private Map<TypeLiteral<?>, DynamicMap<?>> sysMaps;
  private Map<TypeLiteral<?>, DynamicMap<?>> sshMaps;
  private Map<TypeLiteral<?>, DynamicMap<?>> httpMaps;
  private Map<TypeLiteral<?>, DynamicMap<?>> apiMaps;

  @Inject
  PluginGuiceEnvironment(
      Injector sysInjector,
      ThreadLocalRequestContext local,
      ServerInformation srvInfo,
      CopyConfigModule ccm,
      MetricMaker serverMetrics) {
    this.sysInjector = sysInjector;
    this.srvInfo = srvInfo;
    this.local = local;
    this.copyConfigModule = ccm;
    this.copyConfigKeys = Guice.createInjector(ccm).getAllBindings().keySet();
    this.serverMetrics = serverMetrics;

    onStart = new CopyOnWriteArrayList<>();
    onStart.addAll(listeners(sysInjector, StartPluginListener.class));

    onStop = new CopyOnWriteArrayList<>();
    onStop.addAll(listeners(sysInjector, StopPluginListener.class));

    onReload = new CopyOnWriteArrayList<>();
    onReload.addAll(listeners(sysInjector, ReloadPluginListener.class));

    sysItems = dynamicItemsOf(sysInjector);
    sysSets = dynamicSetsOf(sysInjector);
    sysMaps = dynamicMapsOf(sysInjector);

    apiSets = new HashMap<>();
    apiItems = new HashMap<>();
    apiMaps = new HashMap<>();
  }

  ServerInformation getServerInformation() {
    return srvInfo;
  }

  MetricMaker getServerMetrics() {
    return serverMetrics;
  }

  boolean hasDynamicItem(TypeLiteral<?> type) {
    return sysItems.containsKey(type)
        || (sshItems != null && sshItems.containsKey(type))
        || (httpItems != null && httpItems.containsKey(type));
  }

  boolean hasDynamicSet(TypeLiteral<?> type) {
    return sysSets.containsKey(type)
        || (sshSets != null && sshSets.containsKey(type))
        || (httpSets != null && httpSets.containsKey(type));
  }

  boolean hasDynamicMap(TypeLiteral<?> type) {
    return sysMaps.containsKey(type)
        || (sshMaps != null && sshMaps.containsKey(type))
        || (httpMaps != null && httpMaps.containsKey(type));
  }

  public Module getSysModule() {
    return sysModule;
  }

  public void setDbCfgInjector(Injector dbInjector, Injector cfgInjector) {
    final Module db = copy(dbInjector);
    final Module cm = copy(cfgInjector);
    final Module sm = copy(sysInjector);
    sysModule = Modules.combine(copyConfigModule, db, cm, sm);
  }

  public void setSshInjector(Injector injector) {
    sshModule = copy(injector);
    sshGen = injector.getProvider(ModuleGenerator.class);
    sshItems = dynamicItemsOf(injector);
    sshSets = dynamicSetsOf(injector);
    sshMaps = dynamicMapsOf(injector);
    onStart.addAll(listeners(injector, StartPluginListener.class));
    onStop.addAll(listeners(injector, StopPluginListener.class));
    onReload.addAll(listeners(injector, ReloadPluginListener.class));
  }

  boolean hasSshModule() {
    return sshModule != null;
  }

  Module getSshModule() {
    return sshModule;
  }

  ModuleGenerator newSshModuleGenerator() {
    return sshGen.get();
  }

  public void setHttpInjector(Injector injector) {
    httpModule = copy(injector);
    httpGen = injector.getProvider(ModuleGenerator.class);
    httpItems = dynamicItemsOf(injector);
    httpSets = httpDynamicSetsOf(injector);
    httpMaps = dynamicMapsOf(injector);
    onStart.addAll(listeners(injector, StartPluginListener.class));
    onStop.addAll(listeners(injector, StopPluginListener.class));
    onReload.addAll(listeners(injector, ReloadPluginListener.class));
  }

  private Map<TypeLiteral<?>, DynamicSet<?>> httpDynamicSetsOf(Injector i) {
    // Copy binding of DynamicSet<WebUiPlugin> from sysInjector to HTTP.
    // This supports older plugins that bound a plugin in the HttpModule.
    TypeLiteral<WebUiPlugin> key = TypeLiteral.get(WebUiPlugin.class);
    DynamicSet<?> web = sysSets.get(key);
    requireNonNull(web, "DynamicSet<WebUiPlugin> exists in sysInjector");

    Map<TypeLiteral<?>, DynamicSet<?>> m = new HashMap<>(dynamicSetsOf(i));
    m.put(key, web);
    return Collections.unmodifiableMap(m);
  }

  boolean hasHttpModule() {
    return httpModule != null;
  }

  @UsedAt(UsedAt.Project.GOOGLE)
  public Module getHttpModule() {
    return httpModule;
  }

  ModuleGenerator newHttpModuleGenerator() {
    return httpGen.get();
  }

  public RequestContext enter(Plugin plugin) {
    return local.setContext(new PluginRequestContext(plugin.getPluginUser()));
  }

  public void exit(RequestContext old) {
    @SuppressWarnings("unused")
    var unused = local.setContext(old);
  }

  public void onStartPlugin(Plugin plugin) {
    RequestContext oldContext = enter(plugin);
    try {
      attachItem(sysItems, plugin.getSysInjector(), plugin);
      attachItem(sshItems, plugin.getSshInjector(), plugin);
      attachItem(httpItems, plugin.getHttpInjector(), plugin);

      attachSet(sysSets, plugin.getSysInjector(), plugin);
      attachSet(sshSets, plugin.getSshInjector(), plugin);
      attachSet(httpSets, plugin.getHttpInjector(), plugin);

      attachMap(sysMaps, plugin.getSysInjector(), plugin);
      attachMap(sshMaps, plugin.getSshInjector(), plugin);
      attachMap(httpMaps, plugin.getHttpInjector(), plugin);

      apiInjector = Optional.ofNullable(plugin.getApiInjector()).orElse(apiInjector);

      if (apiInjector != null) {
        apiItems.putAll(dynamicItemsOf(apiInjector));
        apiSets.putAll(dynamicSetsOf(apiInjector));
        apiMaps.putAll(dynamicMapsOf(apiInjector));

        ImmutableList<Injector> allPluginInjectors =
            listOfInjectors(
                plugin.getSysInjector(), plugin.getSshInjector(), plugin.getHttpInjector());
        allPluginInjectors.forEach(i -> attachItem(apiItems, i, plugin));
        allPluginInjectors.forEach(i -> attachSet(apiSets, i, plugin));
        allPluginInjectors.forEach(i -> attachMap(apiMaps, i, plugin));
      }
    } finally {
      exit(oldContext);
    }

    for (StartPluginListener l : onStart) {
      l.onStartPlugin(plugin);
    }
  }

  private ImmutableList<Injector> listOfInjectors(Injector... injectors) {
    ImmutableList.Builder<Injector> injectorsListBuilder = ImmutableList.builder();

    for (Injector injector : injectors) {
      if (injector != null) {
        injectorsListBuilder.add(injector);
      }
    }

    return injectorsListBuilder.build();
  }

  public void onStopPlugin(Plugin plugin) {
    for (StopPluginListener l : onStop) {
      l.onStopPlugin(plugin);
    }
  }

  private void attachItem(
      Map<TypeLiteral<?>, DynamicItem<?>> items, @Nullable Injector src, Plugin plugin) {
    for (RegistrationHandle h :
        PrivateInternals_DynamicTypes.attachItems(src, plugin.getName(), items)) {
      plugin.add(h);
    }
  }

  private void attachSet(
      Map<TypeLiteral<?>, DynamicSet<?>> sets, @Nullable Injector src, Plugin plugin) {
    for (RegistrationHandle h :
        PrivateInternals_DynamicTypes.attachSets(src, plugin.getName(), sets)) {
      plugin.add(h);
    }
  }

  private void attachMap(
      Map<TypeLiteral<?>, DynamicMap<?>> maps, @Nullable Injector src, Plugin plugin) {
    for (RegistrationHandle h :
        PrivateInternals_DynamicTypes.attachMaps(src, plugin.getName(), maps)) {
      plugin.add(h);
    }
  }

  void onReloadPlugin(Plugin oldPlugin, Plugin newPlugin) {
    // Index all old registrations by the raw type. These may be replaced
    // during the reattach calls below. Any that are not replaced will be
    // removed when the old plugin does its stop routine.
    ListMultimap<TypeLiteral<?>, ReloadableRegistrationHandle<?>> old = LinkedListMultimap.create();
    for (ReloadableRegistrationHandle<?> h : oldPlugin.getReloadableHandles()) {
      old.put(h.getKey().getTypeLiteral(), h);
    }

    RequestContext oldContext = enter(newPlugin);
    try {
      Optional.ofNullable(newPlugin.getApiInjector())
          .ifPresent(i -> reattachMap(old, apiMaps, i, newPlugin));
      reattachMap(old, sysMaps, newPlugin.getSysInjector(), newPlugin);
      reattachMap(old, sshMaps, newPlugin.getSshInjector(), newPlugin);
      reattachMap(old, httpMaps, newPlugin.getHttpInjector(), newPlugin);

      Optional.ofNullable(newPlugin.getApiInjector())
          .ifPresent(i -> reattachSet(old, apiSets, i, newPlugin));
      reattachSet(old, sysSets, newPlugin.getSysInjector(), newPlugin);
      reattachSet(old, sshSets, newPlugin.getSshInjector(), newPlugin);
      reattachSet(old, httpSets, newPlugin.getHttpInjector(), newPlugin);

      Optional.ofNullable(newPlugin.getApiInjector())
          .ifPresent(i -> reattachItem(old, apiItems, i, newPlugin));
      reattachItem(old, sysItems, newPlugin.getSysInjector(), newPlugin);
      reattachItem(old, sshItems, newPlugin.getSshInjector(), newPlugin);
      reattachItem(old, httpItems, newPlugin.getHttpInjector(), newPlugin);
    } finally {
      exit(oldContext);
    }

    for (ReloadPluginListener l : onReload) {
      l.onReloadPlugin(oldPlugin, newPlugin);
    }
  }

  private void reattachMap(
      ListMultimap<TypeLiteral<?>, ReloadableRegistrationHandle<?>> oldHandles,
      Map<TypeLiteral<?>, DynamicMap<?>> maps,
      @Nullable Injector src,
      Plugin newPlugin) {
    if (src == null || maps == null || maps.isEmpty()) {
      return;
    }

    for (Map.Entry<TypeLiteral<?>, DynamicMap<?>> e : maps.entrySet()) {
      @SuppressWarnings("unchecked")
      TypeLiteral<Object> type = (TypeLiteral<Object>) e.getKey();

      @SuppressWarnings("unchecked")
      PrivateInternals_DynamicMapImpl<Object> map =
          (PrivateInternals_DynamicMapImpl<Object>) e.getValue();

      Map<Annotation, ReloadableRegistrationHandle<?>> am = new HashMap<>();
      for (ReloadableRegistrationHandle<?> h : oldHandles.get(type)) {
        Annotation a = h.getKey().getAnnotation();
        if (a != null && !UNIQUE_ANNOTATION.isInstance(a)) {
          am.put(a, h);
        }
      }

      for (Binding<?> binding : bindings(src, e.getKey())) {
        @SuppressWarnings("unchecked")
        Binding<Object> b = (Binding<Object>) binding;
        Key<Object> key = b.getKey();
        if (key.getAnnotation() == null) {
          continue;
        }

        @SuppressWarnings("unchecked")
        ReloadableRegistrationHandle<Object> h =
            (ReloadableRegistrationHandle<Object>) am.remove(key.getAnnotation());
        if (h != null) {
          replace(newPlugin, h, b);
          oldHandles.remove(type, h);
        } else {
          newPlugin.add(map.put(newPlugin.getName(), b.getKey(), b.getProvider()));
        }
      }
    }
  }

  /** Type used to declare unique annotations. Guice hides this, so extract it. */
  private static final Class<?> UNIQUE_ANNOTATION = UniqueAnnotations.create().annotationType();

  private void reattachSet(
      ListMultimap<TypeLiteral<?>, ReloadableRegistrationHandle<?>> oldHandles,
      Map<TypeLiteral<?>, DynamicSet<?>> sets,
      @Nullable Injector src,
      Plugin newPlugin) {
    if (src == null || sets == null || sets.isEmpty()) {
      return;
    }

    for (Map.Entry<TypeLiteral<?>, DynamicSet<?>> e : sets.entrySet()) {
      @SuppressWarnings("unchecked")
      TypeLiteral<Object> type = (TypeLiteral<Object>) e.getKey();

      @SuppressWarnings("unchecked")
      DynamicSet<Object> set = (DynamicSet<Object>) e.getValue();

      // Index all old handles that match this DynamicSet<T> keyed by
      // annotations. Ignore the unique annotations, thereby favoring
      // the @Named annotations or some other non-unique naming.
      Map<Annotation, ReloadableRegistrationHandle<?>> am = new HashMap<>();
      List<ReloadableRegistrationHandle<?>> old = oldHandles.get(type);
      Iterator<ReloadableRegistrationHandle<?>> oi = old.iterator();
      while (oi.hasNext()) {
        ReloadableRegistrationHandle<?> h = oi.next();
        Annotation a = h.getKey().getAnnotation();
        if (a != null && !UNIQUE_ANNOTATION.isInstance(a)) {
          am.put(a, h);
          oi.remove();
        }
      }

      // Replace old handles with new bindings, favoring cases where there
      // is an exact match on an @Named annotation. If there is no match
      // pick any handle and replace it. We generally expect only one
      // handle of each DynamicSet type when using unique annotations, but
      // possibly multiple ones if @Named was used. Plugin authors that want
      // atomic replacement across reloads should use @Named annotations with
      // stable names that do not change across plugin versions to ensure the
      // handles are swapped correctly.
      oi = old.iterator();
      for (Binding<?> binding : bindings(src, type)) {
        @SuppressWarnings("unchecked")
        Binding<Object> b = (Binding<Object>) binding;
        Key<Object> key = b.getKey();
        if (key.getAnnotation() == null) {
          continue;
        }

        @SuppressWarnings("unchecked")
        ReloadableRegistrationHandle<Object> h1 =
            (ReloadableRegistrationHandle<Object>) am.remove(key.getAnnotation());
        if (h1 != null) {
          replace(newPlugin, h1, b);
        } else if (oi.hasNext()) {
          @SuppressWarnings("unchecked")
          ReloadableRegistrationHandle<Object> h2 =
              (ReloadableRegistrationHandle<Object>) oi.next();
          oi.remove();
          replace(newPlugin, h2, b);
        } else {
          newPlugin.add(set.add(newPlugin.getName(), b.getKey(), b.getProvider()));
        }
      }
    }
  }

  private void reattachItem(
      ListMultimap<TypeLiteral<?>, ReloadableRegistrationHandle<?>> oldHandles,
      Map<TypeLiteral<?>, DynamicItem<?>> items,
      @Nullable Injector src,
      Plugin newPlugin) {
    if (src == null || items == null || items.isEmpty()) {
      return;
    }

    for (Map.Entry<TypeLiteral<?>, DynamicItem<?>> e : items.entrySet()) {
      @SuppressWarnings("unchecked")
      TypeLiteral<Object> type = (TypeLiteral<Object>) e.getKey();

      @SuppressWarnings("unchecked")
      DynamicItem<Object> item = (DynamicItem<Object>) e.getValue();

      Iterator<ReloadableRegistrationHandle<?>> oi = oldHandles.get(type).iterator();

      for (Binding<?> binding : bindings(src, type)) {
        @SuppressWarnings("unchecked")
        Binding<Object> b = (Binding<Object>) binding;
        if (oi.hasNext()) {
          @SuppressWarnings("unchecked")
          ReloadableRegistrationHandle<Object> h = (ReloadableRegistrationHandle<Object>) oi.next();
          oi.remove();
          replace(newPlugin, h, b);
        } else {
          newPlugin.add(item.set(b.getKey(), b.getProvider(), newPlugin.getName()));
        }
      }
    }
  }

  private static <T> void replace(
      Plugin newPlugin, ReloadableRegistrationHandle<T> h, Binding<T> b) {
    RegistrationHandle n = h.replace(b.getKey(), b.getProvider());
    if (n != null) {
      newPlugin.add(n);
    }
  }

  static <T> List<T> listeners(Injector src, Class<T> type) {
    List<Binding<T>> bindings = bindings(src, TypeLiteral.get(type));
    int cnt = bindings != null ? bindings.size() : 0;
    List<T> found = Lists.newArrayListWithCapacity(cnt);
    if (bindings != null) {
      for (Binding<T> b : bindings) {
        found.add(b.getProvider().get());
      }
    }
    return found;
  }

  private static <T> List<Binding<T>> bindings(Injector src, TypeLiteral<T> type) {
    return src.findBindingsByType(type);
  }

  private Module copy(Injector src) {
    Set<TypeLiteral<?>> dynamicTypes = new HashSet<>();
    Set<TypeLiteral<?>> dynamicItemTypes = new HashSet<>();
    for (Map.Entry<Key<?>, Binding<?>> e : src.getBindings().entrySet()) {
      TypeLiteral<?> type = e.getKey().getTypeLiteral();
      if (type.getRawType() == DynamicItem.class) {
        ParameterizedType t = (ParameterizedType) type.getType();
        dynamicItemTypes.add(TypeLiteral.get(t.getActualTypeArguments()[0]));
      } else if (type.getRawType() == DynamicSet.class || type.getRawType() == DynamicMap.class) {
        ParameterizedType t = (ParameterizedType) type.getType();
        dynamicTypes.add(TypeLiteral.get(t.getActualTypeArguments()[0]));
      }
    }

    final Map<Key<?>, Binding<?>> bindings = new LinkedHashMap<>();
    for (Map.Entry<Key<?>, Binding<?>> e : src.getBindings().entrySet()) {
      if (dynamicTypes.contains(e.getKey().getTypeLiteral())
          && e.getKey().getAnnotation() != null) {
        // A type used in DynamicSet or DynamicMap that has an annotation
        // must be picked up by the set/map itself. A type used in either
        // but without an annotation may be magic glue implementing F and
        // using DynamicSet<F> or DynamicMap<F> internally. That should be
        // exported to plugins.
        continue;
      } else if (dynamicItemTypes.contains(e.getKey().getTypeLiteral())) {
        continue;
      } else if (shouldCopy(e.getKey())) {
        bindings.put(e.getKey(), e.getValue());
      }
    }
    bindings.remove(Key.get(Injector.class));
    bindings.remove(Key.get(java.util.logging.Logger.class));

    @Nullable
    final Binding<HttpServletRequest> requestBinding =
        src.getExistingBinding(Key.get(HttpServletRequest.class));

    @Nullable
    final Binding<HttpServletResponse> responseBinding =
        src.getExistingBinding(Key.get(HttpServletResponse.class));

    return new AbstractModule() {
      @SuppressWarnings("unchecked")
      @Override
      protected void configure() {
        for (Map.Entry<Key<?>, Binding<?>> e : bindings.entrySet()) {
          Key<Object> k = (Key<Object>) e.getKey();
          Binding<Object> b = (Binding<Object>) e.getValue();
          bind(k).toProvider(b.getProvider());
        }

        if (requestBinding != null) {
          bind(HttpServletRequest.class)
              .annotatedWith(RootRelative.class)
              .toProvider(requestBinding.getProvider());
        }
        if (responseBinding != null) {
          bind(HttpServletResponse.class)
              .annotatedWith(RootRelative.class)
              .toProvider(responseBinding.getProvider());
        }
      }
    };
  }

  private boolean shouldCopy(Key<?> key) {
    if (copyConfigKeys.contains(key)) {
      return false;
    }
    Class<?> type = key.getTypeLiteral().getRawType();
    if (LifecycleListener.class.isAssignableFrom(type)
        // This is needed for secondary index to work from plugin listeners
        && !IndexCollection.class.isAssignableFrom(type)) {
      return false;
    }
    if (StartPluginListener.class.isAssignableFrom(type)) {
      return false;
    }
    if (StopPluginListener.class.isAssignableFrom(type)) {
      return false;
    }
    if (MetricMaker.class.isAssignableFrom(type)) {
      return false;
    }

    if (type.getName().startsWith("com.google.inject.")) {
      return false;
    }

    if (is("org.apache.sshd.server.command.Command", type)) {
      return false;
    }

    if (is("javax.servlet.Filter", type)) {
      return false;
    }
    if (is("javax.servlet.ServletContext", type)) {
      return false;
    }
    if (is("javax.servlet.ServletRequest", type)) {
      return false;
    }
    if (is("javax.servlet.ServletResponse", type)) {
      return false;
    }
    if (is("javax.servlet.http.HttpServlet", type)) {
      return false;
    }
    if (is("javax.servlet.http.HttpServletRequest", type)) {
      return false;
    }
    if (is("javax.servlet.http.HttpServletResponse", type)) {
      return false;
    }
    if (is("javax.servlet.http.HttpSession", type)) {
      return false;
    }
    if (Map.class.isAssignableFrom(type)
        && key.getAnnotationType() != null
        && "com.google.inject.servlet.RequestParameters"
            .equals(key.getAnnotationType().getName())) {
      return false;
    }
    if (type.getName().startsWith("com.google.gerrit.httpd.GitOverHttpServlet$")) {
      return false;
    }
    return true;
  }

  static boolean is(String name, Class<?> type) {
    while (type != null) {
      if (name.equals(type.getName())) {
        return true;
      }

      Class<?>[] interfaces = type.getInterfaces();
      if (interfaces != null) {
        for (Class<?> i : interfaces) {
          if (is(name, i)) {
            return true;
          }
        }
      }

      type = type.getSuperclass();
    }
    return false;
  }

  @Nullable
  public Injector getApiInjector() {
    return apiInjector;
  }
}
