update copyright
[fedora-idea.git] / java / java-impl / src / com / intellij / openapi / projectRoots / impl / JavaSdkImpl.java
blobbd7d84816a9dba2d8f4aa768ed86d489ab2bfae3
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
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
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
16 package com.intellij.openapi.projectRoots.impl;
18 import com.intellij.openapi.application.PathManager;
19 import com.intellij.openapi.project.ProjectBundle;
20 import com.intellij.openapi.projectRoots.*;
21 import com.intellij.openapi.roots.JavadocOrderRootType;
22 import com.intellij.openapi.roots.OrderRootType;
23 import com.intellij.openapi.util.IconLoader;
24 import com.intellij.openapi.util.SystemInfo;
25 import com.intellij.openapi.vfs.JarFileSystem;
26 import com.intellij.openapi.vfs.LocalFileSystem;
27 import com.intellij.openapi.vfs.VirtualFile;
28 import com.intellij.openapi.vfs.VirtualFileManager;
29 import com.intellij.util.containers.HashMap;
30 import org.jdom.Element;
31 import org.jetbrains.annotations.NonNls;
32 import org.jetbrains.annotations.NotNull;
33 import org.jetbrains.annotations.Nullable;
35 import javax.swing.*;
36 import java.io.File;
37 import java.io.FileFilter;
38 import java.util.*;
39 import java.util.regex.Matcher;
40 import java.util.regex.Pattern;
42 /**
43 * @author Eugene Zhuravlev
44 * Date: Sep 17, 2004
46 public class JavaSdkImpl extends JavaSdk {
47 // do not use javaw.exe for Windows because of issues with encoding
48 @NonNls private static final String VM_EXE_NAME = "java";
49 @NonNls private final Pattern myVersionStringPattern = Pattern.compile("^(.*)java version \"([1234567890_.]*)\"(.*)$");
50 public static final Icon ICON = IconLoader.getIcon("/nodes/ppJdkClosed.png");
51 private static final Icon JDK_ICON_EXPANDED = IconLoader.getIcon("/nodes/ppJdkOpen.png");
52 private static final Icon ADD_ICON = IconLoader.getIcon("/general/addJdk.png");
53 @NonNls private static final String JAVA_VERSION_PREFIX = "java version ";
55 public JavaSdkImpl() {
56 super("JavaSDK");
59 public String getPresentableName() {
60 return ProjectBundle.message("sdk.java.name");
63 public Icon getIcon() {
64 return ICON;
67 public Icon getIconForExpandedTreeNode() {
68 return JDK_ICON_EXPANDED;
71 public Icon getIconForAddAction() {
72 return ADD_ICON;
75 public AdditionalDataConfigurable createAdditionalDataConfigurable(SdkModel sdkModel, SdkModificator sdkModificator) {
76 return null;
79 public void saveAdditionalData(SdkAdditionalData additionalData, Element additional) {
82 public SdkAdditionalData loadAdditionalData(Element additional) {
83 return null;
86 @SuppressWarnings({"HardCodedStringLiteral"})
87 public String getBinPath(Sdk sdk) {
88 return getConvertedHomePath(sdk) + "bin";
91 @NonNls
92 public String getToolsPath(Sdk sdk) {
93 final String versionString = sdk.getVersionString();
94 final boolean isJdk1_x = versionString != null && (versionString.contains("1.0") || versionString.contains("1.1"));
95 return getConvertedHomePath(sdk) + "lib" + File.separator + (isJdk1_x? "classes.zip" : "tools.jar");
98 public String getVMExecutablePath(Sdk sdk) {
100 if ("64".equals(System.getProperty("sun.arch.data.model"))) {
101 return getBinPath(sdk) + File.separator + System.getProperty("os.arch") + File.separator + VM_EXE_NAME;
104 return getBinPath(sdk) + File.separator + VM_EXE_NAME;
107 private static String getConvertedHomePath(Sdk sdk) {
108 String path = sdk.getHomePath().replace('/', File.separatorChar);
109 if (!path.endsWith(File.separator)) {
110 path += File.separator;
112 return path;
115 @SuppressWarnings({"HardCodedStringLiteral"})
116 public String suggestHomePath() {
117 if (SystemInfo.isMac) {
118 return "/System/Library/Frameworks/JavaVM.framework/Versions/";
120 return null;
123 public boolean isValidSdkHome(String path) {
124 return checkForJdk(new File(path));
127 public String suggestSdkName(String currentSdkName, String sdkHome) {
128 final String suggestedName;
129 if (currentSdkName != null && currentSdkName.length() > 0) {
130 final Matcher matcher = myVersionStringPattern.matcher(currentSdkName);
131 final boolean replaceNameWithVersion = matcher.matches();
132 if (replaceNameWithVersion){
133 // user did not change name -> set it automatically
134 final String versionString = getVersionString(sdkHome);
135 suggestedName = versionString == null ? currentSdkName : matcher.replaceFirst("$1" + versionString + "$3");
137 else {
138 suggestedName = currentSdkName;
141 else {
142 String versionString = getVersionString(sdkHome);
143 if (versionString != null) {
144 suggestedName = getVersionNumber(versionString);
145 } else {
146 suggestedName = ProjectBundle.message("sdk.java.unknown.name");
149 return suggestedName;
152 private static String getVersionNumber(String versionString) {
153 if (versionString.startsWith(JAVA_VERSION_PREFIX)) {
154 versionString = versionString.substring(JAVA_VERSION_PREFIX.length());
155 if (versionString.startsWith("\"") && versionString.endsWith("\"")) {
156 versionString = versionString.substring(1, versionString.length() - 1);
158 int dotIdx = versionString.indexOf('.');
159 if (dotIdx > 0) {
160 try {
161 int major = Integer.parseInt(versionString.substring(0, dotIdx));
162 int minorDot = versionString.indexOf('.', dotIdx + 1);
163 if (minorDot > 0) {
164 int minor = Integer.parseInt(versionString.substring(dotIdx + 1, minorDot));
165 versionString = String.valueOf(major) + "." + String.valueOf(minor);
168 catch (NumberFormatException e) {
169 // Do nothing. Use original version string if failed to parse according to major.minor pattern.
173 return versionString;
176 @SuppressWarnings({"HardCodedStringLiteral"})
177 public void setupSdkPaths(Sdk sdk) {
178 final File jdkHome = new File(sdk.getHomePath());
179 VirtualFile[] classes = findClasses(jdkHome, false);
180 VirtualFile sources = findSources(jdkHome);
181 VirtualFile docs = findDocs(jdkHome, "docs/api");
183 final SdkModificator sdkModificator = sdk.getSdkModificator();
184 final Set<VirtualFile> previousRoots = new LinkedHashSet<VirtualFile>(Arrays.asList(sdkModificator.getRoots(OrderRootType.CLASSES)));
185 sdkModificator.removeRoots(OrderRootType.CLASSES);
186 previousRoots.removeAll(new HashSet<VirtualFile>(Arrays.asList(classes)));
187 for (VirtualFile aClass : classes) {
188 sdkModificator.addRoot(aClass, OrderRootType.CLASSES);
190 for (VirtualFile root : previousRoots) {
191 sdkModificator.addRoot(root, OrderRootType.CLASSES);
193 if(sources != null){
194 sdkModificator.addRoot(sources, OrderRootType.SOURCES);
196 if(docs != null){
197 sdkModificator.addRoot(docs, JavadocOrderRootType.getInstance());
199 else if (SystemInfo.isMac) {
200 VirtualFile commonDocs = findDocs(jdkHome, "docs");
201 if (commonDocs == null) {
202 commonDocs = findInJar(new File(jdkHome, "docs.jar"), "doc/api");
204 if (commonDocs != null) {
205 sdkModificator.addRoot(commonDocs, JavadocOrderRootType.getInstance());
208 VirtualFile appleDocs = findDocs(jdkHome, "appledocs");
209 if (appleDocs == null) {
210 appleDocs = findInJar(new File(jdkHome, "appledocs.jar"), "appledoc/api");
212 if (appleDocs != null) {
213 sdkModificator.addRoot(appleDocs, JavadocOrderRootType.getInstance());
216 sdkModificator.commitChanges();
219 private final Map<String, String> myCachedVersionStrings = new HashMap<String, String>();
221 public final String getVersionString(final String sdkHome) {
222 String versionString;
224 if(myCachedVersionStrings.containsKey(sdkHome)) {
225 return myCachedVersionStrings.get(sdkHome);
226 } else {
227 versionString = getJdkVersion(sdkHome);
229 if (versionString != null && versionString.length() == 0) {
230 versionString = null;
233 if (versionString != null){
234 myCachedVersionStrings.put(sdkHome, versionString);
237 return versionString;
240 @NotNull
241 public String getComponentName() {
242 return getName();
245 public void initComponent() { }
247 public void disposeComponent() {
250 public int compareTo(@NotNull String versionString, @NotNull String versionNumber) {
251 return getVersionNumber(versionString).compareTo(versionNumber);
254 public Sdk createJdk(final String jdkName, final String home, final boolean isJre) {
255 ProjectJdkImpl jdk = new ProjectJdkImpl(jdkName, this);
256 SdkModificator sdkModificator = jdk.getSdkModificator();
258 String path = home.replace(File.separatorChar, '/');
259 sdkModificator.setHomePath(path);
260 jdk.setVersionString(jdkName); // must be set after home path, otherwise setting home path clears the version string
262 File jdkHomeFile = new File(home);
263 addClasses(jdkHomeFile, sdkModificator, isJre);
264 addSources(jdkHomeFile, sdkModificator);
265 addDocs(jdkHomeFile, sdkModificator);
266 sdkModificator.commitChanges();
267 return jdk;
270 public static Sdk getMockJdk(@NonNls String versionName) {
271 File mockJdkCEPath = new File(PathManager.getHomePath(), "java/mockJDK");
272 if (mockJdkCEPath.exists()) {
273 return createMockJdk(mockJdkCEPath.getPath(), versionName, getInstance());
275 final String forcedPath = System.getProperty("idea.testingFramework.mockJDK");
276 String jdkHome = forcedPath != null ? forcedPath : PathManager.getHomePath() + File.separator + "mockJDK";
277 return createMockJdk(jdkHome, versionName, getInstance());
280 public static Sdk getMockJdk15(@NonNls String versionName) {
281 File mockJdkCEPath = new File(PathManager.getHomePath(), "java/mockJDK");
282 if (mockJdkCEPath.exists()) {
283 return createMockJdk(mockJdkCEPath.getPath(), versionName, getInstance());
285 String jdkHome = PathManager.getHomePath() + File.separator + "mockJDK-1.5";
286 return createMockJdk(jdkHome, versionName, getInstance());
289 public static Sdk getMockJdk17(@NonNls String versionName) {
290 String jdkHome = PathManager.getHomePath() + File.separator + "mockJDK-1.7";
291 return createMockJdk(jdkHome, versionName, getInstance());
294 private static Sdk createMockJdk(String jdkHome, final String versionName, JavaSdk javaSdk) {
295 File jdkHomeFile = new File(jdkHome);
296 if (!jdkHomeFile.exists()) return null;
298 final Sdk jdk = new ProjectJdkImpl(versionName, javaSdk);
299 final SdkModificator sdkModificator = jdk.getSdkModificator();
301 String path = jdkHome.replace(File.separatorChar, '/');
302 sdkModificator.setHomePath(path);
303 sdkModificator.setVersionString(versionName); // must be set after home path, otherwise setting home path clears the version string
305 addSources(jdkHomeFile, sdkModificator);
306 addClasses(jdkHomeFile, sdkModificator, false);
307 addClasses(jdkHomeFile, sdkModificator, true);
308 sdkModificator.commitChanges();
310 return jdk;
313 private static void addClasses(File file, SdkModificator sdkModificator, final boolean isJre) {
314 VirtualFile[] classes = findClasses(file, isJre);
315 for (VirtualFile virtualFile : classes) {
316 sdkModificator.addRoot(virtualFile, OrderRootType.CLASSES);
320 private static VirtualFile[] findClasses(File file, boolean isJre) {
321 FileFilter jarFileFilter = new FileFilter(){
322 @SuppressWarnings({"HardCodedStringLiteral"})
323 public boolean accept(File f){
324 if (f.isDirectory()) return false;
325 if (f.getName().endsWith(".jar")) return true;
326 return false;
330 File[] jarDirs;
331 if(SystemInfo.isMac && /*!ApplicationManager.getApplication().isUnitTestMode()) &&*/ !file.getName().startsWith("mockJDK")){
332 File libFile = new File(file, "lib");
333 @NonNls File classesFile = new File(file, "../Classes");
334 @NonNls File libExtFile = new File(libFile, "ext");
335 @NonNls File libEndorsedFile = new File(libFile, "endorsed");
336 jarDirs = new File[]{libEndorsedFile, libFile, classesFile, libExtFile};
338 else{
339 @NonNls final String jre = "jre";
340 File jreLibFile = isJre ? new File(file, "lib") : new File(new File(file, jre), "lib");
341 @NonNls File jreLibExtFile = new File(jreLibFile, "ext");
342 @NonNls File jreLibEndorsedFile = new File(jreLibFile, "endorsed");
343 jarDirs = new File[]{jreLibEndorsedFile, jreLibFile, jreLibExtFile};
346 ArrayList<File> childrenList = new ArrayList<File>();
347 for (File jarDir : jarDirs) {
348 if (jarDir != null && jarDir.isDirectory()) {
349 File[] files = jarDir.listFiles(jarFileFilter);
350 for (File file1 : files) {
351 childrenList.add(file1);
356 ArrayList<VirtualFile> result = new ArrayList<VirtualFile>();
357 for (File child : childrenList) {
358 String url = JarFileSystem.PROTOCOL_PREFIX + child.getAbsolutePath().replace(File.separatorChar, '/') + JarFileSystem.JAR_SEPARATOR;
359 VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(url);
360 if (vFile != null) {
361 result.add(vFile);
365 @NonNls File classesZipFile = new File(new File(file, "lib"), "classes.zip");
366 if(!classesZipFile.isDirectory() && classesZipFile.exists()){
367 String url =
368 JarFileSystem.PROTOCOL_PREFIX + classesZipFile.getAbsolutePath().replace(File.separatorChar, '/') + JarFileSystem.JAR_SEPARATOR;
369 VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(url);
370 if (vFile != null){
371 result.add(vFile);
375 return result.toArray(new VirtualFile[result.size()]);
378 private static void addSources(File file, SdkModificator sdkModificator) {
379 VirtualFile vFile = findSources(file);
380 if (vFile != null) {
381 sdkModificator.addRoot(vFile, OrderRootType.SOURCES);
385 @Nullable
386 @SuppressWarnings({"HardCodedStringLiteral"})
387 public static VirtualFile findSources(File file) {
388 File srcfile = new File(file, "src");
389 File jarfile = new File(file, "src.jar");
390 if (!jarfile.exists()) {
391 jarfile = new File(file, "src.zip");
394 if (jarfile.exists()) {
395 VirtualFile vFile = findInJar(jarfile, "src");
396 if (vFile != null) return vFile;
397 // try 1.4 format
398 vFile = findInJar(jarfile, "");
399 return vFile;
401 else {
402 if (!srcfile.exists() || !srcfile.isDirectory()) return null;
403 String path = srcfile.getAbsolutePath().replace(File.separatorChar, '/');
404 return LocalFileSystem.getInstance().findFileByPath(path);
408 @SuppressWarnings({"HardCodedStringLiteral"})
409 private static void addDocs(File file, SdkModificator rootContainer) {
410 VirtualFile vFile = findDocs(file, "docs/api");
411 if (vFile != null) {
412 rootContainer.addRoot(vFile, JavadocOrderRootType.getInstance());
416 @Nullable
417 private static VirtualFile findInJar(File jarFile, String relativePath) {
418 if (!jarFile.exists()) return null;
419 String url = JarFileSystem.PROTOCOL_PREFIX +
420 jarFile.getAbsolutePath().replace(File.separatorChar, '/') + JarFileSystem.JAR_SEPARATOR + relativePath;
421 return VirtualFileManager.getInstance().findFileByUrl(url);
424 @Nullable
425 public static VirtualFile findDocs(File file, final String relativePath) {
426 file = new File(file.getAbsolutePath() + File.separator + relativePath.replace('/', File.separatorChar));
427 if (!file.exists() || !file.isDirectory()) return null;
428 String path = file.getAbsolutePath().replace(File.separatorChar, '/');
429 return LocalFileSystem.getInstance().findFileByPath(path);