// 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 com.google.common.base.CharMatcher;
import com.google.common.base.Joiner;
import com.google.common.base.MoreObjects;
import com.google.common.base.Strings;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ImmutableList;
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.SetMultimap;
import com.google.common.collect.Sets;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.events.LifecycleListener;
import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.systemstatus.ServerInformation;
import com.google.gerrit.server.PluginUser;
import com.google.gerrit.server.cache.PersistentCacheFactory;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.ConfigUtil;
import com.google.gerrit.server.config.GerritRuntime;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.plugins.ServerPluginProvider.PluginDescription;
import com.google.inject.Inject;
import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.AbstractMap;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.TimeUnit;
import java.util.jar.JarFile;
import org.eclipse.jgit.internal.storage.file.FileSnapshot;
import org.eclipse.jgit.lib.Config;

@Singleton
public class PluginLoader implements LifecycleListener {
  private static final FluentLogger logger = FluentLogger.forEnclosingClass();

  public String getPluginName(Path srcPath) {
    return MoreObjects.firstNonNull(getGerritPluginName(srcPath), PluginUtil.nameOf(srcPath));
  }

  private final Path pluginsDir;
  private final Path dataDir;
  private final Path tempDir;
  private final PluginGuiceEnvironment env;
  private final ServerInformationImpl srvInfoImpl;
  private final PluginUser.Factory pluginUserFactory;
  private final ConcurrentMap<String, Plugin> running = Maps.newConcurrentMap();
  private final ConcurrentMap<String, Plugin> disabled = Maps.newConcurrentMap();
  private final Map<String, FileSnapshot> broken = Maps.newHashMap();
  private final Map<Plugin, CleanupHandle> cleanupHandles = Maps.newConcurrentMap();
  private final Queue<Plugin> toCleanup = new ArrayDeque<>();
  private final Provider<PluginCleanerTask> cleaner;
  private final PluginScannerThread scanner;
  private final Provider<String> urlProvider;
  private final PersistentCacheFactory persistentCacheFactory;
  private final boolean remoteAdmin;
  private final MandatoryPluginsCollection mandatoryPlugins;
  private final UniversalServerPluginProvider serverPluginFactory;
  private final GerritRuntime gerritRuntime;

  @Inject
  public PluginLoader(
      SitePaths sitePaths,
      PluginGuiceEnvironment pe,
      ServerInformationImpl sii,
      PluginUser.Factory puf,
      Provider<PluginCleanerTask> pct,
      @GerritServerConfig Config cfg,
      @CanonicalWebUrl Provider<String> provider,
      PersistentCacheFactory cacheFactory,
      UniversalServerPluginProvider pluginFactory,
      MandatoryPluginsCollection mpc,
      GerritRuntime gerritRuntime) {
    pluginsDir = sitePaths.plugins_dir;
    dataDir = sitePaths.data_dir;
    tempDir = sitePaths.tmp_dir;
    env = pe;
    srvInfoImpl = sii;
    pluginUserFactory = puf;
    cleaner = pct;
    urlProvider = provider;
    persistentCacheFactory = cacheFactory;
    serverPluginFactory = pluginFactory;

    remoteAdmin = cfg.getBoolean("plugins", null, "allowRemoteAdmin", false);
    mandatoryPlugins = mpc;
    this.gerritRuntime = gerritRuntime;

    long checkFrequency =
        ConfigUtil.getTimeUnit(
            cfg,
            "plugins",
            null,
            "checkFrequency",
            TimeUnit.MINUTES.toMillis(1),
            TimeUnit.MILLISECONDS);
    if (checkFrequency > 0) {
      scanner = new PluginScannerThread(this, checkFrequency);
    } else {
      scanner = null;
    }
  }

  public boolean isRemoteAdminEnabled() {
    return remoteAdmin;
  }

  public void checkRemoteAdminEnabled() throws MethodNotAllowedException {
    if (!remoteAdmin) {
      throw new MethodNotAllowedException("remote plugin administration is disabled");
    }
  }

  public Plugin get(String name) {
    Plugin p = running.get(name);
    if (p != null) {
      return p;
    }
    return disabled.get(name);
  }

  public Iterable<Plugin> getPlugins(boolean all) {
    if (!all) {
      return running.values();
    }
    List<Plugin> plugins = new ArrayList<>(running.values());
    plugins.addAll(disabled.values());
    return plugins;
  }

