Import/Export SettingsAction in kotlin

This commit is contained in:
Vladimir Krivosheev
2015-09-29 17:06:18 +02:00
parent 9b2970ef73
commit bc167c32a0
3 changed files with 314 additions and 405 deletions
@@ -13,320 +13,255 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.ide.actions
/**
* @author cdr
*/
package com.intellij.ide.actions;
import com.intellij.AbstractBundle
import com.intellij.CommonBundle
import com.intellij.ide.IdeBundle
import com.intellij.ide.plugins.IdeaPluginDescriptor
import com.intellij.ide.plugins.PluginManager
import com.intellij.ide.plugins.PluginManagerCore
import com.intellij.openapi.actionSystem.AnAction
import com.intellij.openapi.actionSystem.AnActionEvent
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.application.PathManager
import com.intellij.openapi.application.impl.ApplicationImpl
import com.intellij.openapi.components.*
import com.intellij.openapi.components.impl.ServiceManagerImpl
import com.intellij.openapi.components.impl.stores.StateStorageManager
import com.intellij.openapi.components.impl.stores.StoreUtil
import com.intellij.openapi.diagnostic.Logger
import com.intellij.openapi.extensions.PluginDescriptor
import com.intellij.openapi.options.OptionsBundle
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.openapi.util.text.StringUtil
import com.intellij.openapi.vfs.CharsetToolkit
import com.intellij.util.PairProcessor
import com.intellij.util.PlatformUtils
import com.intellij.util.ReflectionUtil
import com.intellij.util.containers.ContainerUtil
import com.intellij.util.containers.MultiMap
import com.intellij.util.io.ZipUtil
import gnu.trove.THashSet
import com.intellij.AbstractBundle;
import com.intellij.CommonBundle;
import com.intellij.ide.IdeBundle;
import com.intellij.ide.plugins.IdeaPluginDescriptor;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.application.impl.ApplicationImpl;
import com.intellij.openapi.components.*;
import com.intellij.openapi.components.impl.ServiceManagerImpl;
import com.intellij.openapi.components.impl.stores.StateStorageManager;
import com.intellij.openapi.components.impl.stores.StoreUtil;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.extensions.PluginDescriptor;
import com.intellij.openapi.options.OptionsBundle;
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.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.util.PairProcessor;
import com.intellij.util.PlatformUtils;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.io.ZipUtil;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.*
import java.util.*
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
private class ExportSettingsAction : AnAction(), DumbAware {
override fun actionPerformed(e: AnActionEvent?) {
ApplicationManager.getApplication().saveSettings()
public class ExportSettingsAction extends AnAction implements DumbAware {
private static final Logger LOG = Logger.getInstance(ExportSettingsAction.class);
@Override
public void actionPerformed(@Nullable AnActionEvent e) {
ApplicationManager.getApplication().saveSettings();
ChooseComponentsToExportDialog dialog = new ChooseComponentsToExportDialog(getExportableComponentsMap(true, true), true,
IdeBundle.message("title.select.components.to.export"),
IdeBundle.message(
"prompt.please.check.all.components.to.export"));
val dialog = ChooseComponentsToExportDialog(getExportableComponentsMap(true, true), true,
IdeBundle.message("title.select.components.to.export"),
IdeBundle.message(
"prompt.please.check.all.components.to.export"))
if (!dialog.showAndGet()) {
return;
return
}
Set<ExportableComponent> markedComponents = dialog.getExportableComponents();
val markedComponents = dialog.exportableComponents
if (markedComponents.isEmpty()) {
return;
return
}
Set<File> exportFiles = new THashSet<File>(FileUtil.FILE_HASHING_STRATEGY);
for (ExportableComponent markedComponent : markedComponents) {
ContainerUtil.addAll(exportFiles, markedComponent.getExportFiles());
val exportFiles = THashSet(FileUtil.FILE_HASHING_STRATEGY)
for (markedComponent in markedComponents) {
ContainerUtil.addAll<File, File, Set<File>>(exportFiles, *markedComponent.exportFiles)
}
final File saveFile = dialog.getExportFile();
val saveFile = dialog.exportFile
try {
if (saveFile.exists() && Messages.showOkCancelDialog(
IdeBundle.message("prompt.overwrite.settings.file", FileUtil.toSystemDependentName(saveFile.getPath())),
IdeBundle.message("prompt.overwrite.settings.file", FileUtil.toSystemDependentName(saveFile.path)),
IdeBundle.message("title.file.already.exists"), Messages.getWarningIcon()) != Messages.OK) {
return;
return
}
MyZipOutputStream zipOut = new MyZipOutputStream(new BufferedOutputStream(new FileOutputStream(saveFile)));
val zipOut = MyZipOutputStream(BufferedOutputStream(FileOutputStream(saveFile)))
try {
Set<String> writtenItemRelativePaths = new THashSet<String>();
String configRoot = FileUtilRt.toSystemIndependentName(PathManager.getConfigPath());
for (File file : exportFiles) {
val writtenItemRelativePaths = THashSet<String>()
val configRoot = FileUtilRt.toSystemIndependentName(PathManager.getConfigPath())
for (file in exportFiles) {
if (file.exists()) {
String relativePath = FileUtilRt.getRelativePath(configRoot, FileUtilRt.toSystemIndependentName(file.getAbsolutePath()), '/');
assert relativePath != null;
ZipUtil.addFileOrDirRecursively(zipOut, null, file, relativePath, null, writtenItemRelativePaths);
val relativePath = FileUtilRt.getRelativePath(configRoot, FileUtilRt.toSystemIndependentName(file.absolutePath), '/')!!
ZipUtil.addFileOrDirRecursively(zipOut, null, file, relativePath, null, writtenItemRelativePaths)
}
}
exportInstalledPlugins(zipOut);
exportInstalledPlugins(zipOut)
ZipEntry zipEntry = new ZipEntry(ImportSettingsFilenameFilter.SETTINGS_JAR_MARKER);
zipOut.putNextEntry(zipEntry);
zipOut.closeEntry();
val zipEntry = ZipEntry(ImportSettingsFilenameFilter.SETTINGS_JAR_MARKER)
zipOut.putNextEntry(zipEntry)
zipOut.closeEntry()
}
finally {
zipOut.doClose();
zipOut.doClose()
}
ShowFilePathAction.showDialog(getEventProject(e), IdeBundle.message("message.settings.exported.successfully"),
IdeBundle.message("title.export.successful"), saveFile, null);
ShowFilePathAction.showDialog(AnAction.getEventProject(e), IdeBundle.message("message.settings.exported.successfully"),
IdeBundle.message("title.export.successful"), saveFile, null)
}
catch (IOException e1) {
Messages.showErrorDialog(IdeBundle.message("error.writing.settings", e1.toString()), IdeBundle.message("title.error.writing.file"));
}
}
private static void exportInstalledPlugins(@NotNull MyZipOutputStream zipOut) throws IOException {
List<String> plugins = new ArrayList<String>();
for (IdeaPluginDescriptor descriptor : PluginManagerCore.getPlugins()) {
if (!descriptor.isBundled() && descriptor.isEnabled()) {
plugins.add(descriptor.getPluginId().getIdString());
}
}
if (plugins.isEmpty()) {
return;
}
ZipEntry e = new ZipEntry(PluginManager.INSTALLED_TXT);
zipOut.putNextEntry(e);
try {
PluginManagerCore.writePluginsList(plugins, new OutputStreamWriter(zipOut, CharsetToolkit.UTF8_CHARSET));
}
finally {
zipOut.closeEntry();
}
}
private static class MyZipOutputStream extends ZipOutputStream {
private boolean ignoreClose = true;
public MyZipOutputStream(@NotNull OutputStream out) {
super(out);
}
@Override
public void close() throws IOException {
if (!ignoreClose) {
doClose();
}
}
public void doClose() throws IOException {
super.close();
}
}
@NotNull
public static MultiMap<File, ExportableComponent> getExportableComponentsMap(boolean onlyExisting, boolean computePresentableNames) {
ApplicationImpl application = (ApplicationImpl)ApplicationManager.getApplication();
StateStorageManager storageManager = ComponentsPackage.getStateStore(application).getStateStorageManager();
return getExportableComponentsMap(onlyExisting, computePresentableNames, storageManager);
}
@NotNull
public static MultiMap<File, ExportableComponent> getExportableComponentsMap(final boolean onlyExisting, final boolean computePresentableNames, final @NotNull StateStorageManager storageManager) {
@SuppressWarnings("deprecation")
List<ExportableApplicationComponent> components1 = ComponentsPackage.getComponents(ApplicationManager.getApplication(), ExportableApplicationComponent.class);
List<ExportableComponent> components2 = ServiceBean.loadServicesFromBeans(ExportableComponent.EXTENSION_POINT, ExportableComponent.class);
final MultiMap<File, ExportableComponent> result = MultiMap.createLinkedSet();
for (ExportableComponent component : ContainerUtil.concat(components1, components2)) {
for (File exportFile : component.getExportFiles()) {
result.putValue(exportFile, component);
}
}
if (onlyExisting) {
for (Iterator<File> it = result.keySet().iterator(); it.hasNext(); ) {
if (!it.next().exists()) {
it.remove();
}
}
}
ServiceManagerImpl.processAllImplementationClasses((ApplicationImpl)ApplicationManager.getApplication(), new PairProcessor<Class<?>, PluginDescriptor>() {
@Override
public boolean process(@NotNull Class<?> aClass, @Nullable PluginDescriptor pluginDescriptor) {
State stateAnnotation = StoreUtil.getStateSpec(aClass);
if (stateAnnotation != null && !StringUtil.isEmpty(stateAnnotation.name())) {
if (ExportableComponent.class.isAssignableFrom(aClass)) {
return true;
}
int storageIndex;
Storage[] storages = stateAnnotation.storages();
if (storages.length == 1) {
storageIndex = 0;
}
else {
return true;
}
Storage storage = storages[storageIndex];
if (storage.roamingType() != RoamingType.DISABLED &&
storage.storageClass().equals(StateStorage.class) &&
storage.scheme() == StorageScheme.DEFAULT &&
!StringUtil.isEmpty(storage.file()) &&
storage.file().startsWith(StoragePathMacros.APP_CONFIG)) {
File additionalExportFile = null;
if (!StringUtil.isEmpty(stateAnnotation.additionalExportFile())) {
String expandedPath = storageManager.expandMacros(stateAnnotation.additionalExportFile());
additionalExportFile = new File(expandedPath);
if (!additionalExportFile.exists()) {
//noinspection deprecation
additionalExportFile = new File(storageManager.expandMacros(StoragePathMacros.ROOT_CONFIG) + '/' + expandedPath);
}
if (onlyExisting && !additionalExportFile.exists()) {
additionalExportFile = null;
}
}
File file = new File(storageManager.expandMacros(storage.file()));
boolean fileExists = !onlyExisting || file.exists();
if (fileExists || additionalExportFile != null) {
File[] files;
if (additionalExportFile == null) {
files = new File[]{file};
}
else {
files = fileExists ? new File[]{file, additionalExportFile} : new File[]{additionalExportFile};
}
ExportableComponentItem item = new ExportableComponentItem(files,
computePresentableNames
? getComponentPresentableName(stateAnnotation, aClass, pluginDescriptor)
: "",
storage.roamingType());
result.putValue(file, item);
if (additionalExportFile != null) {
result.putValue(additionalExportFile, item);
}
}
}
}
return true;
}
});
return result;
}
@NotNull
private static String getComponentPresentableName(@NotNull State state, @NotNull Class<?> aClass, @Nullable PluginDescriptor pluginDescriptor) {
if (state.presentableName() != State.NameGetter.class) {
try {
return ReflectionUtil.newInstance(state.presentableName()).get();
}
catch (Exception e) {
LOG.error(e);
}
}
String defaultName = state.name();
String resourceBundleName;
if (pluginDescriptor != null && pluginDescriptor instanceof IdeaPluginDescriptor && !"com.intellij".equals(pluginDescriptor.getPluginId().getIdString())) {
resourceBundleName = ((IdeaPluginDescriptor)pluginDescriptor).getResourceBundleBaseName();
}
else {
resourceBundleName = OptionsBundle.PATH_TO_BUNDLE;
}
if (resourceBundleName == null) {
return defaultName;
}
ClassLoader classLoader = pluginDescriptor == null ? null : pluginDescriptor.getPluginClassLoader();
classLoader = classLoader == null ? aClass.getClassLoader() : classLoader;
if (classLoader != null) {
String message = messageOrDefault(classLoader, resourceBundleName, defaultName);
if (message != defaultName) {
return message;
}
if (PlatformUtils.isRubyMine()) {
// ruby plugin in RubyMine has id "com.intellij", so, we cannot set "resource-bundle" in plugin.xml
return messageOrDefault(classLoader, "org.jetbrains.plugins.ruby.RBundle", defaultName);
}
}
return defaultName;
}
@NotNull
private static String messageOrDefault(@NotNull ClassLoader classLoader, @NotNull String bundleName, @NotNull String defaultName) {
ResourceBundle bundle = AbstractBundle.getResourceBundle(bundleName, classLoader);
return bundle == null ? defaultName : CommonBundle.messageOrDefault(bundle, "exportable." + defaultName + ".presentable.name", defaultName);
}
public static final class ExportableComponentItem implements ExportableComponent {
private final File[] files;
private final String name;
private final RoamingType roamingType;
public ExportableComponentItem(@NotNull File[] files, @NotNull String name, @NotNull RoamingType roamingType) {
this.files = files;
this.name = name;
this.roamingType = roamingType;
}
@NotNull
@Override
public File[] getExportFiles() {
return files;
}
@NotNull
@Override
public String getPresentableName() {
return name;
}
@NotNull
public RoamingType getRoamingType() {
return roamingType;
catch (e1: IOException) {
Messages.showErrorDialog(IdeBundle.message("error.writing.settings", e1.toString()), IdeBundle.message("title.error.writing.file"))
}
}
}
private class MyZipOutputStream(out: OutputStream) : ZipOutputStream(out) {
override fun close() {
}
fun doClose() {
super.close()
}
}
class ExportableComponentItem(private val files: Array<File>, private val name: String, val roamingType: RoamingType) : ExportableComponent {
override fun getExportFiles() = files
override fun getPresentableName() = name
}
private val LOG = Logger.getInstance(ExportSettingsAction::class.java)
private fun exportInstalledPlugins(zipOut: MyZipOutputStream) {
val plugins = ArrayList<String>()
for (descriptor in PluginManagerCore.getPlugins()) {
if (!descriptor.isBundled && descriptor.isEnabled) {
plugins.add(descriptor.pluginId.idString)
}
}
if (plugins.isEmpty()) {
return
}
val e = ZipEntry(PluginManager.INSTALLED_TXT)
zipOut.putNextEntry(e)
try {
PluginManagerCore.writePluginsList(plugins, OutputStreamWriter(zipOut, CharsetToolkit.UTF8_CHARSET))
}
finally {
zipOut.closeEntry()
}
}
fun getExportableComponentsMap(onlyExisting: Boolean, computePresentableNames: Boolean, storageManager: StateStorageManager = ApplicationManager.getApplication().stateStore.stateStorageManager): MultiMap<File, ExportableComponent> {
val result = MultiMap.createLinkedSet<File, ExportableComponent>()
val processor = { component: ExportableComponent ->
for (exportFile in component.exportFiles) {
result.putValue(exportFile, component)
}
}
@Suppress("DEPRECATED_SYMBOL_WITH_MESSAGE")
ApplicationManager.getApplication().getComponents(ExportableApplicationComponent::class.java).forEach(processor)
ServiceBean.loadServicesFromBeans(ExportableComponent.EXTENSION_POINT, ExportableComponent::class.java).forEach(processor)
if (onlyExisting) {
val it = result.keySet().iterator()
while (it.hasNext()) {
if (!it.next().exists()) {
it.remove()
}
}
}
ServiceManagerImpl.processAllImplementationClasses(ApplicationManager.getApplication() as ApplicationImpl, object : PairProcessor<Class<*>, PluginDescriptor> {
override fun process(aClass: Class<*>, pluginDescriptor: PluginDescriptor?): Boolean {
val stateAnnotation = StoreUtil.getStateSpec(aClass)
if (stateAnnotation != null && !StringUtil.isEmpty(stateAnnotation.name)) {
if (ExportableComponent::class.java.isAssignableFrom(aClass)) {
return true
}
val storageIndex: Int
val storages = stateAnnotation.storages
if (storages.size() == 1) {
storageIndex = 0
}
else {
return true
}
val storage = storages[storageIndex]
if (storage.roamingType != RoamingType.DISABLED && storage.storageClass == StateStorage::class.java && storage.scheme == StorageScheme.DEFAULT && !StringUtil.isEmpty(storage.file) && storage.file.startsWith(StoragePathMacros.APP_CONFIG)) {
var additionalExportFile: File? = null
if (!StringUtil.isEmpty(stateAnnotation.additionalExportFile)) {
val expandedPath = storageManager.expandMacros(stateAnnotation.additionalExportFile)
additionalExportFile = File(expandedPath)
if (!additionalExportFile.exists()) {
//noinspection deprecation
additionalExportFile = File(storageManager.expandMacros(StoragePathMacros.ROOT_CONFIG) + '/' + expandedPath)
}
if (onlyExisting && !additionalExportFile.exists()) {
additionalExportFile = null
}
}
val file = File(storageManager.expandMacros(storage.file))
val fileExists = !onlyExisting || file.exists()
if (fileExists || additionalExportFile != null) {
val files = if (additionalExportFile == null) {
arrayOf(file)
}
else {
if (fileExists) arrayOf(file, additionalExportFile) else arrayOf(additionalExportFile)
}
val item = ExportableComponentItem(files, if (computePresentableNames) getComponentPresentableName(stateAnnotation, aClass, pluginDescriptor) else "", storage.roamingType)
result.putValue(file, item)
if (additionalExportFile != null) {
result.putValue(additionalExportFile, item)
}
}
}
}
return true
}
})
return result
}
private fun getComponentPresentableName(state: State, aClass: Class<*>, pluginDescriptor: PluginDescriptor?): String {
val presentableName = state.presentableName.java
if (presentableName != State.NameGetter::class.java) {
try {
return ReflectionUtil.newInstance(presentableName).get()
}
catch (e: Exception) {
LOG.error(e)
}
}
val defaultName = state.name
val resourceBundleName = (if (pluginDescriptor is IdeaPluginDescriptor && "com.intellij" != pluginDescriptor.pluginId.idString) {
pluginDescriptor.resourceBundleBaseName
}
else {
OptionsBundle.PATH_TO_BUNDLE
}) ?: return defaultName
var classLoader = pluginDescriptor?.pluginClassLoader ?: aClass.classLoader
if (classLoader != null) {
val message = messageOrDefault(classLoader, resourceBundleName, defaultName)
if (message !== defaultName) {
return message
}
if (PlatformUtils.isRubyMine()) {
// ruby plugin in RubyMine has id "com.intellij", so, we cannot set "resource-bundle" in plugin.xml
return messageOrDefault(classLoader, "org.jetbrains.plugins.ruby.RBundle", defaultName)
}
}
return defaultName
}
private fun messageOrDefault(classLoader: ClassLoader, bundleName: String, defaultName: String): String {
val bundle = AbstractBundle.getResourceBundle(bundleName, classLoader) ?: return defaultName
return CommonBundle.messageOrDefault(bundle, "exportable.$defaultName.presentable.name", defaultName)
}
@@ -13,168 +13,141 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.ide.actions
/**
* @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.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.updateSettings.impl.UpdateSettings
import com.intellij.openapi.util.io.FileUtil
import com.intellij.openapi.util.io.FileUtilRt
import com.intellij.util.Consumer
import gnu.trove.THashSet
import java.io.File
import java.io.IOException
import java.util.*
import java.util.zip.ZipException
import java.util.zip.ZipFile
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.updateSettings.impl.UpdateSettings;
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 gnu.trove.THashSet;
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 {
@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) {
File saveFile = new File(path);
private class ImportSettingsAction : AnAction(), DumbAware {
override fun actionPerformed(e: AnActionEvent) {
val dataContext = e.dataContext
val 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(object : Consumer<String> {
override fun consume(path: String) {
val saveFile = File(path)
try {
doImport(saveFile);
doImport(saveFile)
}
catch (ZipException e1) {
catch (e1: ZipException) {
Messages.showErrorDialog(
IdeBundle.message("error.reading.settings.file", presentableFileName(saveFile), e1.getMessage(), promptLocationMessage()),
IdeBundle.message("title.invalid.file"));
IdeBundle.message("title.invalid.file"))
}
catch (IOException e1) {
catch (e1: IOException) {
Messages.showErrorDialog(IdeBundle.message("error.reading.settings.file.2", presentableFileName(saveFile), e1.getMessage()),
IdeBundle.message("title.error.reading.file"));
IdeBundle.message("title.error.reading.file"))
}
}
});
})
}
private static void doImport(@NotNull File saveFile) throws IOException {
private fun doImport(saveFile: File) {
if (!saveFile.exists()) {
Messages.showErrorDialog(IdeBundle.message("error.cannot.find.file", presentableFileName(saveFile)),
IdeBundle.message("title.file.not.found"));
return;
IdeBundle.message("title.file.not.found"))
return
}
@SuppressWarnings("IOResourceOpenedButNotSafelyClosed")
final ZipEntry magicEntry = new ZipFile(saveFile).getEntry(ImportSettingsFilenameFilter.SETTINGS_JAR_MARKER);
val magicEntry = 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;
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"));
val fileToComponents = getExportableComponentsMap(false, true)
val components = getComponentsStored(saveFile, fileToComponents.values())
fileToComponents.values().retainAll(components)
val dialog = ChooseComponentsToExportDialog(fileToComponents, false,
IdeBundle.message("title.select.components.to.import"),
IdeBundle.message("prompt.check.components.to.import"))
if (!dialog.showAndGet()) {
return;
return
}
final Set<ExportableComponent> chosenComponents = dialog.getExportableComponents();
Set<String> relativeNamesToExtract = new THashSet<String>();
for (ExportableComponent chosenComponent : chosenComponents) {
for (File exportFile : chosenComponent.getExportFiles()) {
String rPath = FileUtilRt.getRelativePath(new File(PathManager.getConfigPath()), exportFile);
assert rPath != null;
relativeNamesToExtract.add(FileUtil.toSystemIndependentName(rPath));
val chosenComponents = dialog.exportableComponents
val relativeNamesToExtract = THashSet<String>()
for (chosenComponent in chosenComponents) {
for (exportFile in chosenComponent.exportFiles) {
relativeNamesToExtract.add(FileUtil.toSystemIndependentName(FileUtilRt.getRelativePath(File(PathManager.getConfigPath()), exportFile)!!))
}
}
relativeNamesToExtract.add(PluginManager.INSTALLED_TXT);
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.addActionCommand(new StartupActionScriptManager.UnzipCommand(tempFile, outDir, filenameFilter));
val tempFile = File(PathManager.getPluginTempPath(), saveFile.name)
FileUtil.copy(saveFile, tempFile)
val outDir = File(PathManager.getConfigPath())
val filenameFilter = ImportSettingsFilenameFilter(relativeNamesToExtract)
StartupActionScriptManager.addActionCommand(StartupActionScriptManager.UnzipCommand(tempFile, outDir, filenameFilter))
// remove temp file
StartupActionScriptManager.addActionCommand(new StartupActionScriptManager.DeleteCommand(tempFile));
StartupActionScriptManager.addActionCommand(StartupActionScriptManager.DeleteCommand(tempFile))
UpdateSettings.getInstance().forceCheckForUpdateAfterRestart();
UpdateSettings.getInstance().forceCheckForUpdateAfterRestart()
String key = ApplicationManager.getApplication().isRestartCapable()
? "message.settings.imported.successfully.restart"
: "message.settings.imported.successfully";
val key = if (ApplicationManager.getApplication().isRestartCapable)
"message.settings.imported.successfully.restart"
else
"message.settings.imported.successfully"
if (Messages.showOkCancelDialog(IdeBundle.message(key,
ApplicationNamesInfo.getInstance().getProductName(),
ApplicationNamesInfo.getInstance().getFullProductName()),
IdeBundle.message("title.restart.needed"), Messages.getQuestionIcon()) == Messages.OK) {
((ApplicationEx)ApplicationManager.getApplication()).restart(true);
ApplicationNamesInfo.getInstance().productName,
ApplicationNamesInfo.getInstance().fullProductName),
IdeBundle.message("title.restart.needed"), Messages.getQuestionIcon()) == Messages.OK) {
(ApplicationManager.getApplication() as ApplicationEx).restart(true)
}
}
private static String presentableFileName(@NotNull File file) {
return "'" + FileUtil.toSystemDependentName(file.getPath()) + "'";
}
private fun presentableFileName(file: File) = "'" + FileUtil.toSystemDependentName(file.path) + "'"
private static String promptLocationMessage() {
return IdeBundle.message("message.please.ensure.correct.settings");
}
private fun promptLocationMessage() = IdeBundle.message("message.please.ensure.correct.settings")
@NotNull
private static List<ExportableComponent> getComponentsStored(@NotNull File settings,
@NotNull Collection<? extends ExportableComponent> registeredComponents) throws IOException {
THashSet<String> zipEntries = new THashSet<String>();
ZipFile zip = new ZipFile(settings);
try {
Enumeration enumeration = zip.entries();
private fun getComponentsStored(settings: File, registeredComponents: Collection<ExportableComponent>): List<ExportableComponent> {
val zipEntries = THashSet<String>()
ZipFile(settings).use {
val enumeration = it.entries()
while (enumeration.hasMoreElements()) {
ZipEntry zipEntry = (ZipEntry)enumeration.nextElement();
zipEntries.add(zipEntry.getName());
zipEntries.add(enumeration.nextElement().name)
}
}
finally {
zip.close();
}
File configPath = new File(PathManager.getConfigPath());
List<ExportableComponent> components = new ArrayList<ExportableComponent>();
for (ExportableComponent component : registeredComponents) {
for (File exportFile : component.getExportFiles()) {
String relativePath = FileUtilRt.getRelativePath(configPath, exportFile);
assert relativePath != null;
relativePath = FileUtilRt.toSystemIndependentName(relativePath);
if (exportFile.getName().indexOf('.') == -1 && !exportFile.isFile()) {
relativePath += '/';
val configPath = File(PathManager.getConfigPath())
val components = ArrayList<ExportableComponent>()
for (component in registeredComponents) {
for (exportFile in component.exportFiles) {
var relativePath = FileUtilRt.getRelativePath(configPath, exportFile)!!
relativePath = FileUtilRt.toSystemIndependentName(relativePath)
if (exportFile.name.indexOf('.') == -1 && !exportFile.isFile) {
relativePath += '/'
}
if (zipEntries.contains(relativePath)) {
components.add(component);
break;
components.add(component)
break
}
}
}
return components;
return components
}
}
@@ -17,7 +17,8 @@ package org.jetbrains.settingsRepository
import com.intellij.configurationStore.ROOT_CONFIG
import com.intellij.configurationStore.StateStorageManagerImpl
import com.intellij.ide.actions.ExportSettingsAction
import com.intellij.ide.actions.ExportableComponentItem
import com.intellij.ide.actions.getExportableComponentsMap
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.components.*
import com.intellij.openapi.util.io.FileUtil
@@ -27,7 +28,7 @@ import java.io.File
fun copyLocalConfig(storageManager: StateStorageManagerImpl = ApplicationManager.getApplication()!!.stateStore.stateStorageManager as StateStorageManagerImpl) {
val streamProvider = storageManager.streamProvider!! as IcsManager.IcsStreamProvider
val fileToComponents = ExportSettingsAction.getExportableComponentsMap(true, false, storageManager)
val fileToComponents = getExportableComponentsMap(true, false, storageManager)
for (file in fileToComponents.keySet()) {
val absolutePath = FileUtilRt.toSystemIndependentName(file.absolutePath)
var fileSpec = storageManager.collapseMacros(absolutePath)
@@ -69,7 +70,7 @@ private fun saveDirectory(parent: File, parentFileSpec: String, roamingType: Roa
private fun getRoamingType(components: Collection<ExportableComponent>): RoamingType {
for (component in components) {
if (component is ExportSettingsAction.ExportableComponentItem) {
if (component is ExportableComponentItem) {
return component.roamingType
}
else if (component is PersistentStateComponent<*>) {