focus stealing issue: isActive() is more accurate + removed direct call to requestFoc...
[idea/community.git] / platform / platform-impl / src / com / intellij / openapi / application / ConfigImportHelper.java
1 /*
2  * Copyright 2000-2009 JetBrains s.r.o.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 package com.intellij.openapi.application;
17
18 import com.intellij.openapi.util.io.FileUtil;
19 import com.intellij.openapi.util.text.StringUtil;
20 import com.intellij.util.SystemProperties;
21 import com.intellij.util.ui.UIUtil;
22 import com.intellij.ui.AppUIUtil;
23 import org.jetbrains.annotations.NonNls;
24 import org.jetbrains.annotations.Nullable;
25
26 import javax.swing.*;
27 import java.io.*;
28 import java.util.PropertyResourceBundle;
29
30 /**
31  * @author max
32  */
33 public class ConfigImportHelper {
34   @NonNls private static final String BUILD_NUMBER_FILE = "build.txt";
35   @NonNls private static final String PLUGINS_PATH = "plugins";
36   @NonNls private static final String BIN_FOLDER = "bin";
37
38   private ConfigImportHelper() {}
39
40   public static void importConfigsTo(String newConfigPath) {
41     do {
42       ImportOldConfigsPanel dlg;
43       if (UIUtil.hasJdk6Dialogs()) {
44         dlg = new ImportOldConfigsPanel();
45       }
46       else {
47         dlg = new ImportOldConfigsPanel(JOptionPane.getRootFrame());
48       }
49
50       UIUtil.setToolkitModal(dlg);
51       AppUIUtil.updateDialogIcon(dlg);
52       dlg.setVisible(true);
53       if (dlg.isImportEnabled()) {
54         File instHome = dlg.getSelectedFile();
55         File oldConfigDir = getOldConfigDir(instHome);
56         if (!validateOldConfigDir(instHome, oldConfigDir)) continue;
57
58         doImport(newConfigPath, oldConfigDir);
59       }
60
61       break;
62     }
63     while (true);
64   }
65
66   public static void doImport(final String newConfigPath, final File oldConfigDir) {
67     try {
68       xcopy(oldConfigDir, new File(newConfigPath));
69     }
70     catch (IOException e) {
71       JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
72                                     ApplicationBundle.message("error.unable.to.import.settings", e.getMessage()),
73                                     ApplicationBundle.message("title.settings.import.failed"), JOptionPane.WARNING_MESSAGE);
74     }
75   }
76
77   public static boolean validateOldConfigDir(final File instHome, final File oldConfigDir) {
78     if (oldConfigDir == null) {
79       JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
80                                     ApplicationBundle.message("error.invalid.installation.home", instHome.getAbsolutePath(),
81                                                               ApplicationNamesInfo.getInstance().getFullProductName()));
82       return false;
83     }
84
85     if (!oldConfigDir.exists()) {
86       JOptionPane.showMessageDialog(JOptionPane.getRootFrame(),
87                                     ApplicationBundle.message("error.no.settings.path",
88                                                               oldConfigDir.getAbsolutePath()),
89                                     ApplicationBundle.message("title.settings.import.failed"), JOptionPane.WARNING_MESSAGE);
90       return false;
91     }
92     return true;
93   }
94
95   public static void xcopy(File src, File dest) throws IOException{
96     src = src.getCanonicalFile();
97     dest = dest.getCanonicalFile();
98     if (!src.isDirectory()){
99       throw new IOException(ApplicationBundle.message("config.import.invalid.directory.error", src.getAbsolutePath()));
100     }
101     if (!dest.isDirectory()){
102       throw new IOException(ApplicationBundle.message("config.import.invalid.directory.error", dest.getAbsolutePath()));
103     }
104     FileUtil.copyDir(src, dest);
105
106     // Delete plugins just imported. They're most probably incompatible with newer idea version.
107     File plugins = new File(dest, PLUGINS_PATH);
108     if (plugins.exists()) {
109       FileUtil.delete(plugins);
110     }
111   }
112
113   @Nullable
114   public static File getOldConfigDir(File oldInstallHome) {
115     int oldBuildNumber = getBuildNumber(oldInstallHome);
116
117     if (oldBuildNumber != -1 && oldBuildNumber <= 600) { // Pandora
118       //noinspection HardCodedStringLiteral
119       return new File(oldInstallHome, "config");
120     }
121
122     File[] launchFileCandidates = getLaunchFilesCandidates(oldInstallHome);
123     for (File file : launchFileCandidates) {
124       if (file.exists()) {
125         String configDir = PathManager.substituteVars(getConfigFromLaxFile(file), oldInstallHome.getPath());
126         if (configDir != null) {
127           File probableConfig = new File(configDir);
128           if (probableConfig.exists()) return probableConfig;
129         }
130       }
131     }
132
133     return null;
134   }
135
136   @SuppressWarnings({"HardCodedStringLiteral"})
137   private static File[] getLaunchFilesCandidates(File instHome) {
138     File bin = new File(instHome, BIN_FOLDER);
139     return new File[]{
140       new File(bin, "idea.properties"),
141       new File(bin, "idea.lax"),
142       new File(bin, "idea.bat"),
143       new File(bin, "idea.sh"),
144       new File(new File(instHome, "Contents"), "Info.plist"),
145       new File(new File(new File(bin, "idea.app"), "Contents"), "Info.plist"),
146       new File(new File(new File(instHome, "idea.app"), "Contents"), "Info.plist")
147     };
148   }
149
150   @SuppressWarnings({"HardCodedStringLiteral"})
151   @Nullable
152   public static String getConfigFromLaxFile(File file) {
153       if (file.getName().endsWith(".properties")) {
154           try {
155             InputStream fis = new BufferedInputStream(new FileInputStream(file));
156             PropertyResourceBundle bundle;
157             try {
158               bundle = new PropertyResourceBundle(fis);
159             }
160             finally {
161               fis.close();
162             }
163             return bundle.getString("idea.config.path");
164           } catch (IOException e) {
165               return null;
166           }
167       }
168
169       String fileContent = getContent(file);
170       String configParam = "idea.config.path=";
171       int idx = fileContent.indexOf(configParam);
172       if (idx == -1) {
173           configParam = "<key>idea.config.path</key>";
174           idx = fileContent.indexOf(configParam);
175           if (idx == -1) return null;
176           idx = fileContent.indexOf("<string>", idx);
177           if (idx == -1) return null;
178           idx += "<string>".length();
179           return fixDirName(fileContent.substring(idx, fileContent.indexOf("</string>", idx)), true);
180       } else {
181           String configDir = "";
182           idx += configParam.length();
183           if (fileContent.length() > idx) {
184               if (fileContent.charAt(idx) == '"') {
185                   idx++;
186                   while ((fileContent.length() > idx) && (fileContent.charAt(idx) != '"') && (fileContent.charAt(idx) != '\n') &&
187                           (fileContent.charAt(idx) != '\r')) {
188                       configDir += fileContent.charAt(idx);
189                       idx++;
190                   }
191               } else {
192                   while ((fileContent.length() > idx) && (!Character.isSpaceChar(fileContent.charAt(idx))) &&
193                           (fileContent.charAt(idx) != '\n') &&
194                           (fileContent.charAt(idx) != '\r')) {
195                       configDir += fileContent.charAt(idx);
196                       idx++;
197                   }
198               }
199           }
200           configDir = fixDirName(configDir, true);
201           if (configDir.length() > 0) {
202               configDir = (new File(configDir)).getPath();
203           }
204           return configDir;
205       }
206   }
207
208   @Nullable
209   private static String getContent(File file) {
210     try {
211       StringBuffer content = new StringBuffer();
212       BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
213       try {
214         do {
215           String line = reader.readLine();
216           if (line == null) break;
217           content.append(line);
218           content.append('\n');
219         }
220         while (true);
221       }
222       finally {
223         reader.close();
224       }
225
226       return content.toString();
227     }
228     catch (Exception e) {
229       return null;
230     }
231   }
232
233   public static String fixDirName(String dir, boolean replaceUserHome) {
234     if (StringUtil.startsWithChar(dir, '\"') && StringUtil.endsWithChar(dir, '\"')) {
235       dir = dir.substring(1, dir.length() - 1);
236     }
237     if (replaceUserHome) {
238       if (dir.startsWith("~\\") || dir.startsWith("~//") || StringUtil.startsWithConcatenationOf(dir, "~", File.separator)) {
239         dir = SystemProperties.getUserHome() + dir.substring(1);
240       }
241     }
242     return dir;
243   }
244
245   public static boolean isInstallationHome(String installationHome) {
246     String mainJarName = StringUtil.toLowerCase(ApplicationNamesInfo.getInstance().getProductName()) + ".jar";
247     //noinspection HardCodedStringLiteral
248     boolean quickTest = new File(new File(installationHome, "lib"), mainJarName).exists() &&
249                         new File(installationHome, BIN_FOLDER).exists();
250     if (!quickTest) return false;
251
252     File[] files = getLaunchFilesCandidates(new File(installationHome));
253     for (File file : files) {
254       if (file.exists()) return true;
255     }
256
257     return false;
258   }
259
260   private static int getBuildNumber(File installDirectory) {
261     installDirectory = installDirectory.getAbsoluteFile();
262
263     File buildTxt = new File(installDirectory, BUILD_NUMBER_FILE);
264     if ((!buildTxt.exists()) || (buildTxt.isDirectory())){
265       buildTxt = new File(new File(installDirectory, BIN_FOLDER), BUILD_NUMBER_FILE);
266     }
267
268     if (buildTxt.exists() && !buildTxt.isDirectory()){
269       int buildNumber = -1;
270       String buildNumberText = getContent(buildTxt);
271       if (buildNumberText != null) {
272         try{
273           if (buildNumberText.length() > 1){
274             buildNumberText = buildNumberText.trim();
275             buildNumber = Integer.parseInt(buildNumberText);
276           }
277         }
278         catch (Exception e){
279           // OK
280         }
281       }
282       return buildNumber;
283     }
284
285     return -1;
286   }
287 }