diff --git a/eclipse-language-servers/org.springframework.tooling.boot.java.ls/src/org/springframework/tooling/boot/java/ls/MissingJdkWarning.java b/eclipse-language-servers/org.springframework.tooling.boot.java.ls/src/org/springframework/tooling/boot/java/ls/MissingJdkWarning.java new file mode 100644 index 000000000..945d97921 --- /dev/null +++ b/eclipse-language-servers/org.springframework.tooling.boot.java.ls/src/org/springframework/tooling/boot/java/ls/MissingJdkWarning.java @@ -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 + ); + } +} diff --git a/eclipse-language-servers/org.springframework.tooling.boot.java.ls/src/org/springframework/tooling/boot/java/ls/MissingToolsJarWarning.java b/eclipse-language-servers/org.springframework.tooling.boot.java.ls/src/org/springframework/tooling/boot/java/ls/MissingToolsJarWarning.java deleted file mode 100644 index 1933a1670..000000000 --- a/eclipse-language-servers/org.springframework.tooling.boot.java.ls/src/org/springframework/tooling/boot/java/ls/MissingToolsJarWarning.java +++ /dev/null @@ -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 - ); - } - }); - } - - - -} diff --git a/eclipse-language-servers/org.springframework.tooling.boot.java.ls/src/org/springframework/tooling/boot/java/ls/SpringBootJavaLanguageServer.java b/eclipse-language-servers/org.springframework.tooling.boot.java.ls/src/org/springframework/tooling/boot/java/ls/SpringBootJavaLanguageServer.java index 5ab363fd7..f7de5a1da 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.java.ls/src/org/springframework/tooling/boot/java/ls/SpringBootJavaLanguageServer.java +++ b/eclipse-language-servers/org.springframework.tooling.boot.java.ls/src/org/springframework/tooling/boot/java/ls/SpringBootJavaLanguageServer.java @@ -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 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; diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/JRE.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/JRE.java new file mode 100644 index 000000000..eeedd46c7 --- /dev/null +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/JRE.java @@ -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 jhomes = new LinkedHashSet<>(); + jhomes.add(mainHome); + findPairedJdk(mainHome, jhomes::add); + if (javaVersionNeedsToolsJar()) { + //Finding a JDK with a tools jar + List 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 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 lookedIn; + + public MissingToolsJarException(File javaHome, List 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; + } + + +} diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageServerProcessStreamConnector.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageServerProcessStreamConnector.java index d4344a229..6e0c25a08 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageServerProcessStreamConnector.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons/src/org/springframework/tooling/ls/eclipse/commons/STS4LanguageServerProcessStreamConnector.java @@ -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 lookedIn; - - public MissingToolsJarException(File javaHome, List 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 lookedIn = new ArrayList<>(); - Set 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 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"); }