  public String installPluginFromStream(String originalName, InputStream in)
      throws IOException, PluginInstallException {
    checkRemoteInstall();

    String fileName = originalName;
    Path tmp = PluginUtil.asTemp(in, ".next_" + fileName + "_", ".tmp", pluginsDir);
    String name = MoreObjects.firstNonNull(getGerritPluginName(tmp), PluginUtil.nameOf(fileName));
    if (!originalName.equals(name)) {
      logger.atWarning().log(
          "Plugin provides its own name: <%s>, use it instead of the input name: <%s>",
          name, originalName);
    }

    String fileExtension = getExtension(fileName);
    Path dst = pluginsDir.resolve(name + fileExtension);
    synchronized (this) {
      Plugin active = running.get(name);
      if (active != null) {
        fileName = active.getSrcFile().getFileName().toString();
        logger.atInfo().log("Replacing plugin %s", active.getName());
        Path old = pluginsDir.resolve(".last_" + fileName);
        Files.deleteIfExists(old);
        Files.move(active.getSrcFile(), old);
      }

      Files.deleteIfExists(pluginsDir.resolve(fileName + ".disabled"));
      Files.move(tmp, dst);
      try {
        Plugin plugin = runPlugin(name, dst, active);
        if (active == null) {
          logger.atInfo().log(
              "Installed plugin %s%s",
              plugin.getName(), plugin.getApiModule().isPresent() ? " (w/ ApiModule)" : "");
        }
      } catch (PluginInstallException e) {
        Files.deleteIfExists(dst);
        throw e;
      }

      cleanInBackground();
    }

    return name;
  }

  private synchronized void unloadPlugin(Plugin plugin) {
    persistentCacheFactory.onStop(plugin.getName());
    String name = plugin.getName();
    logger.atInfo().log("Unloading plugin %s, version %s", name, plugin.getVersion());
    plugin.stop(env);
    env.onStopPlugin(plugin);
    running.remove(name);
    disabled.remove(name);
    toCleanup.add(plugin);
  }

  public void disablePlugins(Set<String> names) throws PluginInstallException {
    if (!isRemoteAdminEnabled()) {
      logger.atWarning().log(
          "Remote plugin administration is disabled, ignoring disablePlugins(%s)", names);
      return;
    }

    synchronized (this) {
      for (String name : names) {
        Plugin active = running.get(name);
        if (active == null) {
          continue;
        }

        if (active.getApiModule().isPresent()) {
          throw new PluginInstallException(
              String.format(
                  "Plugin %s has registered an ApiModule therefore it cannot be disabled", name));
        }

        if (mandatoryPlugins.contains(name)) {
          logger.atWarning().log("Mandatory plugin %s cannot be disabled", name);
          continue;
        }

        logger.atInfo().log("Disabling plugin %s", active.getName());
        Path off =
            active.getSrcFile().resolveSibling(active.getSrcFile().getFileName() + ".disabled");
        try {
          Files.move(active.getSrcFile(), off);
        } catch (IOException e) {
          logger.atSevere().withCause(e).log("Failed to disable plugin");
          // In theory we could still unload the plugin even if the rename
          // failed. However, it would be reloaded on the next server startup,
          // which is probably not what the user expects.
          continue;
        }

        unloadPlugin(active);
        try {
          FileSnapshot snapshot = FileSnapshot.save(off.toFile());
          Plugin offPlugin = loadPlugin(name, off, snapshot);
          disabled.put(name, offPlugin);
        } catch (Exception e) {
          // This shouldn't happen, as the plugin was loaded earlier.
          logger.atWarning().withCause(e.getCause()).log(
              "Cannot load disabled plugin %s", active.getName());
        }
      }
      cleanInBackground();
    }
  }

  public void enablePlugins(Set<String> names) throws PluginInstallException {
    if (!isRemoteAdminEnabled()) {
      logger.atWarning().log(
          "Remote plugin administration is disabled, ignoring enablePlugins(%s)", names);
      return;
    }

    synchronized (this) {
      for (String name : names) {
        Plugin off = disabled.get(name);
        if (off == null) {
          continue;
        }

        logger.atInfo().log("Enabling plugin %s", name);
        String n = off.getSrcFile().toFile().getName();
        if (n.endsWith(".disabled")) {
          n = n.substring(0, n.lastIndexOf('.'));
        }
        Path on = pluginsDir.resolve(n);
        try {
          Files.move(off.getSrcFile(), on);
        } catch (IOException e) {
          logger.atSevere().withCause(e).log("Failed to move plugin %s into place", name);
          continue;
        }
        disabled.remove(name);
        runPlugin(name, on, null);
      }
      cleanInBackground();
    }
  }

