// 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.errorprone.annotations.CanIgnoreReturnValue;
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;
  }

  @CanIgnoreReturnValue
  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) {
    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 (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);
          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);
  }

  @CanIgnoreReturnValue
  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;
      }

      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) {
      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);
    }
  }

  @CanIgnoreReturnValue
  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");
    }
  }
}
