| package com.google.gct.idea.settings; |
| |
| import com.google.common.annotations.VisibleForTesting; |
| import com.intellij.ide.IdeBundle; |
| import com.intellij.ide.actions.ImportSettingsFilenameFilter; |
| import com.intellij.ide.plugins.PluginManager; |
| import com.intellij.ide.startup.StartupActionScriptManager; |
| import com.intellij.openapi.actionSystem.AnAction; |
| import com.intellij.openapi.actionSystem.AnActionEvent; |
| import com.intellij.openapi.application.ApplicationManager; |
| import com.intellij.openapi.application.ApplicationNamesInfo; |
| import com.intellij.openapi.application.PathManager; |
| import com.intellij.openapi.application.ex.ApplicationEx; |
| import com.intellij.openapi.components.ExportableApplicationComponent; |
| import com.intellij.openapi.components.ExportableComponent; |
| import com.intellij.openapi.components.ServiceBean; |
| import com.intellij.openapi.ui.Messages; |
| import com.intellij.openapi.updateSettings.impl.UpdateSettings; |
| import com.intellij.openapi.util.io.FileUtil; |
| import com.intellij.util.io.ZipUtil; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.util.*; |
| import java.util.zip.ZipEntry; |
| import java.util.zip.ZipException; |
| import java.util.zip.ZipFile; |
| |
| /** |
| * Provides functionality to update IDEA setting from a jar containing new settings |
| */ |
| public class ImportSettings { |
| private static final String DIALOG_TITLE = "Setting Synchronization"; |
| public static final String SETTINGS_JAR_MARKER = "IntelliJ IDEA Global Settings"; |
| |
| /** |
| * Parse and update the IDEA settings in the jar at <code>path</code>. |
| * Note: This function might require a restart of the application. |
| * @param path The location of the jar with the new IDEA settings. |
| */ |
| public static void doImport(String path) { |
| final File saveFile = new File(path); |
| try { |
| if (!saveFile.exists()) { |
| Messages.showErrorDialog(IdeBundle.message("error.cannot.find.file", presentableFileName(saveFile)), DIALOG_TITLE); |
| return; |
| } |
| |
| // What is this file used for? |
| final ZipEntry magicEntry = new ZipFile(saveFile).getEntry(SETTINGS_JAR_MARKER); |
| if (magicEntry == null) { |
| Messages.showErrorDialog("The file " + presentableFileName(saveFile) + " contains no settings to import", |
| DIALOG_TITLE); |
| return; |
| } |
| |
| final ArrayList<ExportableComponent> registeredComponents = new ArrayList<ExportableComponent>( |
| Arrays.asList(ApplicationManager.getApplication().getComponents(ExportableApplicationComponent.class))); |
| registeredComponents.addAll(ServiceBean.loadServicesFromBeans(ExportableComponent.EXTENSION_POINT, ExportableComponent.class)); |
| |
| List<ExportableComponent> storedComponents = getComponentsStored(saveFile, registeredComponents); |
| |
| Set<String> relativeNamesToExtract = new HashSet<String>(); |
| for (final ExportableComponent aComponent : storedComponents) { |
| final File[] exportFiles = aComponent.getExportFiles(); |
| for (File exportFile : exportFiles) { |
| final File configPath = new File(PathManager.getConfigPath()); |
| final String rPath = FileUtil.getRelativePath(configPath, exportFile); |
| assert rPath != null; |
| final String relativePath = FileUtil.toSystemIndependentName(rPath); |
| relativeNamesToExtract.add(relativePath); |
| } |
| } |
| |
| relativeNamesToExtract.add(PluginManager.INSTALLED_TXT); |
| |
| final File tempFile = new File(PathManager.getPluginTempPath() + "/" + saveFile.getName()); |
| FileUtil.copy(saveFile, tempFile); |
| File outDir = new File(PathManager.getConfigPath()); |
| final ImportSettingsFilenameFilter filenameFilter = new ImportSettingsFilenameFilter(relativeNamesToExtract); |
| StartupActionScriptManager.ActionCommand unzip = new StartupActionScriptManager.UnzipCommand(tempFile, outDir, filenameFilter); |
| StartupActionScriptManager.addActionCommand(unzip); |
| |
| // remove temp file |
| StartupActionScriptManager.ActionCommand deleteTemp = new StartupActionScriptManager.DeleteCommand(tempFile); |
| StartupActionScriptManager.addActionCommand(deleteTemp); |
| |
| UpdateSettings.getInstance().forceCheckForUpdateAfterRestart(); |
| |
| String key = ApplicationManager.getApplication().isRestartCapable() |
| ? "message.settings.imported.successfully.restart" |
| : "message.settings.imported.successfully"; |
| final int ret = Messages.showOkCancelDialog(IdeBundle.message(key, |
| ApplicationNamesInfo.getInstance().getProductName(), |
| ApplicationNamesInfo.getInstance().getFullProductName()), |
| IdeBundle.message("title.restart.needed"), Messages.getQuestionIcon()); |
| if (ret == Messages.OK) { |
| ((ApplicationEx)ApplicationManager.getApplication()).restart(true); |
| } |
| } |
| catch (ZipException e1) { |
| Messages.showErrorDialog( |
| "Error reading file " + presentableFileName(saveFile) + ".\\nThere was " + e1.getMessage(), |
| DIALOG_TITLE); |
| } |
| catch (IOException e1) { |
| Messages.showErrorDialog(IdeBundle.message("error.reading.settings.file.2", presentableFileName(saveFile), e1.getMessage()), |
| DIALOG_TITLE); |
| } |
| } |
| |
| private static String presentableFileName(final File file) { |
| return "'" + FileUtil.toSystemDependentName(file.getPath()) + "'"; |
| } |
| |
| private static List<ExportableComponent> getComponentsStored(File zipFile, |
| ArrayList<ExportableComponent> registeredComponents) |
| throws IOException { |
| final File configPath = new File(PathManager.getConfigPath()); |
| |
| final ArrayList<ExportableComponent> components = new ArrayList<ExportableComponent>(); |
| for (ExportableComponent component : registeredComponents) { |
| final File[] exportFiles = component.getExportFiles(); |
| for (File exportFile : exportFiles) { |
| final String rPath = FileUtil.getRelativePath(configPath, exportFile); |
| assert rPath != null; |
| String relativePath = FileUtil.toSystemIndependentName(rPath); |
| if (exportFile.isDirectory()) relativePath += "/"; |
| if (ZipUtil.isZipContainsEntry(zipFile, relativePath)) { |
| components.add(component); |
| break; |
| } |
| } |
| } |
| return components; |
| } |
| } |