  private void removeStalePluginFiles() {
    DirectoryStream.Filter<Path> filter =
        entry -> entry.getFileName().toString().startsWith("plugin_");
    try (DirectoryStream<Path> files = Files.newDirectoryStream(tempDir, filter)) {
      for (Path file : files) {
        logger.atInfo().log("Removing stale plugin file: %s", file.toFile().getName());
        try {
          Files.delete(file);
        } catch (IOException e) {
          logger.atSevere().log(
              "Failed to remove stale plugin file %s: %s", file.toFile().getName(), e.getMessage());
        }
      }
    } catch (IOException e) {
      logger.atWarning().log("Unable to discover stale plugin files: %s", e.getMessage());
    }
  }

  @Override
  public synchronized void start() {
    removeStalePluginFiles();
    Path absolutePath = pluginsDir.toAbsolutePath();
    if (!Files.exists(absolutePath)) {
      logger.atInfo().log("%s does not exist; creating", absolutePath);
      try {
        Files.createDirectories(absolutePath);
      } catch (IOException e) {
        logger.atSevere().log("Failed to create %s: %s", absolutePath, e.getMessage());
      }
    }
    logger.atInfo().log("Loading plugins from %s", absolutePath);
    srvInfoImpl.state = ServerInformation.State.STARTUP;
    rescan();
    srvInfoImpl.state = ServerInformation.State.RUNNING;
    if (scanner != null) {
      scanner.start();
    }
  }

  @Override
  public void stop() {
    if (scanner != null) {
      scanner.end();
    }
    srvInfoImpl.state = ServerInformation.State.SHUTDOWN;
    synchronized (this) {
      for (Plugin p : running.values()) {
        unloadPlugin(p);
      }
      running.clear();
      disabled.clear();
      broken.clear();
      if (!toCleanup.isEmpty()) {
        processPendingCleanups();
      }
    }
  }

  public void reload(List<String> names) throws InvalidPluginException, PluginInstallException {
    synchronized (this) {
      List<Plugin> reload = Lists.newArrayListWithCapacity(names.size());
      List<String> bad = Lists.newArrayListWithExpectedSize(4);
      for (String name : names) {
        Plugin active = running.get(name);
        if (active != null) {
          reload.add(active);
        } else {
          bad.add(name);
        }
      }
      if (!bad.isEmpty()) {
        throw new InvalidPluginException(
            String.format("Plugin(s) \"%s\" not running", Joiner.on("\", \"").join(bad)));
      }

      for (Plugin active : reload) {
        String name = active.getName();
        try {
          logger.atInfo().log("Reloading plugin %s", name);
          Plugin newPlugin = runPlugin(name, active.getSrcFile(), active);

          if (newPlugin != active) {
            logger.atInfo().log(
                "Reloaded plugin %s%s, version %s",
                newPlugin.getName(),
                newPlugin.getApiModule().isPresent() ? " (w/ ApiModule)" : "",
                newPlugin.getVersion());
          }
        } catch (PluginInstallException e) {
          logger.atWarning().withCause(e.getCause()).log("Cannot reload plugin %s", name);
          throw e;
        }
      }

      cleanInBackground();
    }
  }

  public synchronized void rescan() {
    Set<String> loadedPlugins = new HashSet<>();
    SetMultimap<String, Path> pluginsFiles = prunePlugins(pluginsDir);

    if (!pluginsFiles.isEmpty()) {
      syncDisabledPlugins(pluginsFiles);

      Map<String, Path> activePlugins = filterDisabled(pluginsFiles);
      for (Map.Entry<String, Path> entry : jarsApiFirstSortedPluginsSet(activePlugins)) {
        String name = entry.getKey();
        Path path = entry.getValue();
        String fileName = path.getFileName().toString();
        if (!isUiPlugin(fileName) && !serverPluginFactory.handles(path)) {
          logger.atWarning().log(
              "No Plugin provider was found that handles this file format: %s", fileName);
          continue;
        }

        FileSnapshot brokenTime = broken.get(name);
        if (brokenTime != null && !brokenTime.isModified(path.toFile())) {
          continue;
        }

        Plugin active = running.get(name);
        if (active != null && !active.isModified(path)) {
          loadedPlugins.add(name);
          continue;
        }

        if (active != null) {
          logger.atInfo().log("Reloading plugin %s", active.getName());
        }

        try {
          Plugin loadedPlugin = runPlugin(name, path, active);
          if (!loadedPlugin.isDisabled()) {
            loadedPlugins.add(name);
            logger.atInfo().log(
                "%s plugin %s%s, version %s",
                active == null ? "Loaded" : "Reloaded",
                loadedPlugin.getName(),
                loadedPlugin.getApiModule().isPresent() ? " (w/ ApiModule)" : "",
                loadedPlugin.getVersion());
          }
        } catch (PluginInstallException e) {
          logger.atWarning().withCause(e.getCause()).log("Cannot load plugin %s", name);
        }
      }
    }

    Set<String> missingMandatory = Sets.difference(mandatoryPlugins.asSet(), loadedPlugins);
    if (!missingMandatory.isEmpty()) {
      throw new MissingMandatoryPluginsException(missingMandatory);
    }

    cleanInBackground();
  }

