/*
* Copyright 2000-2014 JetBrains s.r.o.
*
* 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.
*/
/**
* @author cdr
*/
package com.intellij.ide.actions;
import com.intellij.ide.IdeBundle;
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.actionSystem.DataContext;
import com.intellij.openapi.actionSystem.PlatformDataKeys;
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.ExportableComponent;
import com.intellij.openapi.project.DumbAware;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.io.FileUtilRt;
import com.intellij.util.Consumer;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.io.ZipUtil;
import consulo.annotations.RequiredDispatchThread;
import consulo.ide.updateSettings.UpdateSettings;
import org.jetbrains.annotations.NotNull;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.util.*;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
public class ImportSettingsAction extends AnAction implements DumbAware {
@RequiredDispatchThread
@Override
public void actionPerformed(@NotNull AnActionEvent e) {
final DataContext dataContext = e.getDataContext();
final Component component = PlatformDataKeys.CONTEXT_COMPONENT.getData(dataContext);
ChooseComponentsToExportDialog.chooseSettingsFile(PathManager.getConfigPath(), component, IdeBundle.message("title.import.file.location"),
IdeBundle.message("prompt.choose.import.file.path")).doWhenDone(new Consumer<String>() {
@Override
public void consume(String path) {
doImport(path);
}
});
}
private 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)), IdeBundle.message("title.file.not.found"));
return;
}
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
final ZipEntry magicEntry = new ZipFile(saveFile).getEntry(ImportSettingsFilenameFilter.SETTINGS_JAR_MARKER);
if (magicEntry == null) {
Messages.showErrorDialog(IdeBundle.message("error.file.contains.no.settings.to.import", presentableFileName(saveFile), promptLocationMessage()),
IdeBundle.message("title.invalid.file"));
return;
}
MultiMap<File, ExportableComponent> fileToComponents = ExportSettingsAction.getExportableComponentsMap(false, true);
List<ExportableComponent> components = getComponentsStored(saveFile, fileToComponents.values());
fileToComponents.values().retainAll(components);
final ChooseComponentsToExportDialog dialog =
new ChooseComponentsToExportDialog(fileToComponents, false, IdeBundle.message("title.select.components.to.import"),
IdeBundle.message("prompt.check.components.to.import"));
if (!dialog.showAndGet()) {
return;
}
final Set<ExportableComponent> chosenComponents = dialog.getExportableComponents();
Set<String> relativeNamesToExtract = new HashSet<>();
for (final ExportableComponent chosenComponent : chosenComponents) {
final File[] exportFiles = chosenComponent.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().setLastTimeCheck(0);
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(IdeBundle.message("error.reading.settings.file", presentableFileName(saveFile), e1.getMessage(), promptLocationMessage()),
IdeBundle.message("title.invalid.file"));
}
catch (IOException e1) {
Messages.showErrorDialog(IdeBundle.message("error.reading.settings.file.2", presentableFileName(saveFile), e1.getMessage()),
IdeBundle.message("title.error.reading.file"));
}
}
private static String presentableFileName(final File file) {
return "'" + FileUtil.toSystemDependentName(file.getPath()) + "'";
}
private static String promptLocationMessage() {
return IdeBundle.message("message.please.ensure.correct.settings");
}
@NotNull
private static List<ExportableComponent> getComponentsStored(@NotNull File zipFile, @NotNull Collection<? extends ExportableComponent> registeredComponents)
throws IOException {
File configPath = new File(PathManager.getConfigPath());
List<ExportableComponent> components = new ArrayList<>();
for (ExportableComponent component : registeredComponents) {
for (File exportFile : component.getExportFiles()) {
String rPath = FileUtilRt.getRelativePath(configPath, exportFile);
assert rPath != null;
String relativePath = FileUtilRt.toSystemIndependentName(rPath);
if (exportFile.isDirectory()) {
relativePath += '/';
}
if (ZipUtil.isZipContainsEntry(zipFile, relativePath)) {
components.add(component);
break;
}
}
}
return components;
}
}