[java] migrates Java SDK classes to new version parser

This commit is contained in:
Roman Shevchenko
2017-12-21 16:59:49 +01:00
parent 777e4da5dc
commit 9988cfe65c
2 changed files with 49 additions and 124 deletions
@@ -1,4 +1,6 @@
// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
/*
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package com.intellij.openapi.projectRoots.impl;
import com.intellij.icons.AllIcons;
@@ -16,24 +18,23 @@ import com.intellij.openapi.roots.OrderRootType;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.*;
import com.intellij.openapi.vfs.jrt.JrtFileSystem;
import com.intellij.util.PathUtil;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.lang.JavaVersion;
import org.jdom.Element;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.annotations.TestOnly;
import org.jetbrains.jps.model.java.JdkVersionDetector;
import org.jetbrains.jps.model.java.impl.JavaSdkUtil;
import javax.swing.*;
import java.io.File;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;
/**
@@ -46,12 +47,8 @@ public class JavaSdkImpl extends JavaSdk {
public static final DataKey<Boolean> KEY = DataKey.create("JavaSdk");
private static final String VM_EXE_NAME = "java"; // do not use JavaW.exe for Windows because of issues with encoding
private static final Pattern VERSION_STRING_PATTERN = Pattern.compile("^(.*)java version \"([1234567890_.]*)\"(.*)$");
private static final String JAVA_VERSION_PREFIX = "java version ";
private static final String OPENJDK_VERSION_PREFIX = "openjdk version ";
private final Map<String, String> myCachedSdkHomeToVersionString = new ConcurrentHashMap<>();
private final Map<String, JavaSdkVersion> myCachedVersionStringToJavaVersion = new ConcurrentHashMap<>();
private final Map<String, JavaVersion> myCachedSdkHomeToVersion = new ConcurrentHashMap<>();
public JavaSdkImpl(final VirtualFileManager fileManager, final FileTypeManager fileTypeManager) {
super("JavaSDK");
@@ -73,12 +70,9 @@ public class JavaSdkImpl extends JavaSdk {
}
private void updateCache(VirtualFileEvent event) {
final VirtualFile file = event.getFile();
if (FileTypes.ARCHIVE.equals(fileTypeManager.getFileTypeByFileName(event.getFileName()))) {
final String filePath = file.getPath();
if (myCachedSdkHomeToVersionString.keySet().removeIf(sdkHome -> FileUtil.isAncestor(sdkHome, filePath, false))) {
myCachedVersionStringToJavaVersion.clear();
}
String filePath = event.getFile().getPath();
myCachedSdkHomeToVersion.keySet().removeIf(sdkHome -> FileUtil.isAncestor(sdkHome, filePath, false));
}
}
});
@@ -201,50 +195,14 @@ public class JavaSdkImpl extends JavaSdk {
@Override
public String suggestSdkName(String currentSdkName, String sdkHome) {
final String suggestedName;
if (currentSdkName != null && !currentSdkName.isEmpty()) {
final Matcher matcher = VERSION_STRING_PATTERN.matcher(currentSdkName);
final boolean replaceNameWithVersion = matcher.matches();
if (replaceNameWithVersion){
// user did not change name -> set it automatically
final String versionString = getVersionString(sdkHome);
suggestedName = versionString == null ? currentSdkName : matcher.replaceFirst("$1" + versionString + "$3");
}
else {
suggestedName = currentSdkName;
}
}
else {
String versionString = getVersionString(sdkHome);
suggestedName = versionString == null ? ProjectBundle.message("sdk.java.unknown.name") : getVersionNumber(versionString);
}
return suggestedName;
}
JavaVersion version = getJavaVersion(sdkHome);
if (version == null) return currentSdkName;
@NotNull
private static String getVersionNumber(@NotNull String versionString) {
if (versionString.startsWith(JAVA_VERSION_PREFIX) || versionString.startsWith(OPENJDK_VERSION_PREFIX)) {
boolean openJdk = versionString.startsWith(OPENJDK_VERSION_PREFIX);
versionString = versionString.substring(openJdk ? OPENJDK_VERSION_PREFIX.length() : JAVA_VERSION_PREFIX.length());
if (versionString.startsWith("\"") && versionString.endsWith("\"")) {
versionString = versionString.substring(1, versionString.length() - 1);
}
int dotIdx = versionString.indexOf('.');
if (dotIdx > 0) {
try {
int major = Integer.parseInt(versionString.substring(0, dotIdx));
int minorDot = versionString.indexOf('.', dotIdx + 1);
if (minorDot > 0) {
int minor = Integer.parseInt(versionString.substring(dotIdx + 1, minorDot));
versionString = major + "." + minor;
}
}
catch (NumberFormatException e) {
// Do nothing. Use original version string if failed to parse according to major.minor pattern.
}
}
}
return versionString;
StringBuilder suggested = new StringBuilder();
if (version.feature < 9) suggested.append("1.");
suggested.append(version.feature);
if (version.ea) suggested.append("-ea");
return suggested.toString();
}
@Override
@@ -322,23 +280,24 @@ public class JavaSdkImpl extends JavaSdk {
modificator.addRoot(root, annoType);
}
@Nullable
private JavaVersion getJavaVersion(String sdkHome) {
return myCachedSdkHomeToVersion.computeIfAbsent(sdkHome, k -> {
JdkVersionDetector.JdkVersionInfo jdkInfo = SdkVersionUtil.getJdkVersionInfo(k);
return jdkInfo != null ? jdkInfo.version : null;
});
}
@Override
public final String getVersionString(String sdkHome) {
String versionString = myCachedSdkHomeToVersionString.get(sdkHome);
if (versionString == null) {
versionString = SdkVersionUtil.detectJdkVersion(sdkHome);
if (!StringUtil.isEmpty(versionString)) {
myCachedSdkHomeToVersionString.put(sdkHome, versionString);
}
}
return versionString;
JavaVersion version = getJavaVersion(sdkHome);
return version != null ? JdkVersionDetector.formatVersionString(version) : null;
}
@Override
public JavaSdkVersion getVersion(@NotNull Sdk sdk) {
String versionString = sdk.getVersionString();
return versionString == null ? null :
myCachedVersionStringToJavaVersion.computeIfAbsent(versionString, JavaSdkVersion::fromVersionString);
JavaVersion version = getJavaVersion(sdk.getHomePath());
return version != null ? JavaSdkVersion.fromJavaVersion(version) : null;
}
@Override
@@ -1,29 +1,14 @@
/*
* Copyright 2000-2017 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.
* Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
*/
package com.intellij.openapi.projectRoots;
import com.intellij.openapi.util.Version;
import com.intellij.pom.java.LanguageLevel;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.lang.JavaVersion;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Represents version of Java SDK. Use {@code JavaSdk#getVersion(Sdk)} method to obtain version of an {@code Sdk}.
@@ -32,29 +17,25 @@ import java.util.regex.Pattern;
* @see LanguageLevel
*/
public enum JavaSdkVersion {
JDK_1_0(LanguageLevel.JDK_1_3, 0, new String[]{"1.0"}),
JDK_1_1(LanguageLevel.JDK_1_3, 1, new String[]{"1.1"}),
JDK_1_2(LanguageLevel.JDK_1_3, 2, new String[]{"1.2"}),
JDK_1_3(LanguageLevel.JDK_1_3, 3, new String[]{"1.3"}),
JDK_1_4(LanguageLevel.JDK_1_4, 4, new String[]{"1.4"}),
JDK_1_5(LanguageLevel.JDK_1_5, 5, new String[]{"1.5", "5.0"}),
JDK_1_6(LanguageLevel.JDK_1_6, 6, new String[]{"1.6", "6.0"}),
JDK_1_7(LanguageLevel.JDK_1_7, 7, new String[]{"1.7", "7.0"}),
JDK_1_8(LanguageLevel.JDK_1_8, 8, new String[]{"1.8", "8.0"}),
JDK_1_9(LanguageLevel.JDK_1_9, 9, new String[]{"1.9", "9.0", "9-ea"}),
JDK_10(LanguageLevel.JDK_1_9, 10, new String[]{"10.0", "10-ea"});
JDK_1_0(LanguageLevel.JDK_1_3, new String[]{"1.0"}),
JDK_1_1(LanguageLevel.JDK_1_3, new String[]{"1.1"}),
JDK_1_2(LanguageLevel.JDK_1_3, new String[]{"1.2"}),
JDK_1_3(LanguageLevel.JDK_1_3, new String[]{"1.3"}),
JDK_1_4(LanguageLevel.JDK_1_4, new String[]{"1.4"}),
JDK_1_5(LanguageLevel.JDK_1_5, new String[]{"1.5", "5.0"}),
JDK_1_6(LanguageLevel.JDK_1_6, new String[]{"1.6", "6.0"}),
JDK_1_7(LanguageLevel.JDK_1_7, new String[]{"1.7", "7.0"}),
JDK_1_8(LanguageLevel.JDK_1_8, new String[]{"1.8", "8.0"}),
JDK_1_9(LanguageLevel.JDK_1_9, new String[]{"1.9", "9.0", "9-ea"}),
JDK_10(LanguageLevel.JDK_1_9, new String[]{"10.0", "10-ea"});
private static final JavaSdkVersion MAX_JDK = JDK_1_9;
private static final Pattern JAVA_VERSION = Pattern.compile("java version \"(\\d.*)\"");
private final LanguageLevel myMaxLanguageLevel;
private final int myRelease;
private final String[] myVersionStrings;
JavaSdkVersion(@NotNull LanguageLevel maxLanguageLevel, int release, @NotNull String[] description) {
JavaSdkVersion(@NotNull LanguageLevel maxLanguageLevel, @NotNull String[] description) {
myMaxLanguageLevel = maxLanguageLevel;
myRelease = release;
myVersionStrings = description;
}
@@ -93,31 +74,16 @@ public enum JavaSdkVersion {
throw new IllegalArgumentException("Can't map " + languageLevel + " to any of " + Arrays.toString(values()));
}
/**
* Version string could be an actual version (like {@code "1.8.0_131"}),
* or a string returned by "java -version" command (like {@code "java version \"9-ea\""}).
*/
/** See {@link JavaVersion#parse(String)} for supported formats. */
@Nullable
public static JavaSdkVersion fromVersionString(@NotNull String versionString) {
Matcher matcher = JAVA_VERSION.matcher(versionString.trim());
if (matcher.matches()) {
versionString = matcher.group(1);
}
JavaVersion version = JavaVersion.tryParse(versionString);
return version != null ? fromJavaVersion(version) : null;
}
Version parsed = Version.parseVersion(versionString);
if (parsed != null && parsed.major > 0) {
int release = parsed.major == 1 ? parsed.minor : parsed.major;
return ContainerUtil.find(values(), v -> v.myRelease == release);
}
for (JavaSdkVersion version : values()) {
for (String pattern : version.myVersionStrings) {
if (versionString.contains(pattern)) {
return version;
}
}
}
return null;
@Nullable
public static JavaSdkVersion fromJavaVersion(@NotNull JavaVersion version) {
JavaSdkVersion[] values = values();
return version.feature < values.length ? values[version.feature] : null;
}
}