diff --git a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java index f73ceae8acd3..9da10b39e6d4 100644 --- a/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java +++ b/java/java-impl/src/com/intellij/openapi/projectRoots/impl/JavaSdkImpl.java @@ -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 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 myCachedSdkHomeToVersionString = new ConcurrentHashMap<>(); - private final Map myCachedVersionStringToJavaVersion = new ConcurrentHashMap<>(); + private final Map 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 diff --git a/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java index 93aa6056361f..bbecf1620ecd 100644 --- a/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java +++ b/java/java-psi-api/src/com/intellij/openapi/projectRoots/JavaSdkVersion.java @@ -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; } } \ No newline at end of file