diff --git a/java-language-api/src/main/java/com/intellij/java/language/projectRoots/JavaSdkType.java b/java-language-api/src/main/java/com/intellij/java/language/projectRoots/JavaSdkType.java index 4a242e102..003337cfc 100644 --- a/java-language-api/src/main/java/com/intellij/java/language/projectRoots/JavaSdkType.java +++ b/java-language-api/src/main/java/com/intellij/java/language/projectRoots/JavaSdkType.java @@ -16,6 +16,7 @@ package com.intellij.java.language.projectRoots; import com.intellij.java.language.internal.DefaultJavaSdkType; +import consulo.application.Application; import consulo.content.bundle.Sdk; import consulo.content.bundle.SdkModificator; import consulo.content.bundle.SdkTable; @@ -26,35 +27,35 @@ import java.io.File; public abstract class JavaSdkType extends SdkType { - /** - * Return default impl JavaSdkType implementation - */ - @Nonnull - public static JavaSdkType getDefaultJavaSdkType() { - return EP_NAME.findExtensionOrFail(DefaultJavaSdkType.class); - } + /** + * Return default impl JavaSdkType implementation + */ + @Nonnull + public static JavaSdkType getDefaultJavaSdkType() { + return Application.get().getExtensionPoint(SdkType.class).findExtensionOrFail(DefaultJavaSdkType.class); + } - public JavaSdkType(String name) { - super(name); - } + public JavaSdkType(String name) { + super(name); + } - public final Sdk createJdk(String jdkName, @Nonnull String home) { - Sdk jdk = SdkTable.getInstance().createSdk(jdkName, this); - SdkModificator sdkModificator = jdk.getSdkModificator(); + public final Sdk createJdk(String jdkName, @Nonnull String home) { + Sdk jdk = SdkTable.getInstance().createSdk(jdkName, this); + SdkModificator sdkModificator = jdk.getSdkModificator(); - String path = home.replace(File.separatorChar, '/'); - sdkModificator.setHomePath(path); - sdkModificator.setVersionString(jdkName); // must be set after home path, otherwise setting home path clears the version string - sdkModificator.commitChanges(); + String path = home.replace(File.separatorChar, '/'); + sdkModificator.setHomePath(path); + sdkModificator.setVersionString(jdkName); // must be set after home path, otherwise setting home path clears the version string + sdkModificator.commitChanges(); - setupSdkPaths(jdk); + setupSdkPaths(jdk); - return jdk; - } + return jdk; + } - public abstract String getBinPath(Sdk sdk); + public abstract String getBinPath(Sdk sdk); - public abstract String getToolsPath(Sdk sdk); + public abstract String getToolsPath(Sdk sdk); - public abstract void setupCommandLine(@Nonnull GeneralCommandLine generalCommandLine, @Nonnull Sdk sdk); + public abstract void setupCommandLine(@Nonnull GeneralCommandLine generalCommandLine, @Nonnull Sdk sdk); } diff --git a/java-language-api/src/main/java/com/intellij/java/language/projectRoots/JavaSdkVersion.java b/java-language-api/src/main/java/com/intellij/java/language/projectRoots/JavaSdkVersion.java index 269099829..ab2120960 100644 --- a/java-language-api/src/main/java/com/intellij/java/language/projectRoots/JavaSdkVersion.java +++ b/java-language-api/src/main/java/com/intellij/java/language/projectRoots/JavaSdkVersion.java @@ -15,83 +15,83 @@ * @see LanguageLevel */ public enum JavaSdkVersion { - JDK_1_0(LanguageLevel.JDK_1_3), - JDK_1_1(LanguageLevel.JDK_1_3), - JDK_1_2(LanguageLevel.JDK_1_3), - JDK_1_3(LanguageLevel.JDK_1_3), - JDK_1_4(LanguageLevel.JDK_1_4), - JDK_1_5(LanguageLevel.JDK_1_5), - JDK_1_6(LanguageLevel.JDK_1_6), - JDK_1_7(LanguageLevel.JDK_1_7), - JDK_1_8(LanguageLevel.JDK_1_8), - JDK_1_9(LanguageLevel.JDK_1_9), - JDK_10(LanguageLevel.JDK_10), - JDK_11(LanguageLevel.JDK_11), - JDK_12(LanguageLevel.JDK_12), - JDK_13(LanguageLevel.JDK_13), - JDK_14(LanguageLevel.JDK_14), - JDK_15(LanguageLevel.JDK_15), - JDK_16(LanguageLevel.JDK_16), - JDK_17(LanguageLevel.JDK_17), - JDK_18(LanguageLevel.JDK_18), - JDK_19(LanguageLevel.JDK_19), - JDK_20(LanguageLevel.JDK_20), - JDK_21(LanguageLevel.JDK_21), - JDK_22(LanguageLevel.JDK_22), - JDK_23(LanguageLevel.JDK_X); + JDK_1_0(LanguageLevel.JDK_1_3), + JDK_1_1(LanguageLevel.JDK_1_3), + JDK_1_2(LanguageLevel.JDK_1_3), + JDK_1_3(LanguageLevel.JDK_1_3), + JDK_1_4(LanguageLevel.JDK_1_4), + JDK_1_5(LanguageLevel.JDK_1_5), + JDK_1_6(LanguageLevel.JDK_1_6), + JDK_1_7(LanguageLevel.JDK_1_7), + JDK_1_8(LanguageLevel.JDK_1_8), + JDK_1_9(LanguageLevel.JDK_1_9), + JDK_10(LanguageLevel.JDK_10), + JDK_11(LanguageLevel.JDK_11), + JDK_12(LanguageLevel.JDK_12), + JDK_13(LanguageLevel.JDK_13), + JDK_14(LanguageLevel.JDK_14), + JDK_15(LanguageLevel.JDK_15), + JDK_16(LanguageLevel.JDK_16), + JDK_17(LanguageLevel.JDK_17), + JDK_18(LanguageLevel.JDK_18), + JDK_19(LanguageLevel.JDK_19), + JDK_20(LanguageLevel.JDK_20), + JDK_21(LanguageLevel.JDK_21), + JDK_22(LanguageLevel.JDK_22), + JDK_23(LanguageLevel.JDK_X); - public static JavaSdkVersion MAX_JDK = JDK_23; + public static JavaSdkVersion MAX_JDK = JDK_23; - private final LanguageLevel myMaxLanguageLevel; + private final LanguageLevel myMaxLanguageLevel; - JavaSdkVersion(@Nonnull LanguageLevel maxLanguageLevel) { - myMaxLanguageLevel = maxLanguageLevel; - } - - @Nonnull - public LanguageLevel getMaxLanguageLevel() { - return myMaxLanguageLevel; - } - - @Nonnull - public String getDescription() { - int feature = ordinal(); - return feature < 5 ? "1." + feature : String.valueOf(feature); - } + JavaSdkVersion(@Nonnull LanguageLevel maxLanguageLevel) { + myMaxLanguageLevel = maxLanguageLevel; + } - public boolean isAtLeast(@Nonnull JavaSdkVersion version) { - return compareTo(version) >= 0; - } + @Nonnull + public LanguageLevel getMaxLanguageLevel() { + return myMaxLanguageLevel; + } - @Nonnull - public static JavaSdkVersion fromLanguageLevel(@Nonnull LanguageLevel languageLevel) throws IllegalArgumentException { - if (languageLevel == LanguageLevel.JDK_1_3) { - return JDK_1_3; + @Nonnull + public String getDescription() { + int feature = ordinal(); + return feature < 5 ? "1." + feature : String.valueOf(feature); } - JavaSdkVersion[] values = values(); - if (languageLevel == LanguageLevel.JDK_X) { - return values[values.length - 1]; + + public boolean isAtLeast(@Nonnull JavaSdkVersion version) { + return compareTo(version) >= 0; } - for (JavaSdkVersion version : values) { - if (version.getMaxLanguageLevel().isAtLeast(languageLevel)) { - return version; - } + + @Nonnull + public static JavaSdkVersion fromLanguageLevel(@Nonnull LanguageLevel languageLevel) throws IllegalArgumentException { + if (languageLevel == LanguageLevel.JDK_1_3) { + return JDK_1_3; + } + JavaSdkVersion[] values = values(); + if (languageLevel == LanguageLevel.JDK_X) { + return values[values.length - 1]; + } + for (JavaSdkVersion version : values) { + if (version.getMaxLanguageLevel().isAtLeast(languageLevel)) { + return version; + } + } + throw new IllegalArgumentException("Can't map " + languageLevel + " to any of " + Arrays.toString(values)); } - throw new IllegalArgumentException("Can't map " + languageLevel + " to any of " + Arrays.toString(values)); - } - /** - * See {@link JavaVersion#parse(String)} for supported formats. - */ - @Nullable - public static JavaSdkVersion fromVersionString(@Nonnull String versionString) { - JavaVersion version = JavaVersion.tryParse(versionString); - return version != null ? fromJavaVersion(version) : null; - } + /** + * See {@link JavaVersion#parse(String)} for supported formats. + */ + @Nullable + public static JavaSdkVersion fromVersionString(@Nonnull String versionString) { + JavaVersion version = JavaVersion.tryParse(versionString); + return version != null ? fromJavaVersion(version) : null; + } - @Nullable - public static JavaSdkVersion fromJavaVersion(@Nonnull JavaVersion version) { - JavaSdkVersion[] values = values(); - return version.feature < values.length ? values[version.feature] : null; - } + @Nullable + public static JavaSdkVersion fromJavaVersion(@Nonnull JavaVersion version) { + JavaSdkVersion[] values = values(); + return version.feature < values.length ? values[version.feature] : null; + } } \ No newline at end of file diff --git a/java-language-api/src/main/java/com/intellij/java/language/projectRoots/JavaVersionService.java b/java-language-api/src/main/java/com/intellij/java/language/projectRoots/JavaVersionService.java index 362fa1c24..aeedc0595 100644 --- a/java-language-api/src/main/java/com/intellij/java/language/projectRoots/JavaVersionService.java +++ b/java-language-api/src/main/java/com/intellij/java/language/projectRoots/JavaVersionService.java @@ -13,13 +13,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -/* - * @author max - */ package com.intellij.java.language.projectRoots; import com.intellij.java.language.psi.util.PsiUtil; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ComponentScope; import consulo.annotation.component.ServiceAPI; import consulo.ide.ServiceManager; @@ -27,17 +24,22 @@ import jakarta.annotation.Nonnull; +/** + * @author max + */ @ServiceAPI(ComponentScope.APPLICATION) public class JavaVersionService { - public static JavaVersionService getInstance() { - return ServiceManager.getService(JavaVersionService.class); - } + public static JavaVersionService getInstance() { + return ServiceManager.getService(JavaVersionService.class); + } - public boolean isAtLeast(@Nonnull PsiElement element, @Nonnull JavaSdkVersion version) { - return PsiUtil.getLanguageLevel(element).isAtLeast(version.getMaxLanguageLevel()); - } + @RequiredReadAction + public boolean isAtLeast(@Nonnull PsiElement element, @Nonnull JavaSdkVersion version) { + return PsiUtil.getLanguageLevel(element).isAtLeast(version.getMaxLanguageLevel()); + } - public JavaSdkVersion getJavaSdkVersion(@Nonnull PsiElement element) { - return JavaSdkVersion.fromLanguageLevel(PsiUtil.getLanguageLevel(element)); - } + @RequiredReadAction + public JavaSdkVersion getJavaSdkVersion(@Nonnull PsiElement element) { + return JavaSdkVersion.fromLanguageLevel(PsiUtil.getLanguageLevel(element)); + } } \ No newline at end of file diff --git a/java-language-api/src/main/java/com/intellij/java/language/projectRoots/OwnJdkVersionDetector.java b/java-language-api/src/main/java/com/intellij/java/language/projectRoots/OwnJdkVersionDetector.java index bd0ab1c83..245f6ba97 100644 --- a/java-language-api/src/main/java/com/intellij/java/language/projectRoots/OwnJdkVersionDetector.java +++ b/java-language-api/src/main/java/com/intellij/java/language/projectRoots/OwnJdkVersionDetector.java @@ -17,55 +17,55 @@ */ @ServiceAPI(ComponentScope.APPLICATION) public abstract class OwnJdkVersionDetector { - public static OwnJdkVersionDetector getInstance() { - return ServiceManager.getService(OwnJdkVersionDetector.class); - } - - /** - * @deprecated use {@link #detectJdkVersionInfo(String)} (to be removed in IDEA 2019) - */ - @Deprecated - @Nullable - public String detectJdkVersion(@Nonnull String homePath) { - JdkVersionInfo info = detectJdkVersionInfo(homePath); - return info != null ? info.getVersion() : null; - } - - @Nullable - public abstract JdkVersionInfo detectJdkVersionInfo(@Nonnull String homePath); - - public static final class JdkVersionInfo { - public final JavaVersion version; - public final Bitness bitness; - - public JdkVersionInfo(@Nonnull JavaVersion version, @Nonnull Bitness bitness) { - this.version = version; - this.bitness = bitness; - } - - @Override - public String toString() { - return version + " " + bitness; + public static OwnJdkVersionDetector getInstance() { + return ServiceManager.getService(OwnJdkVersionDetector.class); } /** - * @deprecated use {@link #version} (to be removed in IDEA 2019) + * @deprecated use {@link #detectJdkVersionInfo(String)} (to be removed in IDEA 2019) */ @Deprecated - public String getVersion() { - return formatVersionString(version); + @Nullable + public String detectJdkVersion(@Nonnull String homePath) { + JdkVersionInfo info = detectJdkVersionInfo(homePath); + return info != null ? info.getVersion() : null; } - /** - * @deprecated use {@link #bitness} (to be removed in IDEA 2019) - */ - @Deprecated - public Bitness getBitness() { - return bitness; + @Nullable + public abstract JdkVersionInfo detectJdkVersionInfo(@Nonnull String homePath); + + public static final class JdkVersionInfo { + public final JavaVersion version; + public final Bitness bitness; + + public JdkVersionInfo(@Nonnull JavaVersion version, @Nonnull Bitness bitness) { + this.version = version; + this.bitness = bitness; + } + + @Override + public String toString() { + return version + " " + bitness; + } + + /** + * @deprecated use {@link #version} (to be removed in IDEA 2019) + */ + @Deprecated + public String getVersion() { + return formatVersionString(version); + } + + /** + * @deprecated use {@link #bitness} (to be removed in IDEA 2019) + */ + @Deprecated + public Bitness getBitness() { + return bitness; + } } - } - public static String formatVersionString(@Nonnull JavaVersion version) { - return "java version \"" + version + '"'; - } + public static String formatVersionString(@Nonnull JavaVersion version) { + return "java version \"" + version + '"'; + } } \ No newline at end of file diff --git a/java-language-api/src/main/java/com/intellij/java/language/projectRoots/roots/AnnotationOrderRootType.java b/java-language-api/src/main/java/com/intellij/java/language/projectRoots/roots/AnnotationOrderRootType.java index e005405a5..e936c8347 100644 --- a/java-language-api/src/main/java/com/intellij/java/language/projectRoots/roots/AnnotationOrderRootType.java +++ b/java-language-api/src/main/java/com/intellij/java/language/projectRoots/roots/AnnotationOrderRootType.java @@ -25,6 +25,7 @@ import consulo.virtualFileSystem.util.VirtualFileUtil; import jakarta.annotation.Nonnull; + import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -34,44 +35,44 @@ */ @ExtensionImpl public class AnnotationOrderRootType extends OrderRootType { - @Nonnull - public static OrderRootType getInstance() { - return getOrderRootType(AnnotationOrderRootType.class); - } + @Nonnull + public static OrderRootType getInstance() { + return getOrderRootType(AnnotationOrderRootType.class); + } - public AnnotationOrderRootType() { - super("javaExternalAnnotations"); - } + public AnnotationOrderRootType() { + super("javaExternalAnnotations"); + } - @Nonnull - public static VirtualFile[] getFiles(@Nonnull OrderEntry entry) { - List result = new ArrayList(); - RootPolicy> policy = new RootPolicy>() { - @Override - public List visitOrderEntry(OrderEntry orderEntry, List value) { - if (orderEntry instanceof OrderEntryWithTracking) { - Collections.addAll(value, orderEntry.getFiles(getInstance())); - } - return value; - } - }; - entry.accept(policy, result); - return VirtualFileUtil.toVirtualFileArray(result); - } + @Nonnull + public static VirtualFile[] getFiles(@Nonnull OrderEntry entry) { + List result = new ArrayList(); + RootPolicy> policy = new RootPolicy>() { + @Override + public List visitOrderEntry(OrderEntry orderEntry, List value) { + if (orderEntry instanceof OrderEntryWithTracking) { + Collections.addAll(value, orderEntry.getFiles(getInstance())); + } + return value; + } + }; + entry.accept(policy, result); + return VirtualFileUtil.toVirtualFileArray(result); + } - @Nonnull - public static String[] getUrls(@Nonnull OrderEntry entry) { - List result = new ArrayList(); - RootPolicy> policy = new RootPolicy>() { - @Override - public List visitOrderEntry(OrderEntry orderEntry, List value) { - if (orderEntry instanceof OrderEntryWithTracking) { - Collections.addAll(value, orderEntry.getUrls(getInstance())); - } - return value; - } - }; - entry.accept(policy, result); - return ArrayUtil.toStringArray(result); - } + @Nonnull + public static String[] getUrls(@Nonnull OrderEntry entry) { + List result = new ArrayList(); + RootPolicy> policy = new RootPolicy>() { + @Override + public List visitOrderEntry(OrderEntry orderEntry, List value) { + if (orderEntry instanceof OrderEntryWithTracking) { + Collections.addAll(value, orderEntry.getUrls(getInstance())); + } + return value; + } + }; + entry.accept(policy, result); + return ArrayUtil.toStringArray(result); + } } diff --git a/java-language-api/src/main/java/com/intellij/java/language/projectRoots/roots/ExternalLibraryDescriptor.java b/java-language-api/src/main/java/com/intellij/java/language/projectRoots/roots/ExternalLibraryDescriptor.java index f2148be24..05808d2c5 100644 --- a/java-language-api/src/main/java/com/intellij/java/language/projectRoots/roots/ExternalLibraryDescriptor.java +++ b/java-language-api/src/main/java/com/intellij/java/language/projectRoots/roots/ExternalLibraryDescriptor.java @@ -23,55 +23,52 @@ /** * @author nik */ -public abstract class ExternalLibraryDescriptor -{ - private final String myLibraryGroupId; - private final String myLibraryArtifactId; - private final String myMinVersion; - private final String myMaxVersion; +public abstract class ExternalLibraryDescriptor { + private final String myLibraryGroupId; + private final String myLibraryArtifactId; + private final String myMinVersion; + private final String myMaxVersion; - public ExternalLibraryDescriptor(String libraryGroupId, String libraryArtifactId) - { - this(libraryGroupId, libraryArtifactId, null, null); - } + public ExternalLibraryDescriptor(String libraryGroupId, String libraryArtifactId) { + this(libraryGroupId, libraryArtifactId, null, null); + } - public ExternalLibraryDescriptor(@Nonnull String libraryGroupId, @Nonnull String libraryArtifactId, @Nullable String minVersion, @Nullable String maxVersion) - { - myLibraryGroupId = libraryGroupId; - myLibraryArtifactId = libraryArtifactId; - myMinVersion = minVersion; - myMaxVersion = maxVersion; - } + public ExternalLibraryDescriptor( + @Nonnull String libraryGroupId, + @Nonnull String libraryArtifactId, + @Nullable String minVersion, + @Nullable String maxVersion + ) { + myLibraryGroupId = libraryGroupId; + myLibraryArtifactId = libraryArtifactId; + myMinVersion = minVersion; + myMaxVersion = maxVersion; + } - @Nonnull - public String getLibraryGroupId() - { - return myLibraryGroupId; - } + @Nonnull + public String getLibraryGroupId() { + return myLibraryGroupId; + } - @Nonnull - public String getLibraryArtifactId() - { - return myLibraryArtifactId; - } + @Nonnull + public String getLibraryArtifactId() { + return myLibraryArtifactId; + } - @Nullable - public String getMinVersion() - { - return myMinVersion; - } + @Nullable + public String getMinVersion() { + return myMinVersion; + } - @Nullable - public String getMaxVersion() - { - return myMaxVersion; - } + @Nullable + public String getMaxVersion() { + return myMaxVersion; + } - public String getPresentableName() - { - return myLibraryArtifactId; - } + public String getPresentableName() { + return myLibraryArtifactId; + } - @Nonnull - public abstract List getLibraryClassesRoots(); + @Nonnull + public abstract List getLibraryClassesRoots(); } diff --git a/java-language-api/src/main/java/com/intellij/java/language/projectRoots/roots/NativeLibraryOrderRootType.java b/java-language-api/src/main/java/com/intellij/java/language/projectRoots/roots/NativeLibraryOrderRootType.java index f76068fc5..74229e6d4 100644 --- a/java-language-api/src/main/java/com/intellij/java/language/projectRoots/roots/NativeLibraryOrderRootType.java +++ b/java-language-api/src/main/java/com/intellij/java/language/projectRoots/roots/NativeLibraryOrderRootType.java @@ -23,11 +23,11 @@ */ @ExtensionImpl public class NativeLibraryOrderRootType extends OrderRootType { - public static OrderRootType getInstance() { - return getOrderRootType(NativeLibraryOrderRootType.class); - } + public static OrderRootType getInstance() { + return getOrderRootType(NativeLibraryOrderRootType.class); + } - public NativeLibraryOrderRootType() { - super("javaNative"); - } + public NativeLibraryOrderRootType() { + super("javaNative"); + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/openapi/projectRoots/JavaVersionServiceImpl.java b/plugin/src/main/java/com/intellij/java/impl/openapi/projectRoots/JavaVersionServiceImpl.java index 2f9280bae..b563c8089 100644 --- a/plugin/src/main/java/com/intellij/java/impl/openapi/projectRoots/JavaVersionServiceImpl.java +++ b/plugin/src/main/java/com/intellij/java/impl/openapi/projectRoots/JavaVersionServiceImpl.java @@ -18,6 +18,7 @@ import com.intellij.java.language.impl.projectRoots.JavaSdkVersionUtil; import com.intellij.java.language.projectRoots.JavaSdkVersion; import com.intellij.java.language.projectRoots.JavaVersionService; +import consulo.annotation.access.RequiredReadAction; import consulo.annotation.component.ServiceImpl; import consulo.language.psi.PsiElement; import jakarta.inject.Singleton; @@ -26,18 +27,20 @@ /** * @author anna - * @since 3/28/12 + * @since 2012-03-28 */ @Singleton @ServiceImpl public class JavaVersionServiceImpl extends JavaVersionService { - @Override - public boolean isAtLeast(@Nonnull PsiElement element, @Nonnull JavaSdkVersion version) { - return JavaSdkVersionUtil.isAtLeast(element, version); - } + @Override + @RequiredReadAction + public boolean isAtLeast(@Nonnull PsiElement element, @Nonnull JavaSdkVersion version) { + return JavaSdkVersionUtil.isAtLeast(element, version); + } - @Override - public JavaSdkVersion getJavaSdkVersion(@Nonnull PsiElement element) { - return JavaSdkVersionUtil.getJavaSdkVersion(element); - } + @Override + @RequiredReadAction + public JavaSdkVersion getJavaSdkVersion(@Nonnull PsiElement element) { + return JavaSdkVersionUtil.getJavaSdkVersion(element); + } } diff --git a/plugin/src/main/java/com/intellij/java/impl/openapi/projectRoots/OwnJdkVersionDetectorImpl.java b/plugin/src/main/java/com/intellij/java/impl/openapi/projectRoots/OwnJdkVersionDetectorImpl.java index 98d76d617..e494cb3f3 100644 --- a/plugin/src/main/java/com/intellij/java/impl/openapi/projectRoots/OwnJdkVersionDetectorImpl.java +++ b/plugin/src/main/java/com/intellij/java/impl/openapi/projectRoots/OwnJdkVersionDetectorImpl.java @@ -32,116 +32,121 @@ @Singleton @ServiceImpl public class OwnJdkVersionDetectorImpl extends OwnJdkVersionDetector { - private static final Logger LOG = Logger.getInstance(OwnJdkVersionDetectorImpl.class); - - @Nullable - @Override - public JdkVersionInfo detectJdkVersionInfo(@Nonnull String homePath) { - // Java 1.7+ - File releaseFile = new File(homePath, "release"); - if (releaseFile.isFile()) { - Properties p = new Properties(); - try (FileInputStream stream = new FileInputStream(releaseFile)) { - p.load(stream); - String versionString = p.getProperty("JAVA_FULL_VERSION", p.getProperty("JAVA_VERSION")); - if (versionString != null) { - JavaVersion version = JavaVersion.parse(versionString); - String arch = StringUtil.unquoteString(p.getProperty("OS_ARCH", "")); - boolean x64 = "x86_64".equals(arch) || "amd64".equals(arch); - return new JdkVersionInfo(version, x64 ? Bitness.x64 : Bitness.x32); - } - } catch (IOException | IllegalArgumentException e) { - LOG.info(releaseFile.getPath(), e); - } - } + private static final Logger LOG = Logger.getInstance(OwnJdkVersionDetectorImpl.class); - // Java 1.2 - 1.8 - File rtFile = new File(homePath, "jre/lib/rt.jar"); - if (rtFile.isFile()) { - try (JarFile rtJar = new JarFile(rtFile, false)) { - Manifest manifest = rtJar.getManifest(); - if (manifest != null) { - String versionString = manifest.getMainAttributes().getValue("Implementation-Version"); - if (versionString != null) { - JavaVersion version = JavaVersion.parse(versionString); - boolean x64 = Platform.current().os().isMac() || new File(rtFile.getParent(), "amd64").isDirectory(); - return new JdkVersionInfo(version, x64 ? Bitness.x64 : Bitness.x32); - } + @Nullable + @Override + public JdkVersionInfo detectJdkVersionInfo(@Nonnull String homePath) { + // Java 1.7+ + File releaseFile = new File(homePath, "release"); + if (releaseFile.isFile()) { + Properties p = new Properties(); + try (FileInputStream stream = new FileInputStream(releaseFile)) { + p.load(stream); + String versionString = p.getProperty("JAVA_FULL_VERSION", p.getProperty("JAVA_VERSION")); + if (versionString != null) { + JavaVersion version = JavaVersion.parse(versionString); + String arch = StringUtil.unquoteString(p.getProperty("OS_ARCH", "")); + boolean x64 = "x86_64".equals(arch) || "amd64".equals(arch); + return new JdkVersionInfo(version, x64 ? Bitness.x64 : Bitness.x32); + } + } + catch (IOException | IllegalArgumentException e) { + LOG.info(releaseFile.getPath(), e); + } } - } catch (IOException | IllegalArgumentException e) { - LOG.info(rtFile.getPath(), e); - } - } - // last resort - File javaExe = new File(homePath, "bin/" + (Platform.current().os().isWindows() ? "java.exe" : "java")); - if (javaExe.canExecute()) { - try { - Process process = new ProcessBuilder(javaExe.getPath(), "-version").redirectErrorStream(true).start(); - VersionOutputReader reader = new VersionOutputReader(process.getInputStream()); - try { - reader.waitFor(); - } catch (InterruptedException e) { - LOG.info(e); - process.destroy(); + // Java 1.2 - 1.8 + File rtFile = new File(homePath, "jre/lib/rt.jar"); + if (rtFile.isFile()) { + try (JarFile rtJar = new JarFile(rtFile, false)) { + Manifest manifest = rtJar.getManifest(); + if (manifest != null) { + String versionString = manifest.getMainAttributes().getValue("Implementation-Version"); + if (versionString != null) { + JavaVersion version = JavaVersion.parse(versionString); + boolean x64 = Platform.current().os().isMac() || new File(rtFile.getParent(), "amd64").isDirectory(); + return new JdkVersionInfo(version, x64 ? Bitness.x64 : Bitness.x32); + } + } + } + catch (IOException | IllegalArgumentException e) { + LOG.info(rtFile.getPath(), e); + } } - if (!reader.myLines.isEmpty()) { - JavaVersion base = JavaVersion.parse(reader.myLines.get(0)); - JavaVersion rt = JavaVersion.tryParse(reader.myLines.size() > 2 ? reader.myLines.get(1) : null); - JavaVersion version = rt != null && rt.feature == base.feature && rt.minor == base.minor ? rt : base; - boolean x64 = reader.myLines.stream().anyMatch(s -> s.contains("64-Bit") || s.contains("x86_64") || s.contains("amd64")); - return new JdkVersionInfo(version, x64 ? Bitness.x64 : Bitness.x32); + // last resort + File javaExe = new File(homePath, "bin/" + (Platform.current().os().isWindows() ? "java.exe" : "java")); + if (javaExe.canExecute()) { + try { + Process process = new ProcessBuilder(javaExe.getPath(), "-version").redirectErrorStream(true).start(); + VersionOutputReader reader = new VersionOutputReader(process.getInputStream()); + try { + reader.waitFor(); + } + catch (InterruptedException e) { + LOG.info(e); + process.destroy(); + } + + if (!reader.myLines.isEmpty()) { + JavaVersion base = JavaVersion.parse(reader.myLines.get(0)); + JavaVersion rt = JavaVersion.tryParse(reader.myLines.size() > 2 ? reader.myLines.get(1) : null); + JavaVersion version = rt != null && rt.feature == base.feature && rt.minor == base.minor ? rt : base; + boolean x64 = + reader.myLines.stream().anyMatch(s -> s.contains("64-Bit") || s.contains("x86_64") || s.contains("amd64")); + return new JdkVersionInfo(version, x64 ? Bitness.x64 : Bitness.x32); + } + } + catch (IOException | IllegalArgumentException e) { + LOG.info(javaExe.getPath(), e); + } } - } catch (IOException | IllegalArgumentException e) { - LOG.info(javaExe.getPath(), e); - } - } - return null; - } - - private static class VersionOutputReader extends BaseOutputReader { - private static final BaseOutputReader.Options OPTIONS = new BaseOutputReader.Options() { - @Override - public SleepingPolicy policy() { - return SleepingPolicy.BLOCKING; - } - - @Override - public boolean splitToLines() { - return true; - } - - @Override - public boolean sendIncompleteLines() { - return false; - } - - @Override - public boolean withSeparators() { - return false; - } - }; - - private final List myLines; - - VersionOutputReader(@Nonnull InputStream stream) { - super(stream, CharsetToolkit.getDefaultSystemCharset(), OPTIONS); - myLines = new CopyOnWriteArrayList<>(); - start("java -version"); + return null; } - @Nonnull - @Override - protected Future executeOnPooledThread(@Nonnull Runnable runnable) { - return Application.get().executeOnPooledThread(runnable); - } + private static class VersionOutputReader extends BaseOutputReader { + private static final BaseOutputReader.Options OPTIONS = new BaseOutputReader.Options() { + @Override + public SleepingPolicy policy() { + return SleepingPolicy.BLOCKING; + } + + @Override + public boolean splitToLines() { + return true; + } + + @Override + public boolean sendIncompleteLines() { + return false; + } + + @Override + public boolean withSeparators() { + return false; + } + }; + + private final List myLines; + + VersionOutputReader(@Nonnull InputStream stream) { + super(stream, CharsetToolkit.getDefaultSystemCharset(), OPTIONS); + myLines = new CopyOnWriteArrayList<>(); + start("java -version"); + } - @Override - protected void onTextAvailable(@Nonnull String text) { - myLines.add(text); - LOG.trace("text: " + text); + @Nonnull + @Override + protected Future executeOnPooledThread(@Nonnull Runnable runnable) { + return Application.get().executeOnPooledThread(runnable); + } + + @Override + protected void onTextAvailable(@Nonnull String text) { + myLines.add(text); + LOG.trace("text: " + text); + } } - } } \ No newline at end of file diff --git a/plugin/src/main/java/com/intellij/java/impl/openapi/projectRoots/impl/DefaultJavaSdkTypeImpl.java b/plugin/src/main/java/com/intellij/java/impl/openapi/projectRoots/impl/DefaultJavaSdkTypeImpl.java index 69fbf3cb9..a9d75c751 100644 --- a/plugin/src/main/java/com/intellij/java/impl/openapi/projectRoots/impl/DefaultJavaSdkTypeImpl.java +++ b/plugin/src/main/java/com/intellij/java/impl/openapi/projectRoots/impl/DefaultJavaSdkTypeImpl.java @@ -21,7 +21,6 @@ import com.intellij.java.language.projectRoots.roots.AnnotationOrderRootType; import com.intellij.java.language.vfs.jrt.JrtFileSystem; import consulo.annotation.component.ExtensionImpl; -import consulo.application.util.SystemInfo; import consulo.container.plugin.PluginManager; import consulo.content.OrderRootType; import consulo.content.base.BinariesOrderRootType; @@ -52,7 +51,6 @@ import consulo.virtualFileSystem.util.VirtualFileUtil; import jakarta.annotation.Nonnull; import jakarta.annotation.Nullable; -import org.jetbrains.annotations.NonNls; import java.io.File; import java.io.FileFilter; @@ -68,553 +66,552 @@ */ @ExtensionImpl public class DefaultJavaSdkTypeImpl extends DefaultJavaSdkType { - private static final Logger LOG = Logger.getInstance(DefaultJavaSdkTypeImpl.class); - // do not use javaw.exe for Windows because of issues with encoding - private static final String VM_EXE_NAME = "java"; - private final Pattern myVersionStringPattern = Pattern.compile("^(.*)java version \"([1234567890_.]*)\"(.*)$"); - private static final String JAVA_VERSION_PREFIX = "java version "; - private static final String OPENJDK_VERSION_PREFIX = "openjdk version "; - public static final Key KEY = Key.create("JavaSdk"); - - public DefaultJavaSdkTypeImpl() { - super("JDK"); - } - - @Nonnull - @Override - public String getPresentableName() { - return ProjectLocalize.sdkJavaName().get(); - } - - @Nonnull - @Override - public Image getIcon() { - return JavaPsiImplIconGroup.java(); - } - - @Nonnull - @Override - public String getHelpTopic() { - return "reference.project.structure.sdk.java"; - } - - @NonNls - @Override - @Nullable - public String getDefaultDocumentationUrl(@Nonnull final Sdk sdk) { - final JavaSdkVersion version = JavaSdkTypeUtil.getVersion(sdk); - if (version == JavaSdkVersion.JDK_1_5) { - return "http://docs.oracle.com/javase/1.5.0/docs/api/"; - } - if (version == JavaSdkVersion.JDK_1_6) { - return "http://docs.oracle.com/javase/6/docs/api/"; - } - if (version == JavaSdkVersion.JDK_1_7) { - return "http://docs.oracle.com/javase/7/docs/api/"; - } - if (version == JavaSdkVersion.JDK_1_8) { - return "http://download.java.net/jdk8/docs/api/"; - } - if (version == JavaSdkVersion.JDK_1_9) { - return "http://download.java.net/jdk9/docs/api/"; - } - if (version == JavaSdkVersion.JDK_10) { - return "https://docs.oracle.com/javase/10/docs/api/"; - } - if (version == JavaSdkVersion.JDK_11) { - return "https://docs.oracle.com/en/java/javase/11/docs/api/"; - } - if (version == JavaSdkVersion.JDK_12) { - return "https://docs.oracle.com/en/java/javase/12/docs/api/"; - } - return null; - } - - @Override - @SuppressWarnings({"HardCodedStringLiteral"}) - public String getBinPath(Sdk sdk) { - return getConvertedHomePath(sdk) + "bin"; - } - - @Override - @NonNls - public String getToolsPath(Sdk sdk) { - final String versionString = sdk.getVersionString(); - final boolean isJdk1_x = versionString != null && (versionString.contains("1.0") || versionString.contains("1.1")); - return getConvertedHomePath(sdk) + "lib" + File.separator + (isJdk1_x ? "classes.zip" : "tools.jar"); - } - - @Override - public void setupCommandLine(@Nonnull GeneralCommandLine commandLine, @Nonnull Sdk sdk) { - commandLine.setExePath(getBinPath(sdk) + File.separator + VM_EXE_NAME); - } - - private static String getConvertedHomePath(Sdk sdk) { - String homePath = sdk.getHomePath(); - assert homePath != null : sdk; - String path = FileUtil.toSystemDependentName(homePath); - if (!path.endsWith(File.separator)) { - path += File.separator; - } - return path; - } - - /** - * @implNote do not chech JAVA_HOME, {@link #getEnviromentVariables(Platform)} - */ - @Nonnull - @Override - public Collection suggestHomePaths() { - List list = new ArrayList<>(); - if (Platform.current().os().isMac()) { - collectJavaPathsAtMac(list, "/Library/Java/JavaVirtualMachines"); - collectJavaPathsAtMac(list, "/System/Library/Java/JavaVirtualMachines"); - list.add("/usr/libexec/java_home"); - } - else if (Platform.current().os().isLinux()) { - list.add("/usr/java"); - list.add("/opt/java"); - list.add("/usr/lib/jvm"); - } - else if (Platform.current().os().isWindows()) { - collectJavaPathsAtWindows(list, "ProgramFiles"); - collectJavaPathsAtWindows(list, "ProgramFiles(x86)"); - } - - // JDKs in SDKMan located at $HOME/.sdkman/candidates/java/ - File sdkmanJavaDir = new File(SystemProperties.getUserHome(), "/.sdkman/candidates/java/"); - if (sdkmanJavaDir.exists()) { - collectJavaPathsAtSdkman(list, sdkmanJavaDir); - } - - return list; - } - - @Nonnull - @Override - public Set getEnviromentVariables(@Nonnull Platform platform) { - return Set.of("JAVA_HOME"); - } - - private void collectJavaPathsAtSdkman(List list, File sdkmanJavaDir) { - File[] files = sdkmanJavaDir.listFiles(); - if (files != null) { - for (File dir : files) { - if (!dir.getName().equals("current")) // skip "current" directory, because it's link - { - list.add(dir.getAbsolutePath()); - } - } - } - } - - private static void collectJavaPathsAtMac(List list, String path) { - File dir = new File(path); - if (dir.exists()) { - File[] files = dir.listFiles(); - if (files != null) { - for (File file : files) { - list.add(file.getPath()); - } - } - } - } - - private static void collectJavaPathsAtWindows(List list, String env) { - String programFiles = Platform.current().os().getEnvironmentVariable(env); - if (programFiles != null) { - File temp = new File(programFiles, "Java"); - File[] files = temp.listFiles(); - if (files != null) { - for (File file : files) { - list.add(file.getPath()); - } - } - } - } - - @Override - public boolean canCreatePredefinedSdks() { - return true; - } - - @Override - public FileChooserDescriptor getHomeChooserDescriptor() { - FileChooserDescriptor descriptor = super.getHomeChooserDescriptor(); - descriptor.putUserData(KEY, Boolean.TRUE); - return descriptor; - } - - @NonNls - public static final String MAC_HOME_PATH = "/Home"; - - @Override - public String adjustSelectedSdkHome(String homePath) { - if (Platform.current().os().isMac()) { - File home = new File(homePath, MAC_HOME_PATH); - if (home.exists()) { - return home.getPath(); - } - - home = new File(new File(homePath, "Contents"), "Home"); - if (home.exists()) { - return home.getPath(); - } - } - - return homePath; - } - - @Override - public boolean isValidSdkHome(String path) { - return OwnJdkUtil.checkForJdk(new File(path)); - } - - @Override - public String suggestSdkName(String currentSdkName, String sdkHome) { - final String suggestedName; - if (currentSdkName != null && !currentSdkName.isEmpty()) { - final Matcher matcher = myVersionStringPattern.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 ? ProjectLocalize.sdkJavaUnknownName().get() : getVersionNumber(versionString); - } - return suggestedName; - } - - @Nonnull - private static String getVersionNumber(@Nonnull 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) { + private static final Logger LOG = Logger.getInstance(DefaultJavaSdkTypeImpl.class); + // do not use javaw.exe for Windows because of issues with encoding + private static final String VM_EXE_NAME = "java"; + private final Pattern myVersionStringPattern = Pattern.compile("^(.*)java version \"([1234567890_.]*)\"(.*)$"); + private static final String JAVA_VERSION_PREFIX = "java version "; + private static final String OPENJDK_VERSION_PREFIX = "openjdk version "; + public static final Key KEY = Key.create("JavaSdk"); + + public DefaultJavaSdkTypeImpl() { + super("JDK"); + } + + @Nonnull + @Override + public String getPresentableName() { + return ProjectLocalize.sdkJavaName().get(); + } + + @Nonnull + @Override + public Image getIcon() { + return JavaPsiImplIconGroup.java(); + } + + @Nonnull + @Override + public String getHelpTopic() { + return "reference.project.structure.sdk.java"; + } + + @Override + @Nullable + public String getDefaultDocumentationUrl(@Nonnull final Sdk sdk) { + final JavaSdkVersion version = JavaSdkTypeUtil.getVersion(sdk); + if (version == JavaSdkVersion.JDK_1_5) { + return "http://docs.oracle.com/javase/1.5.0/docs/api/"; + } + if (version == JavaSdkVersion.JDK_1_6) { + return "http://docs.oracle.com/javase/6/docs/api/"; + } + if (version == JavaSdkVersion.JDK_1_7) { + return "http://docs.oracle.com/javase/7/docs/api/"; + } + if (version == JavaSdkVersion.JDK_1_8) { + return "http://download.java.net/jdk8/docs/api/"; + } + if (version == JavaSdkVersion.JDK_1_9) { + return "http://download.java.net/jdk9/docs/api/"; + } + if (version == JavaSdkVersion.JDK_10) { + return "https://docs.oracle.com/javase/10/docs/api/"; + } + if (version == JavaSdkVersion.JDK_11) { + return "https://docs.oracle.com/en/java/javase/11/docs/api/"; + } + if (version == JavaSdkVersion.JDK_12) { + return "https://docs.oracle.com/en/java/javase/12/docs/api/"; + } + return null; + } + + @Override + @SuppressWarnings({"HardCodedStringLiteral"}) + public String getBinPath(Sdk sdk) { + return getConvertedHomePath(sdk) + "bin"; + } + + @Override + public String getToolsPath(Sdk sdk) { + final String versionString = sdk.getVersionString(); + final boolean isJdk1_x = versionString != null && (versionString.contains("1.0") || versionString.contains("1.1")); + return getConvertedHomePath(sdk) + "lib" + File.separator + (isJdk1_x ? "classes.zip" : "tools.jar"); + } + + @Override + public void setupCommandLine(@Nonnull GeneralCommandLine commandLine, @Nonnull Sdk sdk) { + commandLine.setExePath(getBinPath(sdk) + File.separator + VM_EXE_NAME); + } + + private static String getConvertedHomePath(Sdk sdk) { + String homePath = sdk.getHomePath(); + assert homePath != null : sdk; + String path = FileUtil.toSystemDependentName(homePath); + if (!path.endsWith(File.separator)) { + path += File.separator; + } + return path; + } + + /** + * @implNote do not chech JAVA_HOME, {@link #getEnviromentVariables(Platform)} + */ + @Nonnull + @Override + public Collection suggestHomePaths() { + List list = new ArrayList<>(); + if (Platform.current().os().isMac()) { + collectJavaPathsAtMac(list, "/Library/Java/JavaVirtualMachines"); + collectJavaPathsAtMac(list, "/System/Library/Java/JavaVirtualMachines"); + list.add("/usr/libexec/java_home"); + } + else if (Platform.current().os().isLinux()) { + list.add("/usr/java"); + list.add("/opt/java"); + list.add("/usr/lib/jvm"); + } + else if (Platform.current().os().isWindows()) { + collectJavaPathsAtWindows(list, "ProgramFiles"); + collectJavaPathsAtWindows(list, "ProgramFiles(x86)"); + } + + // JDKs in SDKMan located at $HOME/.sdkman/candidates/java/ + File sdkmanJavaDir = new File(SystemProperties.getUserHome(), "/.sdkman/candidates/java/"); + if (sdkmanJavaDir.exists()) { + collectJavaPathsAtSdkman(list, sdkmanJavaDir); + } + + return list; + } + + @Nonnull + @Override + public Set getEnviromentVariables(@Nonnull Platform platform) { + return Set.of("JAVA_HOME"); + } + + private void collectJavaPathsAtSdkman(List list, File sdkmanJavaDir) { + File[] files = sdkmanJavaDir.listFiles(); + if (files != null) { + for (File dir : files) { + if (!dir.getName().equals("current")) // skip "current" directory, because it's link + { + list.add(dir.getAbsolutePath()); + } + } + } + } + + private static void collectJavaPathsAtMac(List list, String path) { + File dir = new File(path); + if (dir.exists()) { + File[] files = dir.listFiles(); + if (files != null) { + for (File file : files) { + list.add(file.getPath()); + } + } + } + } + + private static void collectJavaPathsAtWindows(List list, String env) { + String programFiles = Platform.current().os().getEnvironmentVariable(env); + if (programFiles != null) { + File temp = new File(programFiles, "Java"); + File[] files = temp.listFiles(); + if (files != null) { + for (File file : files) { + list.add(file.getPath()); + } + } + } + } + + @Override + public boolean canCreatePredefinedSdks() { + return true; + } + + @Nonnull + @Override + public FileChooserDescriptor getHomeChooserDescriptor() { + FileChooserDescriptor descriptor = super.getHomeChooserDescriptor(); + descriptor.putUserData(KEY, Boolean.TRUE); + return descriptor; + } + + public static final String MAC_HOME_PATH = "/Home"; + + @Override + public String adjustSelectedSdkHome(String homePath) { + if (Platform.current().os().isMac()) { + File home = new File(homePath, MAC_HOME_PATH); + if (home.exists()) { + return home.getPath(); + } + + home = new File(new File(homePath, "Contents"), "Home"); + if (home.exists()) { + return home.getPath(); + } + } + + return homePath; + } + + @Override + public boolean isValidSdkHome(String path) { + return OwnJdkUtil.checkForJdk(new File(path)); + } + + @Override + public String suggestSdkName(String currentSdkName, String sdkHome) { + final String suggestedName; + if (currentSdkName != null && !currentSdkName.isEmpty()) { + final Matcher matcher = myVersionStringPattern.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 ? ProjectLocalize.sdkJavaUnknownName().get() : getVersionNumber(versionString); + } + return suggestedName; + } + + @Nonnull + private static String getVersionNumber(@Nonnull 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; + } + + @Override + public void setupSdkPaths(Sdk sdk) { + final File jdkHome = new File(sdk.getHomePath()); + + final SdkModificator sdkModificator = sdk.getSdkModificator(); + + boolean isModuleJdk = false; + File jmodsDirectory = new File(jdkHome, "jmods"); + if (jmodsDirectory.exists() && jmodsDirectory.isDirectory()) { + isModuleJdk = true; + File[] files = jmodsDirectory.listFiles(); + for (File file : files) { + VirtualFile jmodFile = JModFileType.INSTANCE.getFileSystem().findLocalVirtualFileByPath(file.getPath()); + if (jmodFile != null) { + VirtualFile classesDir = jmodFile.findChild("classes"); + if (classesDir != null) { + sdkModificator.addRoot(classesDir, BinariesOrderRootType.getInstance()); + } + } + } + } + else if (OwnJdkUtil.isModularRuntime(jdkHome)) { + String jrtBaseUrl = JrtFileSystem.PROTOCOL_PREFIX + getPath(jdkHome) + JrtFileSystem.SEPARATOR; + List modules = readModulesFromReleaseFile(jdkHome); + if (modules != null) { + for (String module : modules) { + sdkModificator.addRoot(jrtBaseUrl + module, BinariesOrderRootType.getInstance()); + } + } + else { + VirtualFile jrt = VirtualFileManager.getInstance().findFileByUrl(jrtBaseUrl); + if (jrt != null) { + for (VirtualFile virtualFile : jrt.getChildren()) { + sdkModificator.addRoot(virtualFile.getUrl(), BinariesOrderRootType.getInstance()); + } + } + } + } + else { + addJavaFxSources(jdkHome, sdkModificator); + + for (VirtualFile aClass : findClasses(jdkHome, false)) { + sdkModificator.addRoot(aClass, BinariesOrderRootType.getInstance()); + } + } + + boolean noSources = true; + VirtualFile srcZipFile = + ZipArchiveFileType.INSTANCE.getFileSystem().findLocalVirtualFileByPath(new File(jdkHome, "src.zip").getPath()); + if (srcZipFile == null) { + srcZipFile = ZipArchiveFileType.INSTANCE.getFileSystem().findLocalVirtualFileByPath(new File(jdkHome, "lib/src.zip").getPath()); + } + + if (srcZipFile != null) { + noSources = false; + + if (isModuleJdk) { + VirtualFile[] children = srcZipFile.getChildren(); + for (VirtualFile child : children) { + if (child.isDirectory()) { + sdkModificator.addRoot(child, SourcesOrderRootType.getInstance()); + } + } + } + else { + sdkModificator.addRoot(srcZipFile, SourcesOrderRootType.getInstance()); + } + } + + VirtualFile docs = findDocs(jdkHome, "docs/api"); + if (docs != null) { + sdkModificator.addRoot(docs, DocumentationOrderRootType.getInstance()); + } + else if (Platform.current().os().isMac()) { + VirtualFile commonDocs = findDocs(jdkHome, "docs"); + if (commonDocs == null) { + commonDocs = findInJar(new File(jdkHome, "docs.jar"), "doc/api"); + if (commonDocs == null) { + commonDocs = findInJar(new File(jdkHome, "docs.jar"), "docs/api"); + } + } + if (commonDocs != null) { + sdkModificator.addRoot(commonDocs, DocumentationOrderRootType.getInstance()); + } + + VirtualFile appleDocs = findDocs(jdkHome, "appledocs"); + if (appleDocs == null) { + appleDocs = findInJar(new File(jdkHome, "appledocs.jar"), "appledoc/api"); + } + if (appleDocs != null) { + sdkModificator.addRoot(appleDocs, DocumentationOrderRootType.getInstance()); + } + + if (commonDocs == null && appleDocs == null && noSources) { + String url = getDefaultDocumentationUrl(sdk); + if (url != null) { + sdkModificator.addRoot(VirtualFileManager.getInstance().findFileByUrl(url), DocumentationOrderRootType.getInstance()); + } + } + } + attachJdkAnnotations(sdkModificator); + sdkModificator.commitChanges(); + } + + private static String getPath(File jarFile) { + return FileUtil.toSystemIndependentName(jarFile.getAbsolutePath()); + } + + /** + * Tries to load the list of modules in the JDK from the 'release' file. Returns null if the 'release' file is not there + * or doesn't contain the expected information. + */ + @Nullable + private static List readModulesFromReleaseFile(File jrtBaseDir) { + File releaseFile = new File(jrtBaseDir, "release"); + if (releaseFile.isFile()) { + try (FileInputStream stream = new FileInputStream(releaseFile)) { + Properties p = new Properties(); + p.load(stream); + String modules = p.getProperty("MODULES"); + if (modules != null) { + return StringUtil.split(StringUtil.unquoteString(modules), " "); + } + } + catch (IOException | IllegalArgumentException e) { + LOG.info(e); + } + } + return null; + } + + public static boolean attachJdkAnnotations(@Nonnull SdkModificator modificator) { + File pluginPath = PluginManager.getPluginPath(DefaultJavaSdkTypeImpl.class); + + File file = new File(pluginPath, "jdk-annotations.jar"); + + VirtualFile localFile = LocalFileSystem.getInstance().findFileByIoFile(file); + + if (localFile == null) { + LOG.error("jdk annotations not found in: " + file); + return false; + } + + VirtualFile jarFile = ArchiveVfsUtil.getArchiveRootForLocalFile(localFile); + if (jarFile == null) { + LOG.error("jdk annotations is not archive: " + file); + return false; + } + + OrderRootType annoType = AnnotationOrderRootType.getInstance(); + modificator.removeRoot(jarFile, annoType); + modificator.addRoot(jarFile, annoType); + return true; + } + + @Override + public final String getVersionString(final String sdkHome) { + OwnJdkVersionDetector.JdkVersionInfo jdkInfo = OwnJdkVersionDetector.getInstance().detectJdkVersionInfo(sdkHome); + return jdkInfo != null ? OwnJdkVersionDetector.formatVersionString(jdkInfo.version) : null; + } + + private static List findClasses(File file, boolean isJre) { + List result = new ArrayList<>(); + + List rootFiles = getJdkClassesRoots(file, isJre); + for (File child : rootFiles) { + String url = VirtualFileUtil.getUrlForLibraryRoot(child); + VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(url); + if (vFile != null) { + result.add(vFile); + } + } + + return result; + } + + public static List getJdkClassesRoots(File home, boolean isJre) { + FileFilter jarFileFilter = f -> !f.isDirectory() && f.getName().endsWith(".jar"); + + File[] jarDirs; + if (Platform.current().os().isMac() && !home.getName().startsWith("mockJDK")) { + File openJdkRtJar = new File(home, "jre/lib/rt.jar"); + if (openJdkRtJar.exists() && !openJdkRtJar.isDirectory()) { + File libDir = new File(home, "lib"); + File classesDir = openJdkRtJar.getParentFile(); + File libExtDir = new File(openJdkRtJar.getParentFile(), "ext"); + File libEndorsedDir = new File(libDir, "endorsed"); + jarDirs = new File[]{ + libEndorsedDir, + libDir, + classesDir, + libExtDir + }; + } + else { + File libDir = new File(home, "lib"); + File classesDir = new File(home, "../Classes"); + File libExtDir = new File(libDir, "ext"); + File libEndorsedDir = new File(libDir, "endorsed"); + jarDirs = new File[]{ + libEndorsedDir, + libDir, + classesDir, + libExtDir + }; + } + } + else { + File libDir = isJre ? new File(home, "lib") : new File(home, "jre/lib"); + File libExtDir = new File(libDir, "ext"); + File libEndorsedDir = new File(libDir, "endorsed"); + jarDirs = new File[]{ + libEndorsedDir, + libDir, + libExtDir + }; + } + + Set pathFilter = Sets.newHashSet(FileUtil.PATH_HASHING_STRATEGY); + List rootFiles = new ArrayList<>(); + for (File jarDir : jarDirs) { + if (jarDir != null && jarDir.isDirectory()) { + File[] jarFiles = jarDir.listFiles(jarFileFilter); + for (File jarFile : jarFiles) { + String jarFileName = jarFile.getName(); + if (jarFileName.equals("alt-rt.jar") || jarFileName.equals("alt-string.jar")) { + continue; // filter out alternative implementations + } + String canonicalPath = getCanonicalPath(jarFile); + if (canonicalPath == null || !pathFilter.add(canonicalPath)) { + continue; // filter out duplicate (symbolically linked) .jar files commonly found in OS X JDK distributions + } + rootFiles.add(jarFile); + } + } + } + + File classesZip = new File(home, "lib/classes.zip"); + if (classesZip.isFile()) { + rootFiles.add(classesZip); + } + + File classesDir = new File(home, "classes"); + if (rootFiles.isEmpty() && classesDir.isDirectory()) { + rootFiles.add(classesDir); + } + + return rootFiles; + } + + + @Nullable + private static String getCanonicalPath(File file) { 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; - } - - @Override - public void setupSdkPaths(Sdk sdk) { - final File jdkHome = new File(sdk.getHomePath()); - - final SdkModificator sdkModificator = sdk.getSdkModificator(); - - boolean isModuleJdk = false; - File jmodsDirectory = new File(jdkHome, "jmods"); - if (jmodsDirectory.exists() && jmodsDirectory.isDirectory()) { - isModuleJdk = true; - File[] files = jmodsDirectory.listFiles(); - for (File file : files) { - VirtualFile jmodFile = JModFileType.INSTANCE.getFileSystem().findLocalVirtualFileByPath(file.getPath()); - if (jmodFile != null) { - VirtualFile classesDir = jmodFile.findChild("classes"); - if (classesDir != null) { - sdkModificator.addRoot(classesDir, BinariesOrderRootType.getInstance()); - } - } - } - } - else if (OwnJdkUtil.isModularRuntime(jdkHome)) { - String jrtBaseUrl = JrtFileSystem.PROTOCOL_PREFIX + getPath(jdkHome) + JrtFileSystem.SEPARATOR; - List modules = readModulesFromReleaseFile(jdkHome); - if (modules != null) { - for (String module : modules) { - sdkModificator.addRoot(jrtBaseUrl + module, BinariesOrderRootType.getInstance()); - } - } - else { - VirtualFile jrt = VirtualFileManager.getInstance().findFileByUrl(jrtBaseUrl); - if (jrt != null) { - for (VirtualFile virtualFile : jrt.getChildren()) { - sdkModificator.addRoot(virtualFile.getUrl(), BinariesOrderRootType.getInstance()); - } - } - } - } - else { - addJavaFxSources(jdkHome, sdkModificator); - - for (VirtualFile aClass : findClasses(jdkHome, false)) { - sdkModificator.addRoot(aClass, BinariesOrderRootType.getInstance()); - } - } - - boolean noSources = true; - VirtualFile srcZipFile = ZipArchiveFileType.INSTANCE.getFileSystem().findLocalVirtualFileByPath(new File(jdkHome, "src.zip").getPath()); - if (srcZipFile == null) { - srcZipFile = ZipArchiveFileType.INSTANCE.getFileSystem().findLocalVirtualFileByPath(new File(jdkHome, "lib/src.zip").getPath()); - } - - if (srcZipFile != null) { - noSources = false; - - if (isModuleJdk) { - VirtualFile[] children = srcZipFile.getChildren(); - for (VirtualFile child : children) { - if (child.isDirectory()) { - sdkModificator.addRoot(child, SourcesOrderRootType.getInstance()); - } - } - } - else { - sdkModificator.addRoot(srcZipFile, SourcesOrderRootType.getInstance()); - } - } - - VirtualFile docs = findDocs(jdkHome, "docs/api"); - if (docs != null) { - sdkModificator.addRoot(docs, DocumentationOrderRootType.getInstance()); - } - else if (Platform.current().os().isMac()) { - VirtualFile commonDocs = findDocs(jdkHome, "docs"); - if (commonDocs == null) { - commonDocs = findInJar(new File(jdkHome, "docs.jar"), "doc/api"); - if (commonDocs == null) { - commonDocs = findInJar(new File(jdkHome, "docs.jar"), "docs/api"); - } - } - if (commonDocs != null) { - sdkModificator.addRoot(commonDocs, DocumentationOrderRootType.getInstance()); - } - - VirtualFile appleDocs = findDocs(jdkHome, "appledocs"); - if (appleDocs == null) { - appleDocs = findInJar(new File(jdkHome, "appledocs.jar"), "appledoc/api"); - } - if (appleDocs != null) { - sdkModificator.addRoot(appleDocs, DocumentationOrderRootType.getInstance()); - } - - if (commonDocs == null && appleDocs == null && noSources) { - String url = getDefaultDocumentationUrl(sdk); - if (url != null) { - sdkModificator.addRoot(VirtualFileManager.getInstance().findFileByUrl(url), DocumentationOrderRootType.getInstance()); - } - } - } - attachJdkAnnotations(sdkModificator); - sdkModificator.commitChanges(); - } - - private static String getPath(File jarFile) { - return FileUtil.toSystemIndependentName(jarFile.getAbsolutePath()); - } - - /** - * Tries to load the list of modules in the JDK from the 'release' file. Returns null if the 'release' file is not there - * or doesn't contain the expected information. - */ - @Nullable - private static List readModulesFromReleaseFile(File jrtBaseDir) { - File releaseFile = new File(jrtBaseDir, "release"); - if (releaseFile.isFile()) { - try (FileInputStream stream = new FileInputStream(releaseFile)) { - Properties p = new Properties(); - p.load(stream); - String modules = p.getProperty("MODULES"); - if (modules != null) { - return StringUtil.split(StringUtil.unquoteString(modules), " "); - } - } - catch (IOException | IllegalArgumentException e) { - LOG.info(e); - } - } - return null; - } - - public static boolean attachJdkAnnotations(@Nonnull SdkModificator modificator) { - File pluginPath = PluginManager.getPluginPath(DefaultJavaSdkTypeImpl.class); - - File file = new File(pluginPath, "jdk-annotations.jar"); - - VirtualFile localFile = LocalFileSystem.getInstance().findFileByIoFile(file); - - if (localFile == null) { - LOG.error("jdk annotations not found in: " + file); - return false; - } - - VirtualFile jarFile = ArchiveVfsUtil.getArchiveRootForLocalFile(localFile); - if (jarFile == null) { - LOG.error("jdk annotations is not archive: " + file); - return false; - } - - OrderRootType annoType = AnnotationOrderRootType.getInstance(); - modificator.removeRoot(jarFile, annoType); - modificator.addRoot(jarFile, annoType); - return true; - } - - @Override - public final String getVersionString(final String sdkHome) { - OwnJdkVersionDetector.JdkVersionInfo jdkInfo = OwnJdkVersionDetector.getInstance().detectJdkVersionInfo(sdkHome); - return jdkInfo != null ? OwnJdkVersionDetector.formatVersionString(jdkInfo.version) : null; - } - - private static List findClasses(File file, boolean isJre) { - List result = new ArrayList<>(); - - List rootFiles = getJdkClassesRoots(file, isJre); - for (File child : rootFiles) { - String url = VirtualFileUtil.getUrlForLibraryRoot(child); - VirtualFile vFile = VirtualFileManager.getInstance().findFileByUrl(url); - if (vFile != null) { - result.add(vFile); - } - } - - return result; - } - - public static List getJdkClassesRoots(File home, boolean isJre) { - FileFilter jarFileFilter = f -> !f.isDirectory() && f.getName().endsWith(".jar"); - - File[] jarDirs; - if (Platform.current().os().isMac() && !home.getName().startsWith("mockJDK")) { - File openJdkRtJar = new File(home, "jre/lib/rt.jar"); - if (openJdkRtJar.exists() && !openJdkRtJar.isDirectory()) { - File libDir = new File(home, "lib"); - File classesDir = openJdkRtJar.getParentFile(); - File libExtDir = new File(openJdkRtJar.getParentFile(), "ext"); - File libEndorsedDir = new File(libDir, "endorsed"); - jarDirs = new File[]{ - libEndorsedDir, - libDir, - classesDir, - libExtDir - }; - } - else { - File libDir = new File(home, "lib"); - File classesDir = new File(home, "../Classes"); - File libExtDir = new File(libDir, "ext"); - File libEndorsedDir = new File(libDir, "endorsed"); - jarDirs = new File[]{ - libEndorsedDir, - libDir, - classesDir, - libExtDir - }; - } - } - else { - File libDir = isJre ? new File(home, "lib") : new File(home, "jre/lib"); - File libExtDir = new File(libDir, "ext"); - File libEndorsedDir = new File(libDir, "endorsed"); - jarDirs = new File[]{ - libEndorsedDir, - libDir, - libExtDir - }; - } - - Set pathFilter = Sets.newHashSet(FileUtil.PATH_HASHING_STRATEGY); - List rootFiles = new ArrayList<>(); - for (File jarDir : jarDirs) { - if (jarDir != null && jarDir.isDirectory()) { - File[] jarFiles = jarDir.listFiles(jarFileFilter); - for (File jarFile : jarFiles) { - String jarFileName = jarFile.getName(); - if (jarFileName.equals("alt-rt.jar") || jarFileName.equals("alt-string.jar")) { - continue; // filter out alternative implementations - } - String canonicalPath = getCanonicalPath(jarFile); - if (canonicalPath == null || !pathFilter.add(canonicalPath)) { - continue; // filter out duplicate (symbolically linked) .jar files commonly found in OS X JDK distributions - } - rootFiles.add(jarFile); - } - } - } - - File classesZip = new File(home, "lib/classes.zip"); - if (classesZip.isFile()) { - rootFiles.add(classesZip); - } - - File classesDir = new File(home, "classes"); - if (rootFiles.isEmpty() && classesDir.isDirectory()) { - rootFiles.add(classesDir); - } - - return rootFiles; - } - - - @Nullable - private static String getCanonicalPath(File file) { - try { - return file.getCanonicalPath(); - } - catch (IOException e) { - return null; - } - } - - private static void addJavaFxSources(File file, SdkModificator sdkModificator) { - VirtualFile fileByIoFile = LocalFileSystem.getInstance().findFileByIoFile(new File(file, "javafx-src.zip")); - if (fileByIoFile == null) { - return; - } - VirtualFile archiveRootForLocalFile = ArchiveVfsUtil.getArchiveRootForLocalFile(fileByIoFile); - if (archiveRootForLocalFile == null) { - return; - } - sdkModificator.addRoot(archiveRootForLocalFile, SourcesOrderRootType.getInstance()); - } - - @Nullable - private static VirtualFile findInJar(File jarFile, String relativePath) { - VirtualFile fileByIoFile = LocalFileSystem.getInstance().findFileByIoFile(jarFile); - if (fileByIoFile == null) { - return null; - } - VirtualFile archiveRootForLocalFile = ArchiveVfsUtil.getArchiveRootForLocalFile(fileByIoFile); - return archiveRootForLocalFile == null ? null : archiveRootForLocalFile.findFileByRelativePath(relativePath); - } - - @Nullable - public static VirtualFile findDocs(File file, final String relativePath) { - file = new File(file.getAbsolutePath() + File.separator + relativePath.replace('/', File.separatorChar)); - if (!file.exists() || !file.isDirectory()) { - return null; - } - String path = file.getAbsolutePath().replace(File.separatorChar, '/'); - return LocalFileSystem.getInstance().findFileByPath(path); - } - - @Override - public boolean isRootTypeApplicable(OrderRootType type) { - return type == BinariesOrderRootType.getInstance() || - type == SourcesOrderRootType.getInstance() || - type == DocumentationOrderRootType.getInstance() || - type == AnnotationOrderRootType.getInstance(); - } + return file.getCanonicalPath(); + } + catch (IOException e) { + return null; + } + } + + private static void addJavaFxSources(File file, SdkModificator sdkModificator) { + VirtualFile fileByIoFile = LocalFileSystem.getInstance().findFileByIoFile(new File(file, "javafx-src.zip")); + if (fileByIoFile == null) { + return; + } + VirtualFile archiveRootForLocalFile = ArchiveVfsUtil.getArchiveRootForLocalFile(fileByIoFile); + if (archiveRootForLocalFile == null) { + return; + } + sdkModificator.addRoot(archiveRootForLocalFile, SourcesOrderRootType.getInstance()); + } + + @Nullable + private static VirtualFile findInJar(File jarFile, String relativePath) { + VirtualFile fileByIoFile = LocalFileSystem.getInstance().findFileByIoFile(jarFile); + if (fileByIoFile == null) { + return null; + } + VirtualFile archiveRootForLocalFile = ArchiveVfsUtil.getArchiveRootForLocalFile(fileByIoFile); + return archiveRootForLocalFile == null ? null : archiveRootForLocalFile.findFileByRelativePath(relativePath); + } + + @Nullable + public static VirtualFile findDocs(File file, final String relativePath) { + file = new File(file.getAbsolutePath() + File.separator + relativePath.replace('/', File.separatorChar)); + if (!file.exists() || !file.isDirectory()) { + return null; + } + String path = file.getAbsolutePath().replace(File.separatorChar, '/'); + return LocalFileSystem.getInstance().findFileByPath(path); + } + + @Override + public boolean isRootTypeApplicable(OrderRootType type) { + return type == BinariesOrderRootType.getInstance() + || type == SourcesOrderRootType.getInstance() + || type == DocumentationOrderRootType.getInstance() + || type == AnnotationOrderRootType.getInstance(); + } }