More tweaks to 'missing jdk warnings' and JDK finding logic

1. allways use java.exe that goest with found tools.jar
2. better support for Java 9 jdk finding
This commit is contained in:
Kris De Volder
2018-01-29 11:48:44 -08:00
parent 47500517fc
commit c6d49c1dee
5 changed files with 226 additions and 150 deletions

View File

@@ -0,0 +1,58 @@
/*******************************************************************************
* Copyright (c) 2018 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.tooling.boot.java.ls;
import java.io.File;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
import org.springframework.tooling.ls.eclipse.commons.JRE.MissingJDKException;
import org.springframework.tooling.ls.eclipse.commons.JRE.MissingToolsJarException;
public class MissingJdkWarning {
private static boolean missingToolsJarWarningIssued = false;
public static void show(MissingJDKException e) {
//Don't warn more than once per Eclipse session.
if (!missingToolsJarWarningIssued) {
Display.getDefault().asyncExec(() -> {
missingToolsJarWarningIssued = true;
if (e instanceof MissingToolsJarException) {
show((MissingToolsJarException)e);
} else {
MessageDialog.openWarning(null, "Missing JDK",
"The JRE you are running Eclipse with appears to not be a JDK.\n\n"+
"Spring Boot Live hovers will not work with a plain JRE.\n\n" +
"The JRE you are running Eclipse with is:\n "+e.javaHome+"\n\n"
);
}
});
}
}
private static void show(MissingToolsJarException e) {
StringBuilder lookedIn = new StringBuilder();
for (File file : e.lookedIn) {
lookedIn.append(" ");
lookedIn.append(file);
lookedIn.append("\n");
}
MessageDialog.openWarning(null, "Missing 'tools.jar'",
"Could not find 'tools.jar' in the active JRE.\n\n"+
"Spring Boot Live hovers will not work without it.\n\n" +
"The JRE you are running Eclipse with is:\n "+e.javaHome+"\n\n" +
"Where we looked for 'tools.jar':\n" +
lookedIn
);
}
}

View File

@@ -1,50 +0,0 @@
/*******************************************************************************
* Copyright (c) 2018 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.tooling.boot.java.ls;
import java.io.File;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Display;
import org.springframework.tooling.ls.eclipse.commons.STS4LanguageServerProcessStreamConnector.MissingToolsJarException;
public class MissingToolsJarWarning {
private static boolean missingToolsJarWarningIssued = false;
public static void show(MissingToolsJarException e) {
Display.getDefault().asyncExec(() -> {
//Don't warn more than once per Eclipse session.
if (!missingToolsJarWarningIssued) {
missingToolsJarWarningIssued = true;
StringBuilder lookedIn = new StringBuilder();
for (File file : e.lookedIn) {
lookedIn.append(" ");
lookedIn.append(file);
lookedIn.append("\n");
}
MessageDialog.openWarning(null, "Missing 'tools.jar'",
"Could not find 'tools.jar' in the active JRE.\n\n"+
"Spring Boot Live hovers will not work without it.\n\n" +
"The JRE you are running Eclipse with is:\n "+e.javaHome+"\n\n" +
"Where we looked for 'tools.jar':\n" +
lookedIn
);
}
});
}
}

View File

@@ -21,6 +21,9 @@ import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.osgi.framework.Bundle;
import org.springframework.tooling.ls.eclipse.commons.JRE;
import org.springframework.tooling.ls.eclipse.commons.JRE.MissingJDKException;
import org.springframework.tooling.ls.eclipse.commons.JRE.MissingToolsJarException;
import org.springframework.tooling.ls.eclipse.commons.STS4LanguageServerProcessStreamConnector;
/**
@@ -30,7 +33,8 @@ public class SpringBootJavaLanguageServer extends STS4LanguageServerProcessStrea
public SpringBootJavaLanguageServer() {
List<String> commands = new ArrayList<>();
commands.add(getJDKLocation());
JRE jre = getJRE();
commands.add(jre.getJavaExecutable());
// commands.add("-Xdebug");
// commands.add("-Xrunjdwp:server=y,transport=dt_socket,address=4000,suspend=n");
@@ -40,13 +44,8 @@ public class SpringBootJavaLanguageServer extends STS4LanguageServerProcessStrea
commands.add("-Xmx1024m");
commands.add("-cp");
String classpath = getLanguageServerJARLocation();
try {
File toolsJar = getToolsJAR();
if (toolsJar!=null) {
classpath = toolsJar + File.pathSeparator + classpath;
}
} catch (MissingToolsJarException e) {
MissingToolsJarWarning.show(e);
if (jre.toolsJar!=null) {
classpath = jre.toolsJar + File.pathSeparator + classpath;
}
commands.add(classpath);
commands.add("org.springframework.boot.loader.JarLauncher");
@@ -57,6 +56,15 @@ public class SpringBootJavaLanguageServer extends STS4LanguageServerProcessStrea
setWorkingDirectory(workingDir);
}
private JRE getJRE() {
try {
return JRE.findJRE(true);
} catch (MissingJDKException e) {
MissingJdkWarning.show(e);
return new JRE(e.javaHome, null); //Not everything will work without tools jar. But some of it will. So fallback on JRE without toolsjar.
}
}
protected String getLanguageServerJARLocation() {
String languageServer = "boot-java-language-server-" + Constants.LANGUAGE_SERVER_VERSION;

View File

@@ -0,0 +1,152 @@
/*******************************************************************************
* Copyright (c) 2018 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.tooling.ls.eclipse.commons;
import java.io.File;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import org.eclipse.jdt.internal.launching.StandardVMType;
@SuppressWarnings("restriction")
public class JRE {
public final File javaHome;
public final File toolsJar;
public JRE(File javaHome, File toolsJar) {
this.javaHome = javaHome;
this.toolsJar = toolsJar;
}
public String getJavaExecutable() {
if (javaHome.exists()) {
File javaExecutable = StandardVMType.findJavaExecutable(javaHome);
if (javaExecutable != null && javaExecutable.isFile()) {
return javaExecutable.getAbsolutePath();
}
}
return null;
}
@Override
public String toString() {
return "JRE("+javaHome+")";
}
/**
* Get a JRE, with a paired tools jar if it is needed based on current JRE version
* and whether the caller wants it.
*
* @return The tools.jar, or null if none is needed.
* @throws MissingToolsJarException If tools jar is needed but could not be found.
* @throws MissingJava9JDKException
*/
public static JRE findJRE(boolean needJdk) throws MissingJDKException {
File mainHome = new File(System.getProperty("java.home"));
if (!needJdk) {
return new JRE(mainHome, null);
}
Set<File> jhomes = new LinkedHashSet<>();
jhomes.add(mainHome);
findPairedJdk(mainHome, jhomes::add);
if (javaVersionNeedsToolsJar()) {
//Finding a JDK with a tools jar
List<File> lookedIn = new ArrayList<>();
for (File jhome : jhomes) {
for (String tjPath : TOOLS_JAR_PATHS) {
File toolsJar = new File(jhome, tjPath).toPath().normalize().toFile();
lookedIn.add(toolsJar);
if (toolsJar.isFile()) {
return new JRE(jhome, toolsJar);
}
}
}
throw new MissingToolsJarException(mainHome, lookedIn);
} else { // needJdk && !needsToolsJar
//Find a jdk 'java 9 style'.
for (File jhome : jhomes) {
for (String jmPath : JMOD_PATHS) {
File jmodFile = new File(jhome, jmPath).toPath().normalize().toFile();
if (jmodFile.exists()) {
return new JRE(jhome, null);
}
}
}
throw new MissingJDKException(mainHome);
}
}
/**
* Different places to look for tools jar, relative to Java home (for java version < 9)
*/
private final static String[] TOOLS_JAR_PATHS = {
"../lib/tools.jar",
"lib/tools.jar"
};
/**
* Different places to look for jdk.mamagement.jmod file. We don't need this file
* explicitly. It is just used as a means to try to recognize whether the given
* java home is a JDK.
*/
private static final String JMOD_PATHS[] = {
"jmods/jdk.management.jmod"
};
private static boolean javaVersionNeedsToolsJar() {
int javaVersion = Integer.parseInt(System.getProperty("java.version").split("\\.")[0]);
return javaVersion<9;
}
private static void findPairedJdk(File mainHome, Consumer<File> requestor) {
//Mainly for windows where it is common to have side-by-side install of a jre and jdk, instead of a
//nested jre install inside of a jdk.
//E.g.
//C:\ProgramFiles\Java\jdk1.8.0_161
//C:\ProgramFiles\Java\jre1.8.0_161
String name = mainHome.getName();
String pairedName = name.replace("jre", "jdk");
if (!pairedName.equals(name)) {
File pairedJdk = new File(mainHome.getParentFile(), pairedName);
if (pairedJdk.exists()) {
requestor.accept(pairedJdk);
}
}
}
@SuppressWarnings("serial")
public static class MissingToolsJarException extends MissingJDKException {
public final List<File> lookedIn;
public MissingToolsJarException(File javaHome, List<File> lookedIn) {
super(javaHome);
this.lookedIn = lookedIn;
}
}
@SuppressWarnings("serial")
public static class MissingJDKException extends Exception {
public MissingJDKException(File javaHome) {
super();
this.javaHome = javaHome;
}
public final File javaHome;
}
}

