com.intellij.openapi.application.ConfigImportHelper Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of platform-impl Show documentation
Show all versions of platform-impl Show documentation
A packaging of the IntelliJ Community Edition platform-impl library.
This is release number 1 of trunk branch 142.
The newest version!
/*
* 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.
*/
package com.intellij.openapi.application;
import com.intellij.ide.plugins.IdeaPluginDescriptorImpl;
import com.intellij.ide.plugins.PluginManager;
import com.intellij.ide.plugins.PluginManagerCore;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.ui.AppUIUtil;
import com.intellij.util.*;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.util.ArrayList;
import java.util.List;
import java.util.PropertyResourceBundle;
/**
* @author max
*/
public class ConfigImportHelper {
/**
* Holds name of the system property that is supposed to hold 'true'
value when IDE settings have been
* imported on the current startup
*/
@NonNls public static final String CONFIG_IMPORTED_IN_CURRENT_SESSION_KEY = "intellij.config.imported.in.current.session";
@NonNls private static final String BUILD_NUMBER_FILE = SystemInfo.isMac ? "/Resources/build.txt" : "build.txt";
@NonNls private static final String PLUGINS_PATH = "plugins";
@NonNls private static final String BIN_FOLDER = "bin";
@NonNls private static final String CONFIG_RELATED_PATH = SystemInfo.isMac ? "" : "config/";
@NonNls private static final String OPTIONS_XML = "options/options.xml";
private ConfigImportHelper() {
}
public static void importConfigsTo(@NotNull String newConfigPath) {
ConfigImportSettings settings = getConfigImportSettings();
File newConfigDir = new File(newConfigPath);
File oldConfigDir = findOldConfigDir(newConfigDir, settings.getCustomPathsSelector());
do {
ImportOldConfigsPanel dialog = new ImportOldConfigsPanel(oldConfigDir, settings);
dialog.setModalityType(Dialog.ModalityType.TOOLKIT_MODAL);
AppUIUtil.updateWindowIcon(dialog);
dialog.setVisible(true);
if (dialog.isImportEnabled()) {
File installationHome = dialog.getSelectedFile();
oldConfigDir = getOldConfigDir(installationHome, settings);
if (!validateOldConfigDir(installationHome, oldConfigDir, settings)) {
continue;
}
assert oldConfigDir != null;
doImport(newConfigDir, oldConfigDir, settings, installationHome);
settings.importFinished(newConfigPath);
System.setProperty(CONFIG_IMPORTED_IN_CURRENT_SESSION_KEY, Boolean.TRUE.toString());
}
break;
}
while (true);
}
@NotNull
private static ConfigImportSettings getConfigImportSettings() {
try {
@SuppressWarnings("unchecked")
Class customProviderClass =
(Class)Class.forName("com.intellij.openapi.application." + PlatformUtils.getPlatformPrefix() + "ConfigImportSettings");
if (ConfigImportSettings.class.isAssignableFrom(customProviderClass)) {
return ReflectionUtil.newInstance(customProviderClass);
}
}
catch (ClassNotFoundException ignored) {
}
catch (RuntimeException ignored) {
}
return new ConfigImportSettings();
}
@Nullable
private static File findOldConfigDir(@NotNull File configDir, @Nullable String customPathSelector) {
final File selectorDir = CONFIG_RELATED_PATH.isEmpty() ? configDir : configDir.getParentFile();
final File parent = selectorDir.getParentFile();
if (parent == null || !parent.exists()) {
return null;
}
File maxFile = null;
long lastModified = 0;
final String selector = PathManager.getPathsSelector() != null ? PathManager.getPathsSelector() : selectorDir.getName();
final String prefix = getPrefixFromSelector(selector);
final String customPrefix = customPathSelector != null ? getPrefixFromSelector(customPathSelector) : null;
for (File file : parent.listFiles(new FilenameFilter() {
@Override
public boolean accept(@NotNull File file, @NotNull String name) {
return StringUtil.startsWithIgnoreCase(name, prefix) ||
customPrefix != null && StringUtil.startsWithIgnoreCase(name, customPrefix);
}
})) {
File options = new File(file, CONFIG_RELATED_PATH + OPTIONS_XML);
if (!options.exists()) {
continue;
}
long modified = options.lastModified();
if (modified > lastModified) {
lastModified = modified;
maxFile = file;
}
}
return maxFile != null ? new File(maxFile, CONFIG_RELATED_PATH) : null;
}
private static String getPrefixFromSelector(String selector) {
return (SystemInfo.isMac ? "" : ".") + selector.replaceAll("\\d", "");
}
private static void doImport(@NotNull File newConfigDir, @NotNull File oldConfigDir, ConfigImportSettings settings, File installationHome) {
try {
copy(oldConfigDir, newConfigDir, settings, installationHome);
}
catch (IOException e) {
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
ApplicationBundle.message("error.unable.to.import.settings", e.getMessage()),
ApplicationBundle.message("title.settings.import.failed"), JOptionPane.WARNING_MESSAGE);
}
}
private static boolean validateOldConfigDir(@Nullable File installationHome, @Nullable File oldConfigDir, @NotNull ConfigImportSettings settings) {
if (oldConfigDir == null) {
if (installationHome != null) {
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
ApplicationBundle.message("error.invalid.installation.home", installationHome.getAbsolutePath(), settings.getProductName(ThreeState.YES)));
}
return false;
}
if (!oldConfigDir.exists()) {
JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
ApplicationBundle.message("error.no.settings.path",
oldConfigDir.getAbsolutePath()),
ApplicationBundle.message("title.settings.import.failed"), JOptionPane.WARNING_MESSAGE);
return false;
}
return true;
}
private static void copy(@NotNull File src, @NotNull File dest, ConfigImportSettings settings, File oldInstallationHome) throws IOException {
src = src.getCanonicalFile();
dest = dest.getCanonicalFile();
if (!src.isDirectory()) {
throw new IOException(ApplicationBundle.message("config.import.invalid.directory.error", src.getAbsolutePath()));
}
if (!dest.isDirectory()) {
throw new IOException(ApplicationBundle.message("config.import.invalid.directory.error", dest.getAbsolutePath()));
}
if (FileUtil.filesEqual(src, dest)) {
return;
}
FileUtil.ensureExists(dest);
File[] childFiles = src.listFiles(new FilenameFilter() {
@Override
public boolean accept(@NotNull File dir, @NotNull String name) {
// Don't copy plugins just imported. They're most probably incompatible with newer idea version.
return !StringUtil.startsWithChar(name, '.') && !name.equals(PLUGINS_PATH);
}
});
if (childFiles == null || childFiles.length == 0) {
return;
}
for (File from : childFiles) {
File to = new File(dest, from.getName());
if (from.isDirectory()) {
FileUtil.copyDir(from, to, false);
}
else {
FileUtil.copy(from, to);
}
}
File plugins = new File(src, PLUGINS_PATH);
if (!loadOldPlugins(plugins, dest) && SystemInfo.isMac) {
File oldPluginsDir = getOldPath(oldInstallationHome, settings, PathManager.PROPERTY_PLUGINS_PATH,
new Function() {
@Override
public String fun(String pathSelector) {
return PathManager.getDefaultPluginPathFor(pathSelector);
}
});
if (oldPluginsDir == null) {
//e.g. installation home referred to config home. Try with default selector, same as config name
oldPluginsDir = new File(PathManager.getDefaultPluginPathFor(src.getName()));
}
loadOldPlugins(oldPluginsDir, dest);
}
}
private static boolean loadOldPlugins(File plugins, File dest) throws IOException {
if (plugins.exists()) {
List descriptors = new SmartList();
PluginManagerCore.loadDescriptors(plugins, descriptors, null, 0);
List oldPlugins = new SmartList();
for (IdeaPluginDescriptorImpl descriptor : descriptors) {
// check isBundled also - probably plugin is bundled in new IDE version
if (descriptor.isEnabled() && !descriptor.isBundled()) {
oldPlugins.add(descriptor.getPluginId().getIdString());
}
}
if (!oldPlugins.isEmpty()) {
PluginManagerCore.savePluginsList(oldPlugins, false, new File(dest, PluginManager.INSTALLED_TXT));
}
return true;
}
return false;
}
@Nullable
public static File getOldConfigDir(@Nullable File oldInstallHome, ConfigImportSettings settings) {
if (oldInstallHome == null) {
return null;
}
// check if it's already config dir
if (new File(oldInstallHome, OPTIONS_XML).exists()) {
return oldInstallHome;
}
if (new File(oldInstallHome, CONFIG_RELATED_PATH + OPTIONS_XML).exists()) {
return new File(oldInstallHome, CONFIG_RELATED_PATH);
}
int oldBuildNumber = getBuildNumber(oldInstallHome);
if (oldBuildNumber != -1 && oldBuildNumber <= 600) { // Pandora
//noinspection HardCodedStringLiteral
return new File(oldInstallHome, "config");
}
return getOldPath(oldInstallHome, settings, PathManager.PROPERTY_CONFIG_PATH, new Function() {
@Override
public String fun(String pathsSelector) {
return PathManager.getDefaultConfigPathFor(pathsSelector);
}
});
}
private static File getOldPath(final File oldInstallHome,
final ConfigImportSettings settings,
final String propertyName,
final Function fromPathSelector) {
final File[] launchFileCandidates = getLaunchFilesCandidates(oldInstallHome, settings);
// custom config folder
for (File candidate : launchFileCandidates) {
if (candidate.exists()) {
String configDir = PathManager.substituteVars(getPropertyFromLaxFile(candidate, propertyName),
oldInstallHome.getPath());
if (configDir != null) {
File probableConfig = new File(configDir);
if (probableConfig.exists()) return probableConfig;
}
}
}
// custom config folder not found - use paths selector
for (File candidate : launchFileCandidates) {
if (candidate.exists()) {
final String pathsSelector = getPropertyFromLaxFile(candidate, PathManager.PROPERTY_PATHS_SELECTOR);
if (pathsSelector != null) {
final String configDir = fromPathSelector.fun(pathsSelector);
final File probableConfig = new File(configDir);
if (probableConfig.exists()) {
return probableConfig;
}
}
}
}
return null;
}
@SuppressWarnings({"HardCodedStringLiteral"})
private static File[] getLaunchFilesCandidates(@NotNull final File instHome, @NotNull final ConfigImportSettings settings) {
final File bin = new File(instHome, BIN_FOLDER);
final List files = new ArrayList();
if (SystemInfo.isMac) {
// Info.plist
files.add(new File(new File(instHome, "Contents"), "Info.plist"));
files.add(new File(new File(new File(bin, "idea.app"), "Contents"), "Info.plist"));
files.add(new File(new File(new File(instHome, "idea.app"), "Contents"), "Info.plist"));
}
// idea.properties
files.add(new File(bin, "idea.properties"));
// other binary scripts
final String executableName = StringUtil.toLowerCase(settings.getExecutableName());
// * defaults:
addLaunchExecutableScriptsCandidates(files, executableName, bin);
// * customized files:
files.addAll(settings.getCustomLaunchFilesCandidates(instHome, bin));
// * legacy support:
if (!"idea".equals(executableName)) {
// for compatibility with some platform-base IDEs with wrong executable names
addLaunchExecutableScriptsCandidates(files, "idea", bin);
}
return files.toArray(new File[files.size()]);
}
private static void addLaunchExecutableScriptsCandidates(final List files,
final String executableName,
final File binFolder) {
files.add(new File(binFolder, executableName + ".lax"));
files.add(new File(binFolder, executableName + ".bat"));
files.add(new File(binFolder, executableName + ".sh"));
}
@SuppressWarnings({"HardCodedStringLiteral"})
@Nullable
public static String getPropertyFromLaxFile(@NotNull final File file,
@NotNull final String propertyName) {
if (file.getName().endsWith(".properties")) {
try {
PropertyResourceBundle bundle;
InputStream fis = new BufferedInputStream(new FileInputStream(file));
try {
bundle = new PropertyResourceBundle(fis);
}
finally {
fis.close();
}
if (bundle.containsKey(propertyName)) {
return bundle.getString(propertyName);
}
return null;
}
catch (IOException e) {
return null;
}
}
final String fileContent = getContent(file);
// try to find custom config path
final String propertyValue = findProperty(propertyName, fileContent);
if (!StringUtil.isEmpty(propertyValue)) {
return propertyValue;
}
return null;
}
@Nullable
private static String findProperty(final String propertyName,
final String fileContent) {
String param = propertyName + "=";
int idx = fileContent.indexOf(param);
if (idx == -1) {
param = "" + propertyName + " ";
idx = fileContent.indexOf(param);
if (idx == -1) return null;
idx = fileContent.indexOf("", idx);
if (idx == -1) return null;
idx += "".length();
return fixDirName(fileContent.substring(idx, fileContent.indexOf(" ", idx)), true);
}
else {
String configDir = "";
idx += param.length();
if (fileContent.length() > idx) {
if (fileContent.charAt(idx) == '"') {
idx++;
while ((fileContent.length() > idx) && (fileContent.charAt(idx) != '"') && (fileContent.charAt(idx) != '\n') &&
(fileContent.charAt(idx) != '\r')) {
configDir += fileContent.charAt(idx);
idx++;
}
}
else {
while ((fileContent.length() > idx) && (!Character.isSpaceChar(fileContent.charAt(idx))) &&
(fileContent.charAt(idx) != '\n') &&
(fileContent.charAt(idx) != '\r')) {
configDir += fileContent.charAt(idx);
idx++;
}
}
}
configDir = fixDirName(configDir, true);
if (configDir.length() > 0) {
configDir = (new File(configDir)).getPath();
}
return configDir;
}
}
@Nullable
private static String getContent(File file) {
try {
StringBuilder content = new StringBuilder();
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
try {
do {
String line = reader.readLine();
if (line == null) break;
content.append(line);
content.append('\n');
}
while (true);
}
finally {
reader.close();
}
return content.toString();
}
catch (Exception e) {
return null;
}
}
public static String fixDirName(String dir, boolean replaceUserHome) {
if (StringUtil.startsWithChar(dir, '\"') && StringUtil.endsWithChar(dir, '\"')) {
dir = dir.substring(1, dir.length() - 1);
}
if (replaceUserHome) {
dir = FileUtil.expandUserHome(dir);
}
return dir;
}
public static boolean isInstallationHomeOrConfig(@NotNull final String installationHome, @NotNull final ConfigImportSettings settings) {
if (new File(installationHome, OPTIONS_XML).exists()) return true;
if (new File(installationHome, CONFIG_RELATED_PATH + OPTIONS_XML).exists()) return true;
if (!new File(installationHome, BIN_FOLDER).exists()) {
return false;
}
File libFolder = new File(installationHome, "lib");
boolean quickTest = false;
String[] mainJarNames = settings.getMainJarNames();
for (String name : mainJarNames) {
String mainJarName = StringUtil.toLowerCase(name) + ".jar";
//noinspection HardCodedStringLiteral
if (new File(libFolder, mainJarName).exists()) {
quickTest = true;
break;
}
}
if (!quickTest) return false;
File[] files = getLaunchFilesCandidates(new File(installationHome), settings);
for (File file : files) {
if (file.exists()) return true;
}
return false;
}
private static int getBuildNumber(File installDirectory) {
installDirectory = installDirectory.getAbsoluteFile();
File buildTxt = new File(installDirectory, BUILD_NUMBER_FILE);
if ((!buildTxt.exists()) || (buildTxt.isDirectory())) {
buildTxt = new File(new File(installDirectory, BIN_FOLDER), BUILD_NUMBER_FILE);
}
if (buildTxt.exists() && !buildTxt.isDirectory()) {
int buildNumber = -1;
String buildNumberText = getContent(buildTxt);
if (buildNumberText != null) {
try {
if (buildNumberText.length() > 1) {
buildNumberText = buildNumberText.trim();
buildNumber = Integer.parseInt(buildNumberText);
}
}
catch (Exception e) {
// OK
}
}
return buildNumber;
}
return -1;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy