mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
[platform] migrates JdkVersionDetector service to new Java version parser
This commit is contained in:
@@ -1,21 +1,10 @@
|
||||
/*
|
||||
* Copyright 2000-2016 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 org.jetbrains.jps.model.java;
|
||||
|
||||
import com.intellij.openapi.util.Bitness;
|
||||
import com.intellij.util.lang.JavaVersion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.service.JpsServiceManager;
|
||||
@@ -30,18 +19,21 @@ public abstract class JdkVersionDetector {
|
||||
return JpsServiceManager.getInstance().getService(JdkVersionDetector.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns java version for JDK located at {@code homePath} in format like<br>
|
||||
* <tt>java version "1.8.0_40"</tt><br>
|
||||
* by running '<tt>java -version</tt>' command
|
||||
* @param homePath path to JDK home directory
|
||||
* @return version string of {@code null} if version cannot be determined
|
||||
*/
|
||||
/** @deprecated use {@link #detectJdkVersionInfo(String)} (to be removed in IDEA 2019) */
|
||||
@Nullable
|
||||
public abstract String detectJdkVersion(@NotNull String homePath);
|
||||
@SuppressWarnings("deprecation")
|
||||
public String detectJdkVersion(@NotNull String homePath) {
|
||||
JdkVersionInfo info = detectJdkVersionInfo(homePath);
|
||||
return info != null ? info.getVersion() : null;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #detectJdkVersionInfo(String, ActionRunner)} (to be removed in IDEA 2019) */
|
||||
@Nullable
|
||||
public abstract String detectJdkVersion(@NotNull String homePath, @NotNull ActionRunner actionRunner);
|
||||
@SuppressWarnings("deprecation")
|
||||
public String detectJdkVersion(@NotNull String homePath, @NotNull ActionRunner runner) {
|
||||
JdkVersionInfo info = detectJdkVersionInfo(homePath, runner);
|
||||
return info != null ? info.getVersion() : null;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public abstract JdkVersionInfo detectJdkVersionInfo(@NotNull String homePath);
|
||||
@@ -55,22 +47,27 @@ public abstract class JdkVersionDetector {
|
||||
}
|
||||
|
||||
public static final class JdkVersionInfo {
|
||||
private final String myVersion;
|
||||
private final Bitness myBitness;
|
||||
public final JavaVersion version;
|
||||
public final Bitness bitness;
|
||||
|
||||
public JdkVersionInfo(@NotNull String version, @NotNull Bitness bitness) {
|
||||
myVersion = version;
|
||||
myBitness = bitness;
|
||||
public JdkVersionInfo(@NotNull JavaVersion version, @NotNull Bitness bitness) {
|
||||
this.version = version;
|
||||
this.bitness = bitness;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String toString() {
|
||||
return version + " " + bitness;
|
||||
}
|
||||
|
||||
/** @deprecated use {@link #version} (to be removed in IDEA 2019) */
|
||||
public String getVersion() {
|
||||
return myVersion;
|
||||
return "java version \"" + version + '"';
|
||||
}
|
||||
|
||||
@NotNull
|
||||
/** @deprecated use {@link #bitness} (to be removed in IDEA 2019) */
|
||||
public Bitness getBitness() {
|
||||
return myBitness;
|
||||
return bitness;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,5 @@
|
||||
/*
|
||||
* 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 org.jetbrains.jps.model.java.impl;
|
||||
|
||||
@@ -21,6 +9,7 @@ import com.intellij.openapi.util.SystemInfo;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.util.io.BaseOutputReader;
|
||||
import com.intellij.util.lang.JavaVersion;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jps.model.java.JdkVersionDetector;
|
||||
@@ -44,67 +33,58 @@ public class JdkVersionDetectorImpl extends JdkVersionDetector {
|
||||
private static final Logger LOG = Logger.getInstance("#com.intellij.openapi.projectRoots.impl.SdkVersionUtil");
|
||||
private static final ActionRunner ACTION_RUNNER = r -> SharedThreadPool.getInstance().executeOnPooledThread(r);
|
||||
|
||||
@Override
|
||||
@Nullable
|
||||
public String detectJdkVersion(@NotNull String homePath) {
|
||||
return detectJdkVersion(homePath, ACTION_RUNNER);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String detectJdkVersion(@NotNull String homePath, @NotNull ActionRunner runner) {
|
||||
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 version = manifest.getMainAttributes().getValue("Implementation-Version");
|
||||
if (version != null) {
|
||||
return "java version \"" + version + "\"";
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info(e);
|
||||
}
|
||||
}
|
||||
|
||||
JdkVersionInfo info = detectJdkVersionInfo(homePath, runner);
|
||||
return info != null ? info.getVersion() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JdkVersionInfo detectJdkVersionInfo(@NotNull String homePath) {
|
||||
return detectJdkVersionInfo(homePath, ACTION_RUNNER);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
public JdkVersionInfo detectJdkVersionInfo(@NotNull String homePath, @NotNull ActionRunner runner) {
|
||||
// Java 1.7+
|
||||
File releaseFile = new File(homePath, "release");
|
||||
if (releaseFile.isFile()) {
|
||||
try {
|
||||
Properties p = new Properties();
|
||||
p.load(new FileInputStream(releaseFile));
|
||||
String version = p.getProperty("JAVA_FULL_VERSION", p.getProperty("JAVA_VERSION"));
|
||||
if (version != null) {
|
||||
version = StringUtil.unquoteString(version);
|
||||
int i = version.indexOf('+');
|
||||
if (i > 0) {
|
||||
version = version.substring(0, i);
|
||||
}
|
||||
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("java version \"" + version + "\"", x64 ? Bitness.x64 : Bitness.x32);
|
||||
return new JdkVersionInfo(version, x64 ? Bitness.x64 : Bitness.x32);
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
LOG.info(e);
|
||||
catch (IOException | IllegalArgumentException e) {
|
||||
LOG.info(releaseFile.getPath(), e);
|
||||
}
|
||||
}
|
||||
|
||||
String javaExe = homePath + File.separator + "bin" + File.separator + (SystemInfo.isWindows ? "java.exe" : "java");
|
||||
if (new File(javaExe).canExecute()) {
|
||||
// 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 = new File(rtFile.getParent(), "amd64").isDirectory();
|
||||
return new JdkVersionInfo(version, x64 ? Bitness.x64 : Bitness.x32);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException | IllegalArgumentException e) {
|
||||
LOG.info(rtFile.getPath(), e);
|
||||
}
|
||||
}
|
||||
|
||||
// last resort
|
||||
File javaExe = new File(homePath, "bin/" + (SystemInfo.isWindows ? "java.exe" : "java"));
|
||||
if (javaExe.canExecute()) {
|
||||
try {
|
||||
Process process = new ProcessBuilder(javaExe, "-version").redirectErrorStream(true).start();
|
||||
Process process = new ProcessBuilder(javaExe.getPath(), "-version").redirectErrorStream(true).start();
|
||||
VersionOutputReader reader = new VersionOutputReader(process.getInputStream(), runner);
|
||||
try {
|
||||
reader.waitFor();
|
||||
@@ -113,10 +93,17 @@ public class JdkVersionDetectorImpl extends JdkVersionDetector {
|
||||
LOG.info(e);
|
||||
process.destroy();
|
||||
}
|
||||
return reader.getVersionInfo();
|
||||
|
||||
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 e) {
|
||||
LOG.info(e);
|
||||
catch (IOException | IllegalArgumentException e) {
|
||||
LOG.info(javaExe.getPath(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -150,27 +137,7 @@ public class JdkVersionDetectorImpl extends JdkVersionDetector {
|
||||
@Override
|
||||
protected void onTextAvailable(@NotNull String text) {
|
||||
myLines.add(text);
|
||||
LOG.debug("text: " + text);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JdkVersionInfo getVersionInfo() {
|
||||
String version = null;
|
||||
Bitness arch = Bitness.x32;
|
||||
|
||||
for (String line : myLines) {
|
||||
if (line.contains("version")) {
|
||||
if (version == null) {
|
||||
version = line;
|
||||
}
|
||||
}
|
||||
else if (line.contains("64-Bit") || line.contains("x86_64") || line.contains("amd64")) {
|
||||
arch = Bitness.x64;
|
||||
}
|
||||
}
|
||||
|
||||
LOG.debug("Returning " + version + " " + arch);
|
||||
return version != null ? new JdkVersionInfo(version, arch) : null;
|
||||
LOG.trace("text: " + text);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 org.jetbrains.jps.model
|
||||
|
||||
import com.intellij.openapi.util.Bitness
|
||||
@@ -9,15 +11,9 @@ import org.junit.Test
|
||||
|
||||
class JdkVersionDetectorTest {
|
||||
@Test fun detectJdkVersion() {
|
||||
val jdkHome = System.getProperty("java.home")
|
||||
val jdkVersion = JdkVersionDetector.getInstance().detectJdkVersion(jdkHome)
|
||||
assertThat(jdkVersion).contains("\"${SystemInfo.JAVA_VERSION.removeSuffix("-ea")}\"")
|
||||
}
|
||||
|
||||
@Test fun detectJdkVersionInfo() {
|
||||
val jdkHome = System.getProperty("java.home")
|
||||
val jdkVersion = JdkVersionDetector.getInstance().detectJdkVersionInfo(jdkHome)
|
||||
assertThat(jdkVersion?.version).contains("\"${SystemInfo.JAVA_VERSION.removeSuffix("-ea")}\"")
|
||||
assertThat(jdkVersion?.version.toString()).startsWith(SystemInfo.JAVA_VERSION)
|
||||
assertThat(jdkVersion?.bitness).isEqualTo(if (SystemInfo.is64Bit) Bitness.x64 else Bitness.x32)
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ package com.intellij.util.lang;
|
||||
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -144,7 +145,7 @@ public final class JavaVersion {
|
||||
*/
|
||||
public static @NotNull JavaVersion parse(@NotNull String versionString) throws IllegalArgumentException {
|
||||
// trimming
|
||||
String str = versionString;
|
||||
String str = versionString.trim();
|
||||
if (str.contains("Runtime Environment")) {
|
||||
int p = str.indexOf("(build ");
|
||||
if (p > 0) str = str.substring(p);
|
||||
@@ -226,4 +227,18 @@ public final class JavaVersion {
|
||||
private static boolean startsWithWord(String s, String word) {
|
||||
return s.startsWith(word) && (s.length() == word.length() || !Character.isLetterOrDigit(s.charAt(word.length())));
|
||||
}
|
||||
|
||||
/**
|
||||
* A safe version of {@link #parse(String)} - returns {@code null} if can't parse a version string.
|
||||
*/
|
||||
public static @Nullable JavaVersion tryParse(String versionString) {
|
||||
if (versionString != null) {
|
||||
try {
|
||||
return parse(versionString);
|
||||
}
|
||||
catch (IllegalArgumentException ignored) { }
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user