View File

@@ -12,30 +12,12 @@ package org.springframework.tooling.ls.eclipse.commons;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import org.eclipse.jdt.internal.launching.StandardVMType;
import org.eclipse.lsp4e.server.ProcessStreamConnectionProvider;
@SuppressWarnings("restriction")
public class STS4LanguageServerProcessStreamConnector extends ProcessStreamConnectionProvider {
public static class MissingToolsJarException extends Exception {
public final File javaHome;
public final List<File> lookedIn;
public MissingToolsJarException(File javaHome, List<File> lookedIn) {
super();
this.javaHome = javaHome;
this.lookedIn = lookedIn;
}
}
private static LanguageServerProcessReaper processReaper = new LanguageServerProcessReaper();
@Override
@@ -50,80 +32,6 @@ public class STS4LanguageServerProcessStreamConnector extends ProcessStreamConne
processReaper.removeProcess(LanguageServerProcessReaper.getProcess(this));
}
protected String getJDKLocation() {
try {
File javaHome= new File(System.getProperty("java.home")).getCanonicalFile(); //$NON-NLS-1$
if (javaHome.exists()) {
File javaExecutable = StandardVMType.findJavaExecutable(javaHome);
if (javaExecutable != null && javaExecutable.exists()) {
return javaExecutable.getAbsolutePath();
}
}
} catch (IOException e) {
return null;
}
return null;
}
/**
* Different places to look for tools jar, relative to Java home.
*/
private static String[] TOOLS_JAR_PATHS = {
"../lib/tools.jar",
"lib/tools.jar"
};
/**
* Get a tools jar if it is needed based on current JRE version.
*
* @return The tools.jar, or null if none is needed.
* @throws MissingToolsJarException If tools jar is needed but could not be found.
*/
protected File getToolsJAR() throws MissingToolsJarException {
if (!needsToolsJar()) {
return null;
}
List<File> lookedIn = new ArrayList<>();
Set<File> jhomes = new LinkedHashSet<>();
File mainHome = new File(System.getProperty("java.home"));
jhomes.add(mainHome);
findPairedJdk(mainHome, jhomes::add);
for (File jhome : jhomes) {
for (String tjPath : TOOLS_JAR_PATHS) {
File toolsJar = new File(jhome, tjPath).toPath().normalize().toFile();
lookedIn.add(toolsJar);
if (toolsJar.isFile()) {
return toolsJar;
}
}
}
throw new MissingToolsJarException(mainHome, lookedIn);
}
protected boolean needsToolsJar() {
int javaVersion = Integer.parseInt(System.getProperty("java.version").split("\\.")[0]);
return javaVersion<9;
}
protected void findPairedJdk(File mainHome, Consumer<File> requestor) {
//Mainly for windows where it is common to have side-by-side install of a jre and jdk, instead of a
//nested jre install inside of a jdk.
//E.g.
//C:\ProgramFiles\Java\jdk1.8.0_161
//C:\ProgramFiles\Java\jre1.8.0_161
String name = mainHome.getName();
String pairedName = name.replace("jre", "jdk");
if (!pairedName.equals(name)) {
File pairedJdk = new File(mainHome.getParentFile(), pairedName);
if (pairedJdk.exists()) {
requestor.accept(pairedJdk);
}
}
}
protected String getWorkingDirLocation() {
return System.getProperty("user.dir");
}