  private void addAllEntries(Map<String, Path> from, TreeSet<Map.Entry<String, Path>> to) {
    Iterator<Map.Entry<String, Path>> it = from.entrySet().iterator();
    while (it.hasNext()) {
      Map.Entry<String, Path> entry = it.next();
      to.add(new AbstractMap.SimpleImmutableEntry<>(entry.getKey(), entry.getValue()));
    }
  }

  private TreeSet<Map.Entry<String, Path>> jarsApiFirstSortedPluginsSet(
      Map<String, Path> activePlugins) {
    TreeSet<Map.Entry<String, Path>> sortedPlugins =
        Sets.newTreeSet(
            new Comparator<Map.Entry<String, Path>>() {
              @Override
              public int compare(Map.Entry<String, Path> e1, Map.Entry<String, Path> e2) {
                Path n1 = e1.getValue().getFileName();
                Path n2 = e2.getValue().getFileName();

                try {
                  boolean e1IsApi = isApi(e1.getValue());
                  boolean e2IsApi = isApi(e2.getValue());
                  return ComparisonChain.start()
                      .compareTrueFirst(e1IsApi, e2IsApi)
                      .compareTrueFirst(isJar(n1), isJar(n2))
                      .compare(n1, n2)
                      .result();
                } catch (IOException ioe) {
                  logger.atSevere().withCause(ioe).log("Unable to compare %s and %s", n1, n2);
                  return 0;
                }
              }

              private boolean isJar(Path pluginPath) {
                return pluginPath.toString().endsWith(".jar");
              }

              private boolean isApi(Path pluginPath) throws IOException {
                return isJar(pluginPath) && hasApiModuleEntryInManifest(pluginPath);
              }

              private boolean hasApiModuleEntryInManifest(Path pluginPath) throws IOException {
                try (JarFile jarFile = new JarFile(pluginPath.toFile())) {
                  return !Strings.isNullOrEmpty(
                      jarFile.getManifest().getMainAttributes().getValue(ServerPlugin.API_MODULE));
                }
              }
            });

    addAllEntries(activePlugins, sortedPlugins);
    return sortedPlugins;
  }

  private void syncDisabledPlugins(SetMultimap<String, Path> jars) {
    stopRemovedPlugins(jars);
    dropRemovedDisabledPlugins(jars);
  }

  private Plugin runPlugin(String name, Path plugin, Plugin oldPlugin)
      throws PluginInstallException {
    FileSnapshot snapshot = FileSnapshot.save(plugin.toFile());
    try {
      boolean restartRequired = oldPlugin != null && !oldPlugin.canReload();
      if (restartRequired && mandatoryPlugins.contains(name)) {
        logger.atWarning().log("Restarting mandatory plugin %s not allowed", name);
        return oldPlugin;
      }

      if (oldPlugin != null && oldPlugin.getApiModule().isPresent()) {
        throw new PluginInstallException(
            String.format(
                "Plugin %s has registered an ApiModule therefore its restart/reload is not allowed",
                name));
      }

      Plugin newPlugin = loadPlugin(name, plugin, snapshot);
      if (newPlugin.getCleanupHandle() != null) {
        cleanupHandles.put(newPlugin, newPlugin.getCleanupHandle());
      }
      /*
       * Pluggable plugin provider may have assigned a plugin name that could be
       * actually different from the initial one assigned during scan. It is
       * safer then to reassign it.
       */
      name = newPlugin.getName();
      boolean reload = oldPlugin != null && oldPlugin.canReload() && newPlugin.canReload();
      if (!reload && oldPlugin != null) {
        unloadPlugin(oldPlugin);
      }
      if (!newPlugin.isDisabled()) {
        try {
          newPlugin.start(env);
        } catch (Exception e) {
          newPlugin.stop(env);
          throw e;
        }
      }
      if (reload) {
        env.onReloadPlugin(oldPlugin, newPlugin);
        unloadPlugin(oldPlugin);
      } else if (!newPlugin.isDisabled()) {
        env.onStartPlugin(newPlugin);
      }
      if (!newPlugin.isDisabled()) {
        running.put(name, newPlugin);
      } else {
        disabled.put(name, newPlugin);
      }
      broken.remove(name);
      return newPlugin;
    } catch (Exception err) {
      broken.put(name, snapshot);
      throw new PluginInstallException(err);
    }
  }

