<commit_before>// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ide.plugins;

import com.intellij.CommonBundle;
import com.intellij.core.CoreBundle;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.plugins.marketplace.MarketplacePluginDownloadService;
import com.intellij.ide.startup.StartupActionScriptManager;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.ex.ApplicationInfoEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.ui.ex.MessagesEx;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.io.Decompressor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.*;
import java.util.function.Consumer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * @author stathik
 */
public final class PluginInstaller {
  private static final Logger LOG = Logger.getInstance(PluginInstaller.class);

  public static final String UNKNOWN_HOST_MARKER = "__unknown_repository__";

  static final Object ourLock = new Object();
  private static final String PLUGINS_PRESELECTION_PATH = "plugins.preselection.path";

  private PluginInstaller() { }

  public static boolean prepareToInstall(List<PluginNode> pluginsToInstall,
                                         List<? extends IdeaPluginDescriptor> customOrAllPlugins,
                                         boolean allowInstallWithoutRestart,
                                         PluginManagerMain.PluginEnabler pluginEnabler,
                                         Runnable onSuccess,
                                         @NotNull ProgressIndicator indicator) {
    //TODO: `PluginInstallOperation` expects only `customPlugins`, but it can take `allPlugins` too
    PluginInstallOperation operation = new PluginInstallOperation(pluginsToInstall, customOrAllPlugins, pluginEnabler, indicator);
    operation.setAllowInstallWithoutRestart(allowInstallWithoutRestart);
    operation.run();
    boolean success = operation.isSuccess();
    if (success) {
      ApplicationManager.getApplication().invokeLater(() -> {
        if (allowInstallWithoutRestart) {
          for (PendingDynamicPluginInstall install : operation.getPendingDynamicPluginInstalls()) {
            installAndLoadDynamicPlugin(install.getFile(), null, install.getPluginDescriptor());
          }
        }
        if (onSuccess != null) {
          onSuccess.run();
        }
      });
    }
    return success;
  }

  /**
   * @return true if restart is needed
   */
  public static boolean prepareToUninstall(@NotNull IdeaPluginDescriptor pluginDescriptor) throws IOException {
    synchronized (ourLock) {
      if (PluginManagerCore.isPluginInstalled(pluginDescriptor.getPluginId())) {
        if (pluginDescriptor.isBundled()) {
          LOG.error("Plugin is bundled: " + pluginDescriptor.getPluginId());
        }
        else {
          boolean needRestart = !DynamicPlugins.allowLoadUnloadWithoutRestart((IdeaPluginDescriptorImpl)pluginDescriptor);
          if (needRestart) {
            uninstallAfterRestart(pluginDescriptor);
          }

          PluginStateManager.fireState(pluginDescriptor, false);
          return needRestart;
        }
      }
    }
    return false;
  }

  private static void uninstallAfterRestart(IdeaPluginDescriptor pluginDescriptor) throws IOException {
    StartupActionScriptManager.addActionCommand(new StartupActionScriptManager.DeleteCommand(pluginDescriptor.getPluginPath()));
  }

  public static boolean uninstallDynamicPlugin(@Nullable JComponent parentComponent,
                                               @NotNull IdeaPluginDescriptorImpl pluginDescriptor,
                                               boolean isUpdate) {
    DynamicPlugins.UnloadPluginOptions options = new DynamicPlugins.UnloadPluginOptions()
      .withUpdate(isUpdate)
      .withWaitForClassloaderUnload(true);

    boolean uninstalledWithoutRestart = parentComponent != null ?
                                        DynamicPlugins.unloadPluginWithProgress(null, parentComponent, pluginDescriptor, options) :
                                        DynamicPlugins.unloadPlugin(pluginDescriptor, options);

    if (uninstalledWithoutRestart) {
      try {
        FileUtil.delete(pluginDescriptor.getPluginPath());
      }
      catch (IOException e) {
        LOG.info("Failed to delete jar of dynamic plugin", e);
        uninstalledWithoutRestart = false;
      }
    }

    if (!uninstalledWithoutRestart) {
      try {
        uninstallAfterRestart(pluginDescriptor);
      }
      catch (IOException e) {
        LOG.error(e);
      }
    }
    return uninstalledWithoutRestart;
  }

  /**
   * @deprecated Use {@link #installAfterRestart(File, boolean, Path, IdeaPluginDescriptor)}
   */
  @Deprecated
  public static void installAfterRestart(@NotNull File sourceFile,
                                         boolean deleteSourceFile,
                                         @Nullable File existingPlugin,
                                         @NotNull IdeaPluginDescriptor descriptor) throws IOException {

  }

