public Collection<ServerPluginInfo> loadPlugins() {
    Map<String, ServerPluginInfo> bundledPluginsByKey = new LinkedHashMap<>();
    for (ServerPluginInfo bundled : getBundledPluginsMetadata()) {
      failIfContains(bundledPluginsByKey, bundled,
        plugin -> MessageException.of(format("Found two versions of the plugin %s [%s] in the directory %s. Please remove one of %s or %s.",
          bundled.getName(), bundled.getKey(), getRelativeDir(fs.getInstalledBundledPluginsDir()), bundled.getNonNullJarFile().getName(), plugin.getNonNullJarFile().getName())));
      bundledPluginsByKey.put(bundled.getKey(), bundled);
    }

    Map<String, ServerPluginInfo> externalPluginsByKey = new LinkedHashMap<>();
    for (ServerPluginInfo external : getExternalPluginsMetadata()) {
      failIfContains(bundledPluginsByKey, external,
        plugin -> MessageException.of(format("Found a plugin '%s' in the directory '%s' with the same key [%s] as a built-in feature '%s'. Please remove '%s'.",
          external.getName(), getRelativeDir(fs.getInstalledExternalPluginsDir()), external.getKey(), plugin.getName(),
          new File(getRelativeDir(fs.getInstalledExternalPluginsDir()), external.getNonNullJarFile().getName()))));
      failIfContains(externalPluginsByKey, external,
        plugin -> MessageException.of(format("Found two versions of the plugin '%s' [%s] in the directory '%s'. Please remove %s or %s.", external.getName(), external.getKey(),
          getRelativeDir(fs.getInstalledExternalPluginsDir()), external.getNonNullJarFile().getName(), plugin.getNonNullJarFile().getName())));
      externalPluginsByKey.put(external.getKey(), external);
    }

    for (PluginInfo downloaded : getDownloadedPluginsMetadata()) {
      failIfContains(bundledPluginsByKey, downloaded,
        plugin -> MessageException.of(format("Fail to update plugin: %s. Built-in feature with same key already exists: %s. Move or delete plugin from %s directory",
          plugin.getName(), plugin.getKey(), getRelativeDir(fs.getDownloadedPluginsDir()))));

      ServerPluginInfo installedPlugin;
      if (externalPluginsByKey.containsKey(downloaded.getKey())) {
        deleteQuietly(externalPluginsByKey.get(downloaded.getKey()).getNonNullJarFile());
        installedPlugin = moveDownloadedPluginToExtensions(downloaded);
        LOG.info("Plugin {} [{}] updated to version {}", installedPlugin.getName(), installedPlugin.getKey(), installedPlugin.getVersion());
      } else {
        installedPlugin = moveDownloadedPluginToExtensions(downloaded);
        LOG.info("Plugin {} [{}] installed", installedPlugin.getName(), installedPlugin.getKey());
      }

      externalPluginsByKey.put(downloaded.getKey(), installedPlugin);
    }

    Map<String, ServerPluginInfo> plugins = new HashMap<>(externalPluginsByKey.size() + bundledPluginsByKey.size());
    plugins.putAll(externalPluginsByKey);
    plugins.putAll(bundledPluginsByKey);

    PluginRequirementsValidator.unloadIncompatiblePlugins(plugins);

    return plugins.values();
  }
@Test
  public void fail_if_downloaded_plugin_has_same_key_has_bundled() throws IOException {
    File downloaded = createJar(fs.getDownloadedPluginsDir(), "plugin1", "main", null);
    createJar(fs.getInstalledBundledPluginsDir(), "plugin1", "main", null);
    String dir = getDirName(fs.getDownloadedPluginsDir());

    assertThatThrownBy(() -> underTest.loadPlugins())
      .isInstanceOf(MessageException.class)
      .hasMessage("Fail to update plugin: plugin1. Built-in feature with same key already exists: plugin1. "
        + "Move or delete plugin from " + dir + " directory");
  }