  private void stopRemovedPlugins(SetMultimap<String, Path> jars) {
    Set<String> unload = Sets.newHashSet(running.keySet());
    for (Map.Entry<String, Collection<Path>> entry : jars.asMap().entrySet()) {
      for (Path path : entry.getValue()) {
        if (!path.getFileName().toString().endsWith(".disabled")) {
          unload.remove(entry.getKey());
        }
      }
    }
    for (String name : unload) {
      Plugin runningPlugin = running.get(name);

      if (runningPlugin.getApiModule().isPresent()) {
        logger.atWarning().log("Cannot remove plugin %s as it has registered an ApiModule", name);
      } else {
        unloadPlugin(running.get(name));
      }
    }
  }

  private void dropRemovedDisabledPlugins(SetMultimap<String, Path> jars) {
    Set<String> unload = Sets.newHashSet(disabled.keySet());
    for (Map.Entry<String, Collection<Path>> entry : jars.asMap().entrySet()) {
      for (Path path : entry.getValue()) {
        if (path.getFileName().toString().endsWith(".disabled")) {
          unload.remove(entry.getKey());
        }
      }
    }
    for (String name : unload) {
      disabled.remove(name);
    }
  }

  synchronized int processPendingCleanups() {
    Iterator<Plugin> iterator = toCleanup.iterator();
    while (iterator.hasNext()) {
      Plugin plugin = iterator.next();
      iterator.remove();

      CleanupHandle cleanupHandle = cleanupHandles.remove(plugin);
      if (cleanupHandle != null) {
        cleanupHandle.cleanup();
      }
    }
    return toCleanup.size();
  }

  private void cleanInBackground() {
    int cnt = toCleanup.size();
    if (0 < cnt) {
      cleaner.get().clean(cnt);
    }
  }

  private String getExtension(String name) {
    int ext = name.lastIndexOf('.');
    return 0 < ext ? name.substring(ext) : "";
  }

  private Plugin loadPlugin(String name, Path srcPlugin, FileSnapshot snapshot)
      throws InvalidPluginException {
    String pluginName = srcPlugin.getFileName().toString();
    if (isUiPlugin(pluginName)) {
      return loadJsPlugin(name, srcPlugin, snapshot);
    } else if (serverPluginFactory.handles(srcPlugin)) {
      return loadServerPlugin(srcPlugin, snapshot);
    } else {
      throw new InvalidPluginException(
          String.format("Unsupported plugin type: %s", srcPlugin.getFileName()));
    }
  }

  private Path getPluginDataDir(String name) {
    return dataDir.resolve(name);
  }

  private String getPluginCanonicalWebUrl(String name) {
    String canonicalWebUrl = urlProvider.get();
    if (Strings.isNullOrEmpty(canonicalWebUrl)) {
      return "/plugins/" + name;
    }

    String url =
        String.format(
            "%s/plugins/%s/", CharMatcher.is('/').trimTrailingFrom(canonicalWebUrl), name);
    return url;
  }

  private Plugin loadJsPlugin(String name, Path srcJar, FileSnapshot snapshot) {
    return new JsPlugin(name, srcJar, pluginUserFactory.create(name), snapshot);
  }

  private ServerPlugin loadServerPlugin(Path scriptFile, FileSnapshot snapshot)
      throws InvalidPluginException {
    String name = serverPluginFactory.getPluginName(scriptFile);
    return serverPluginFactory.get(
        scriptFile,
        snapshot,
        new PluginDescription(
            pluginUserFactory.create(name),
            getPluginCanonicalWebUrl(name),
            getPluginDataDir(name),
            gerritRuntime));
  }