  public static void installAfterRestart(@NotNull Path sourceFile,<commit_msg>PluginInstaller: fix javadoc refs<commit_after>// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package com.intellij.ide.plugins;

import com.intellij.CommonBundle;
import com.intellij.core.CoreBundle;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.plugins.marketplace.MarketplacePluginDownloadService;
import com.intellij.ide.startup.StartupActionScriptManager;
import com.intellij.ide.util.PropertiesComponent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.ex.ApplicationInfoEx;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.PluginId;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.ui.ex.MessagesEx;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VfsUtilCore;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.io.Decompressor;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.*;
import java.util.function.Consumer;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

/**
 * @author stathik
 */
public final class PluginInstaller {
  private static final Logger LOG = Logger.getInstance(PluginInstaller.class);

  public static final String UNKNOWN_HOST_MARKER = "__unknown_repository__";

  static final Object ourLock = new Object();
  private static final String PLUGINS_PRESELECTION_PATH = "plugins.preselection.path";

  private PluginInstaller() { }

  public static boolean prepareToInstall(List<PluginNode> pluginsToInstall,
                                         List<? extends IdeaPluginDescriptor> customOrAllPlugins,
                                         boolean allowInstallWithoutRestart,
                                         PluginManagerMain.PluginEnabler pluginEnabler,
                                         Runnable onSuccess,
                                         @NotNull ProgressIndicator indicator) {
    //TODO: `PluginInstallOperation` expects only `customPlugins`, but it can take `allPlugins` too
    PluginInstallOperation operation = new PluginInstallOperation(pluginsToInstall, customOrAllPlugins, pluginEnabler, indicator);
    operation.setAllowInstallWithoutRestart(allowInstallWithoutRestart);
    operation.run();
    boolean success = operation.isSuccess();
    if (success) {
      ApplicationManager.getApplication().invokeLater(() -> {
        if (allowInstallWithoutRestart) {
          for (PendingDynamicPluginInstall install : operation.getPendingDynamicPluginInstalls()) {
            installAndLoadDynamicPlugin(install.getFile(), null, install.getPluginDescriptor());
          }
        }
        if (onSuccess != null) {
          onSuccess.run();
        }
      });
    }
    return success;
  }

  /**
   * @return true if restart is needed
   */
  public static boolean prepareToUninstall(@NotNull IdeaPluginDescriptor pluginDescriptor) throws IOException {
    synchronized (ourLock) {
      if (PluginManagerCore.isPluginInstalled(pluginDescriptor.getPluginId())) {
        if (pluginDescriptor.isBundled()) {
          LOG.error("Plugin is bundled: " + pluginDescriptor.getPluginId());
        }
        else {
          boolean needRestart = !DynamicPlugins.allowLoadUnloadWithoutRestart((IdeaPluginDescriptorImpl)pluginDescriptor);
          if (needRestart) {
            uninstallAfterRestart(pluginDescriptor);
          }

          PluginStateManager.fireState(pluginDescriptor, false);
          return needRestart;
        }
      }
    }
    return false;
  }

  private static void uninstallAfterRestart(IdeaPluginDescriptor pluginDescriptor) throws IOException {
    StartupActionScriptManager.addActionCommand(new StartupActionScriptManager.DeleteCommand(pluginDescriptor.getPluginPath()));
  }

  public static boolean uninstallDynamicPlugin(@Nullable JComponent parentComponent,
                                               @NotNull IdeaPluginDescriptorImpl pluginDescriptor,
                                               boolean isUpdate) {
    DynamicPlugins.UnloadPluginOptions options = new DynamicPlugins.UnloadPluginOptions()
      .withUpdate(isUpdate)
      .withWaitForClassloaderUnload(true);

    boolean uninstalledWithoutRestart = parentComponent != null ?
                                        DynamicPlugins.unloadPluginWithProgress(null, parentComponent, pluginDescriptor, options) :
                                        DynamicPlugins.unloadPlugin(pluginDescriptor, options);

    if (uninstalledWithoutRestart) {
      try {
        FileUtil.delete(pluginDescriptor.getPluginPath());
      }
      catch (IOException e) {
        LOG.info("Failed to delete jar of dynamic plugin", e);
        uninstalledWithoutRestart = false;
      }
    }

    if (!uninstalledWithoutRestart) {
      try {
        uninstallAfterRestart(pluginDescriptor);
      }
      catch (IOException e) {
        LOG.error(e);
      }
    }
    return uninstalledWithoutRestart;
  }

  /**
   * @deprecated Use {@link #installAfterRestart(Path, boolean, Path, IdeaPluginDescriptor)}
   */
  @Deprecated
  public static void installAfterRestart(@NotNull File sourceFile,
                                         boolean deleteSourceFile,
                                         @Nullable File existingPlugin,
                                         @NotNull IdeaPluginDescriptor descriptor) throws IOException {

  }

  public static void installAfterRestart(@NotNull Path sourceFile,
{'fraction_non_alphanumeric': 0.0828897933625548, 'fraction_numerical': 0.0015654351909830933, 'mean_word_length': 3.111003861003861, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 9, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 46, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2563091', 'n_tokens_mistral': 3365, 'n_tokens_neox': 3268, 'n_words': 662}