Merge remote-tracking branch 'origin/master'
[idea/community.git] / python / src / com / jetbrains / python / sdk / flavors / WinPythonSdkFlavor.java
1 /*
2  * Copyright 2000-2013 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.jetbrains.python.sdk.flavors;
17
18 import com.google.common.collect.ImmutableMap;
19 import com.intellij.openapi.util.io.FileUtil;
20 import com.intellij.openapi.util.io.WindowsRegistryUtil;
21 import com.intellij.openapi.util.text.StringUtil;
22 import com.intellij.openapi.vfs.LocalFileSystem;
23 import com.intellij.openapi.vfs.VirtualFile;
24 import com.intellij.openapi.vfs.newvfs.NewVirtualFile;
25 import com.jetbrains.python.PythonHelpersLocator;
26
27 import java.io.File;
28 import java.util.*;
29
30 /**
31  * @author yole
32  */
33 public class WinPythonSdkFlavor extends CPythonSdkFlavor {
34   public static WinPythonSdkFlavor INSTANCE = new WinPythonSdkFlavor();
35   private static Map<String, String> ourRegistryMap =
36     ImmutableMap.of("HKEY_LOCAL_MACHINE\\SOFTWARE\\Python\\PythonCore", "python.exe",
37                     "HKEY_LOCAL_MACHINE\\SOFTWARE\\Wow6432Node\\Python\\PythonCore", "python.exe",
38                     "HKEY_LOCAL_MACHINE\\SOFTWARE\\IronPython", "ipy.exe");
39
40   private static Set<String> ourRegistryCache;
41
42   private WinPythonSdkFlavor() {
43   }
44
45   @Override
46   public Collection<String> suggestHomePaths() {
47     Set<String> candidates = new TreeSet<String>();
48     findInCandidatePaths(candidates, "python.exe", "jython.bat", "pypy.exe");
49     findInstallations(candidates, "python.exe", PythonHelpersLocator.getHelpersRoot().getParent());
50     return candidates;
51   }
52
53   private static void findInCandidatePaths(Set<String> candidates, String... exe_names) {
54     for (String name : exe_names) {
55       findInstallations(candidates, name, "C:\\", "C:\\Program Files\\");
56       findInPath(candidates, name);
57       findInRegistry(candidates);
58     }
59   }
60
61   private static void findInstallations(Set<String> candidates, String exe_name, String... roots) {
62     for (String root : roots) {
63       findSubdirInstallations(candidates, root, FileUtil.getNameWithoutExtension(exe_name), exe_name);
64     }
65   }
66
67   public static void findInPath(Collection<String> candidates, String exeName) {
68     final String path = System.getenv("PATH");
69     if (path == null) return;
70     for (String pathEntry : StringUtil.split(path, ";")) {
71       if (pathEntry.startsWith("\"") && pathEntry.endsWith("\"")) {
72         if (pathEntry.length() < 2) continue;
73         pathEntry = pathEntry.substring(1, pathEntry.length() - 1);
74       }
75       File f = new File(pathEntry, exeName);
76       if (f.exists()) {
77         candidates.add(FileUtil.toSystemDependentName(f.getPath()));
78       }
79     }
80   }
81
82   public static void findInRegistry(Collection<String> candidates) {
83     fillRegistryCache();
84     candidates.addAll(ourRegistryCache);
85   }
86
87   private static void fillRegistryCache() {
88     if (ourRegistryCache == null) {
89       ourRegistryCache = new HashSet<String>();
90       for (Map.Entry<String, String> entry : ourRegistryMap.entrySet()) {
91         final String prefix = entry.getKey();
92         final String exePath = entry.getValue();
93         List<String> strings = WindowsRegistryUtil.readRegistryBranch(prefix);
94         for (String string : strings) {
95           final String path = WindowsRegistryUtil.readRegistryDefault(prefix + "\\" + string +
96                                                                       "\\InstallPath");
97           if (path != null) {
98             File f = new File(path, exePath);
99             if (f.exists()) {
100               ourRegistryCache.add(FileUtil.toSystemDependentName(f.getPath()));
101             }
102           }
103         }
104       }
105     }
106   }
107
108   private static void findSubdirInstallations(Collection<String> candidates, String rootDir, String dir_prefix, String exe_name) {
109     VirtualFile rootVDir = LocalFileSystem.getInstance().findFileByPath(rootDir);
110     if (rootVDir != null) {
111       if (rootVDir instanceof NewVirtualFile) {
112         ((NewVirtualFile)rootVDir).markDirty();
113       }
114       rootVDir.refresh(true, false);
115       for (VirtualFile dir : rootVDir.getChildren()) {
116         if (dir.isDirectory() && dir.getName().toLowerCase().startsWith(dir_prefix)) {
117           VirtualFile python_exe = dir.findChild(exe_name);
118           if (python_exe != null) candidates.add(FileUtil.toSystemDependentName(python_exe.getPath()));
119         }
120       }
121     }
122   }
123 }