Automatically show language server logs in Eclipse console
This commit is contained in:
@@ -32,6 +32,7 @@ import org.springframework.tooling.ls.eclipse.commons.STS4LanguageServerProcessS
|
||||
public class SpringBootJavaLanguageServer extends STS4LanguageServerProcessStreamConnector {
|
||||
|
||||
public SpringBootJavaLanguageServer() {
|
||||
super("Boot Java Language Server");
|
||||
List<String> commands = new ArrayList<>();
|
||||
JRE jre = getJRE();
|
||||
commands.add(jre.getJavaExecutable());
|
||||
@@ -74,12 +75,13 @@ public class SpringBootJavaLanguageServer extends STS4LanguageServerProcessStrea
|
||||
String languageServerLocalCopy = bundleVersion + "-" + languageServer;
|
||||
|
||||
File dataFile = bundle.getDataFile(languageServerLocalCopy);
|
||||
Exception error = null;
|
||||
if (!dataFile.exists() || bundleVersion.endsWith("qualifier")) { // qualifier check to get the language server always copied in dev mode
|
||||
try {
|
||||
copyLanguageServerJAR(languageServer, languageServerLocalCopy);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
error = e;
|
||||
}
|
||||
}
|
||||
if (!dataFile.exists()) {
|
||||
@@ -91,6 +93,9 @@ public class SpringBootJavaLanguageServer extends STS4LanguageServerProcessStrea
|
||||
if (locallyBuiltJar.exists()) {
|
||||
return locallyBuiltJar.getAbsolutePath();
|
||||
}
|
||||
if (error!=null) {
|
||||
error.printStackTrace();
|
||||
}
|
||||
}
|
||||
return dataFile.getAbsolutePath();
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.springframework.tooling.ls.eclipse.commons.STS4LanguageServerProcessS
|
||||
public class BoshLanguageServer extends STS4LanguageServerProcessStreamConnector {
|
||||
|
||||
public BoshLanguageServer() {
|
||||
super("Bosh Language Server");
|
||||
List<String> commands = new ArrayList<>();
|
||||
commands.add(JRE.currentJRE().getJavaExecutable());
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ public class CloudFoundryManifestLanguageServer extends STS4LanguageServerProces
|
||||
private static List<CloudFoundryManifestLanguageServer> servers = new CopyOnWriteArrayList<>();
|
||||
|
||||
public CloudFoundryManifestLanguageServer() {
|
||||
super("Cloudfoundry Language Server");
|
||||
List<String> commands = new ArrayList<>();
|
||||
|
||||
commands.add(JRE.currentJRE().getJavaExecutable());
|
||||
|
||||
@@ -30,6 +30,7 @@ import org.springframework.tooling.ls.eclipse.commons.STS4LanguageServerProcessS
|
||||
public class ConcourseLanguageServer extends STS4LanguageServerProcessStreamConnector {
|
||||
|
||||
public ConcourseLanguageServer() {
|
||||
super("Concourse Language Server");
|
||||
List<String> commands = new ArrayList<>();
|
||||
commands.add(JRE.currentJRE().getJavaExecutable());
|
||||
|
||||
|
||||
@@ -12,7 +12,9 @@ Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.8.0",
|
||||
org.eclipse.lsp4j;bundle-version="0.4.0",
|
||||
org.eclipse.ui.workbench.texteditor,
|
||||
org.eclipse.jface.text,
|
||||
com.google.guava
|
||||
com.google.guava,
|
||||
org.eclipse.debug.ui,
|
||||
org.eclipse.ui.console
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Bundle-ActivationPolicy: lazy
|
||||
Export-Package: org.springframework.tooling.ls.eclipse.commons
|
||||
|
||||
@@ -12,18 +12,99 @@ package org.springframework.tooling.ls.eclipse.commons;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.lsp4e.server.ProcessStreamConnectionProvider;
|
||||
import org.springframework.tooling.ls.eclipse.commons.console.ConsoleUtil.Console;
|
||||
import org.springframework.tooling.ls.eclipse.commons.console.LanguageServerConsoles;
|
||||
|
||||
import com.google.common.base.Charsets;
|
||||
import com.google.common.base.Supplier;
|
||||
|
||||
public class STS4LanguageServerProcessStreamConnector extends ProcessStreamConnectionProvider {
|
||||
|
||||
private static LanguageServerProcessReaper processReaper = new LanguageServerProcessReaper();
|
||||
|
||||
private Supplier<Console> consoles = null;
|
||||
|
||||
public STS4LanguageServerProcessStreamConnector(String consoleLabel) {
|
||||
if (consoleLabel!=null) {
|
||||
this.consoles = LanguageServerConsoles.getConsoleFactory(consoleLabel);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void start() throws IOException {
|
||||
super.start();
|
||||
processReaper.addProcess(LanguageServerProcessReaper.getProcess(this));
|
||||
Process process = LanguageServerProcessReaper.getProcess(this);
|
||||
processReaper.addProcess(process);
|
||||
if (consoles!=null) {
|
||||
forwardTo(getLanguageServerLog(), consoles.get().out);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ProcessBuilder createProcessBuilder() {
|
||||
if (consoles==null) {
|
||||
return super.createProcessBuilder();
|
||||
}
|
||||
ProcessBuilder builder = new ProcessBuilder(getCommands());
|
||||
builder.directory(new File(getWorkingDirectory()));
|
||||
//builder.redirectError(ProcessBuilder.Redirect.INHERIT);
|
||||
return builder;
|
||||
}
|
||||
|
||||
private void forwardTo(InputStream is, OutputStream os) {
|
||||
Job consoleJob = new Job("Forward Language Server log output to console") {
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor arg0) {
|
||||
try {
|
||||
pipe(is, os);
|
||||
os.write("==== Process Terminated====\n".getBytes(Charsets.UTF_8));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
finally {
|
||||
try {
|
||||
os.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
|
||||
void pipe(InputStream input, OutputStream output) throws IOException {
|
||||
try {
|
||||
byte[] buf = new byte[1024*4];
|
||||
int n = input.read(buf);
|
||||
while (n >= 0) {
|
||||
output.write(buf, 0, n);
|
||||
n = input.read(buf);
|
||||
}
|
||||
output.flush();
|
||||
} finally {
|
||||
input.close();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
consoleJob.setSystem(true);
|
||||
consoleJob.schedule();
|
||||
}
|
||||
|
||||
private InputStream getLanguageServerLog() {
|
||||
return super.getErrorStream();
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getErrorStream() {
|
||||
// lsp4e doesn't do anything with it. So don't pass it on. (Once they do start reading it it might actually break us otherwise)
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2012, 2018 Pivotal Software, 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 Software, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.tooling.ls.eclipse.commons.console;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.LinkedList;
|
||||
|
||||
import org.eclipse.debug.internal.ui.DebugUIPlugin;
|
||||
import org.eclipse.debug.internal.ui.preferences.IDebugPreferenceConstants;
|
||||
import org.eclipse.swt.graphics.Color;
|
||||
import org.eclipse.ui.console.ConsolePlugin;
|
||||
import org.eclipse.ui.console.IConsole;
|
||||
import org.eclipse.ui.console.IOConsole;
|
||||
import org.eclipse.ui.console.IOConsoleInputStream;
|
||||
import org.eclipse.ui.console.IOConsoleOutputStream;
|
||||
|
||||
/**
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
@SuppressWarnings("restriction")
|
||||
public class ConsoleUtil {
|
||||
|
||||
public static class Console {
|
||||
public final InputStream in;
|
||||
public final OutputStream out;
|
||||
public final OutputStream err;
|
||||
|
||||
public Console(IOConsoleInputStream in, IOConsoleOutputStream out,
|
||||
IOConsoleOutputStream err) {
|
||||
this.in = in;
|
||||
this.out = out;
|
||||
this.err = err;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
try {
|
||||
out.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
try {
|
||||
err.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
try {
|
||||
in.close();
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Maximum number of old consoles to keep open. If this number is exceeded the oldest console will
|
||||
* be removed from the UI.
|
||||
*/
|
||||
private final int MAX_SIZE = 3;
|
||||
|
||||
public static Color getOutputColor() {
|
||||
return DebugUIPlugin.getPreferenceColor(IDebugPreferenceConstants.CONSOLE_SYS_OUT_COLOR);
|
||||
}
|
||||
|
||||
public static Color getErrorColor() {
|
||||
return DebugUIPlugin.getPreferenceColor(IDebugPreferenceConstants.CONSOLE_SYS_ERR_COLOR);
|
||||
}
|
||||
|
||||
public static Color getInputColor() {
|
||||
return DebugUIPlugin.getPreferenceColor(IDebugPreferenceConstants.CONSOLE_SYS_IN_COLOR);
|
||||
}
|
||||
|
||||
private LinkedList<IOConsole> history = new LinkedList<IOConsole>();
|
||||
|
||||
private void add(IOConsole console) {
|
||||
IOConsole toClose = null;
|
||||
synchronized (history) {
|
||||
history.addLast(console);
|
||||
if (history.size()>MAX_SIZE) {
|
||||
toClose = history.removeFirst();
|
||||
}
|
||||
}
|
||||
if (toClose!=null) {
|
||||
close(toClose);
|
||||
}
|
||||
console.activate();
|
||||
ConsolePlugin.getDefault().getConsoleManager().addConsoles(new IConsole[]{ console });
|
||||
}
|
||||
|
||||
private static void close(IOConsole console) {
|
||||
ConsolePlugin.getDefault().getConsoleManager().removeConsoles(new IConsole[] {console});
|
||||
}
|
||||
|
||||
public Console getConsole(String title) {
|
||||
|
||||
final IOConsole console = new IOConsole(title, null);
|
||||
final IOConsoleInputStream in = console.getInputStream();
|
||||
final IOConsoleOutputStream out = console.newOutputStream();
|
||||
final IOConsoleOutputStream err = console.newOutputStream();
|
||||
|
||||
in.setColor(getInputColor());
|
||||
out.setColor(getOutputColor());
|
||||
err.setColor(getErrorColor());
|
||||
|
||||
add(console);
|
||||
return new Console(in, out, err);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*******************************************************************************
|
||||
* 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.console;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.tooling.ls.eclipse.commons.console.ConsoleUtil.Console;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
|
||||
public class LanguageServerConsoles {
|
||||
|
||||
private static Map<String, Supplier<Console>> managers;
|
||||
|
||||
public static synchronized Supplier<Console> getConsoleFactory(String languageServerName) {
|
||||
if (managers==null) {
|
||||
managers = new HashMap<>();
|
||||
}
|
||||
return managers.computeIfAbsent(languageServerName, label -> new Supplier<Console>() {
|
||||
ConsoleUtil consoleMgr = new ConsoleUtil(); //one console manager per language server type. This way each has their
|
||||
// own history (which limits number of open consoles per type)
|
||||
int consoleCounter = 0;
|
||||
|
||||
@Override
|
||||
public Console get() {
|
||||
return consoleMgr.getConsole(languageServerName+" "+consoleCounter());
|
||||
}
|
||||
|
||||
private synchronized int consoleCounter() {
|
||||
return ++consoleCounter;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -30,6 +30,7 @@ import org.springframework.tooling.ls.eclipse.commons.STS4LanguageServerProcessS
|
||||
public class SpringBootPropertiesLanguageServer extends STS4LanguageServerProcessStreamConnector {
|
||||
|
||||
public SpringBootPropertiesLanguageServer() {
|
||||
super("Boot Properties Language Server");
|
||||
List<String> commands = new ArrayList<>();
|
||||
commands.add(JRE.currentJRE().getJavaExecutable());
|
||||
|
||||
@@ -53,14 +54,26 @@ public class SpringBootPropertiesLanguageServer extends STS4LanguageServerProces
|
||||
|
||||
Bundle bundle = Platform.getBundle(Constants.PLUGIN_ID);
|
||||
File dataFile = bundle.getDataFile(languageServer);
|
||||
// if (!dataFile.exists()) {
|
||||
try {
|
||||
copyLanguageServerJAR(languageServer);
|
||||
Exception error = null;
|
||||
try {
|
||||
copyLanguageServerJAR(languageServer);
|
||||
}
|
||||
catch (Exception e) {
|
||||
error = e;
|
||||
}
|
||||
if (!dataFile.exists()) {
|
||||
File userHome = new File(System.getProperty("user.home"));
|
||||
File locallyBuiltJar = new File(
|
||||
userHome,
|
||||
"git/sts4/headless-services/boot-properties-language-server/target/boot-properties-language-server-"+Constants.LANGUAGE_SERVER_VERSION + ".jar"
|
||||
);
|
||||
if (locallyBuiltJar.exists()) {
|
||||
return locallyBuiltJar.getAbsolutePath();
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
if (error!=null) {
|
||||
error.printStackTrace();
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
return dataFile.getAbsolutePath();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user