  // Only one active plugin per plugin name can exist for each plugin name.
  // Filter out disabled plugins and transform the multimap to a map
  private Map<String, Path> filterDisabled(SetMultimap<String, Path> pluginPaths) {
    Map<String, Path> activePlugins = Maps.newHashMapWithExpectedSize(pluginPaths.keys().size());
    for (String name : pluginPaths.keys()) {
      for (Path pluginPath : pluginPaths.asMap().get(name)) {
        if (!pluginPath.getFileName().toString().endsWith(".disabled")) {
          assert !activePlugins.containsKey(name);
          activePlugins.put(name, pluginPath);
        }
      }
    }
    return activePlugins;
  }

  // Scan the $site_path/plugins directory and fetch all files and directories.
  // The Key in returned multimap is the plugin name initially assigned from its filename.
  // Values are the files. Plugins can optionally provide their name in MANIFEST file.
  // If multiple plugin files provide the same plugin name, then only
  // the first plugin remains active and all other plugins with the same
  // name are disabled.
  //
  // NOTE: Bear in mind that the plugin name can be reassigned after load by the
  //       Server plugin provider.
  public SetMultimap<String, Path> prunePlugins(Path pluginsDir) {
    List<Path> pluginPaths = scanPathsInPluginsDirectory(pluginsDir);
    SetMultimap<String, Path> map;
    map = asMultimap(pluginPaths);
    for (String plugin : map.keySet()) {
      Collection<Path> files = map.asMap().get(plugin);
      if (files.size() == 1) {
        continue;
      }
      // retrieve enabled plugins
      Iterable<Path> enabled = filterDisabledPlugins(files);
      // If we have only one (the winner) plugin, nothing to do
      if (!Iterables.skip(enabled, 1).iterator().hasNext()) {
        continue;
      }
      Path winner = Iterables.getFirst(enabled, null);
      assert winner != null;
      // Disable all loser plugins by renaming their file names to
      // "file.disabled" and replace the disabled files in the multimap.
      Collection<Path> elementsToRemove = new ArrayList<>();
      Collection<Path> elementsToAdd = new ArrayList<>();
      for (Path loser : Iterables.skip(enabled, 1)) {
        logger.atWarning().log(
            "Plugin <%s> was disabled, because"
                + " another plugin <%s>"
                + " with the same name <%s> already exists",
            loser, winner, plugin);
        Path disabledPlugin = Paths.get(loser + ".disabled");
        elementsToAdd.add(disabledPlugin);
        elementsToRemove.add(loser);
        try {
          Files.move(loser, disabledPlugin);
        } catch (IOException e) {
          logger.atWarning().withCause(e).log("Failed to fully disable plugin %s", loser);
        }
      }
      Iterables.removeAll(files, elementsToRemove);
      Iterables.addAll(files, elementsToAdd);
    }
    return map;
  }

  private List<Path> scanPathsInPluginsDirectory(Path pluginsDir) {
    try {
      return PluginUtil.listPlugins(pluginsDir);
    } catch (IOException e) {
      logger.atSevere().withCause(e).log("Cannot list %s", pluginsDir.toAbsolutePath());
      return ImmutableList.of();
    }
  }

  private Iterable<Path> filterDisabledPlugins(Collection<Path> paths) {
    return Iterables.filter(paths, p -> !p.getFileName().toString().endsWith(".disabled"));
  }

  @Nullable
  public String getGerritPluginName(Path srcPath) {
    String fileName = srcPath.getFileName().toString();
    if (isUiPlugin(fileName)) {
      return fileName.substring(0, fileName.lastIndexOf('.'));
    }
    if (serverPluginFactory.handles(srcPath)) {
      return serverPluginFactory.getPluginName(srcPath);
    }
    return null;
  }

  private SetMultimap<String, Path> asMultimap(List<Path> plugins) {
    SetMultimap<String, Path> map = LinkedHashMultimap.create();
    for (Path srcPath : plugins) {
      map.put(getPluginName(srcPath), srcPath);
    }
    return map;
  }

  private boolean isUiPlugin(String name) {
    return isPlugin(name, "js");
  }

  private boolean isPlugin(String fileName, String ext) {
    String fullExt = "." + ext;
    return fileName.endsWith(fullExt) || fileName.endsWith(fullExt + ".disabled");
  }

  private void checkRemoteInstall() throws PluginInstallException {
    if (!isRemoteAdminEnabled()) {
      throw new PluginInstallException("remote installation is disabled");
    }
  }
}
