Add remote host name to ssh tunnel config, so that it can be used to compute correct request mapping links for live hovers.
This commit is contained in:
@@ -24,7 +24,8 @@ Require-Bundle: org.eclipse.jdt.launching;bundle-version="3.9.0",
|
||||
org.eclipse.ui.ide,
|
||||
org.eclipse.jdt.core,
|
||||
org.eclipse.ui.editors;bundle-version="3.11.100",
|
||||
org.springsource.ide.eclipse.commons.livexp
|
||||
org.springsource.ide.eclipse.commons.livexp,
|
||||
org.apache.commons.lang3
|
||||
Import-Package: com.google.gson;version="2.7.0",
|
||||
org.eclipse.jface.preference,
|
||||
org.osgi.framework
|
||||
|
||||
@@ -14,6 +14,7 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.eclipse.jface.bindings.Binding;
|
||||
import org.eclipse.ui.PlatformUI;
|
||||
import org.eclipse.ui.keys.IBindingService;
|
||||
@@ -96,9 +97,9 @@ public class BootLanguageServerPlugin extends AbstractUIPlugin {
|
||||
}
|
||||
}
|
||||
|
||||
private static LiveSetVariable<String> remoteBootApps = new LiveSetVariable<>();
|
||||
private static LiveSetVariable<Pair<String,String>> remoteBootApps = new LiveSetVariable<>();
|
||||
|
||||
public static LiveSetVariable<String> getRemoteBootApps() {
|
||||
public static LiveSetVariable<Pair<String,String>> getRemoteBootApps() {
|
||||
return remoteBootApps;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,9 @@ import java.nio.file.FileSystems;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.tuple.Pair;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.jface.util.IPropertyChangeListener;
|
||||
import org.eclipse.jface.util.PropertyChangeEvent;
|
||||
@@ -30,6 +32,7 @@ import org.eclipse.lsp4j.jsonrpc.messages.ResponseMessage;
|
||||
import org.eclipse.lsp4j.services.LanguageServer;
|
||||
import org.springsource.ide.eclipse.commons.livexp.core.ValueListener;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
@@ -50,7 +53,7 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
|
||||
private LanguageServer languageServer;
|
||||
|
||||
private final IPropertyChangeListener configListener = (e) -> sendConfiguration();
|
||||
private final ValueListener<ImmutableSet<String>> remoteAppsListener = (e, v) -> sendConfiguration();
|
||||
private final ValueListener<ImmutableSet<Pair<String,String>>> remoteAppsListener = (e, v) -> sendConfiguration();
|
||||
|
||||
public DelegatingStreamConnectionProvider() {
|
||||
String port = System.getProperty("boot-java-ls-port");
|
||||
@@ -123,6 +126,28 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
|
||||
}
|
||||
}
|
||||
|
||||
public class RemoteBootAppData {
|
||||
private String jmxurl;
|
||||
private String host;
|
||||
public RemoteBootAppData(String jmxurl, String host) {
|
||||
super();
|
||||
this.jmxurl = jmxurl;
|
||||
this.host = host;
|
||||
}
|
||||
public String getJmxurl() {
|
||||
return jmxurl;
|
||||
}
|
||||
public void setJmxurl(String jmxurl) {
|
||||
this.jmxurl = jmxurl;
|
||||
}
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
}
|
||||
|
||||
private void sendConfiguration() {
|
||||
Map<String, Object> settings = new HashMap<>();
|
||||
Map<String, Object> bootJavaObj = new HashMap<>();
|
||||
@@ -134,7 +159,12 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi
|
||||
|
||||
bootJavaObj.put("boot-hints", bootHint);
|
||||
bootJavaObj.put("change-detection", bootChangeDetection);
|
||||
bootJavaObj.put("remote-apps", BootLanguageServerPlugin.getRemoteBootApps().getValues());
|
||||
ImmutableSet<Pair<String, String>> remoteApps = BootLanguageServerPlugin.getRemoteBootApps().getValues();
|
||||
bootJavaObj.put("remote-apps", BootLanguageServerPlugin.getRemoteBootApps().getValues()
|
||||
.stream()
|
||||
.map(pair -> new RemoteBootAppData(pair.getLeft(), pair.getRight()))
|
||||
.collect(Collectors.toList())
|
||||
);
|
||||
|
||||
settings.put("boot-java", bootJavaObj);
|
||||
|
||||
|
||||
@@ -21,9 +21,16 @@ import org.springframework.ide.vscode.commons.util.MemoizingProxy;
|
||||
public class RemoteSpringBootApp extends AbstractSpringBootApp {
|
||||
|
||||
private String jmxUrl;
|
||||
private String host = null;
|
||||
private String port = "80";
|
||||
|
||||
protected RemoteSpringBootApp(String jmxUrl) {
|
||||
protected RemoteSpringBootApp(String jmxUrl, String host) {
|
||||
this.jmxUrl = jmxUrl;
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -31,6 +38,19 @@ public class RemoteSpringBootApp extends AbstractSpringBootApp {
|
||||
return jmxUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPort() throws Exception {
|
||||
return port!=null ? port : super.getPort();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getHost() throws Exception {
|
||||
if (host!=null) {
|
||||
return host;
|
||||
}
|
||||
return super.getHost();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Properties getSystemProperties() throws Exception {
|
||||
return withPlatformMxBean(RuntimeMXBean.class, runtime -> {
|
||||
@@ -78,8 +98,8 @@ public class RemoteSpringBootApp extends AbstractSpringBootApp {
|
||||
return "Unknown";
|
||||
}
|
||||
|
||||
public static SpringBootApp create(String jmxUrl) {
|
||||
return MemoizingProxy.create(RemoteSpringBootApp.class, Duration.ofMillis(4900), jmxUrl);
|
||||
public static SpringBootApp create(String jmxUrl, String host) {
|
||||
return MemoizingProxy.create(RemoteSpringBootApp.class, Duration.ofMillis(4900), jmxUrl, host);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
@@ -30,10 +31,27 @@ public class Settings {
|
||||
|
||||
private JsonElement settings;
|
||||
|
||||
private Gson gson;
|
||||
|
||||
public Settings(JsonElement settings) {
|
||||
this.settings = settings;
|
||||
}
|
||||
|
||||
public <T> T getAs(Class<T> type, String... names) {
|
||||
JsonElement json = getRawProperty(names);
|
||||
if (json!=null) {
|
||||
return gson().fromJson(json, type);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private Gson gson() {
|
||||
if (gson==null) {
|
||||
gson = new Gson();
|
||||
}
|
||||
return gson;
|
||||
}
|
||||
|
||||
public Set<String> getStringSet(String... names) {
|
||||
ImmutableSet.Builder<String> strings = ImmutableSet.builder();
|
||||
try {
|
||||
|
||||
@@ -10,8 +10,10 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.handlers;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@@ -19,6 +21,7 @@ import java.util.Set;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.RemoteRunningAppsProvider.RemoteBootAppData;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.RemoteSpringBootApp;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.Settings;
|
||||
@@ -27,13 +30,66 @@ import org.springframework.ide.vscode.commons.util.CollectorUtil;
|
||||
|
||||
public class RemoteRunningAppsProvider implements RunningAppProvider {
|
||||
|
||||
public static class RemoteBootAppData {
|
||||
private String jmxurl;
|
||||
private String host;
|
||||
|
||||
public String getJmxurl() {
|
||||
return jmxurl;
|
||||
}
|
||||
public void setJmxurl(String jmxurl) {
|
||||
this.jmxurl = jmxurl;
|
||||
}
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((host == null) ? 0 : host.hashCode());
|
||||
result = prime * result + ((jmxurl == null) ? 0 : jmxurl.hashCode());
|
||||
return result;
|
||||
}
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
RemoteBootAppData other = (RemoteBootAppData) obj;
|
||||
if (host == null) {
|
||||
if (other.host != null)
|
||||
return false;
|
||||
} else if (!host.equals(other.host))
|
||||
return false;
|
||||
if (jmxurl == null) {
|
||||
if (other.jmxurl != null)
|
||||
return false;
|
||||
} else if (!jmxurl.equals(other.jmxurl))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
@Override
|
||||
public String toString() {
|
||||
return "RemoteBootAppData [jmxurl=" + jmxurl + ", host=" + host + "]";
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
private static Logger logger = LoggerFactory.getLogger(RemoteRunningAppsProvider.class);
|
||||
|
||||
/**
|
||||
* We keep the remote app instances in a Map indexed by url. This allows us to
|
||||
* return the same instance(s) repeatedly as long as the urls do not change.
|
||||
* We keep the remote app instances in a Map indexed by the json daya. This allows us to
|
||||
* return the same instance(s) repeatedly as long as the data does not change.
|
||||
*/
|
||||
private Map<String,SpringBootApp> remoteAppByUrl = new HashMap<>();
|
||||
private Map<RemoteBootAppData,SpringBootApp> remoteAppInstances = new HashMap<>();
|
||||
|
||||
public RemoteRunningAppsProvider(SimpleLanguageServer server) {
|
||||
server.getWorkspaceService().onDidChangeConfiguraton(this::handleSettings);
|
||||
@@ -41,31 +97,36 @@ public class RemoteRunningAppsProvider implements RunningAppProvider {
|
||||
|
||||
@Override
|
||||
public synchronized Collection<SpringBootApp> getAllRunningSpringApps() throws Exception {
|
||||
return remoteAppByUrl.values().stream().filter(SpringBootApp::isSpringBootApp).collect(CollectorUtil.toImmutableList());
|
||||
return remoteAppInstances.values().stream().filter(SpringBootApp::isSpringBootApp).collect(CollectorUtil.toImmutableList());
|
||||
}
|
||||
|
||||
synchronized void handleSettings(Settings settings) {
|
||||
Set<String> urls = settings.getStringSet("boot-java", "remote-apps");
|
||||
|
||||
{ //Remove obsolete apps...
|
||||
Iterator<Entry<String, SpringBootApp>> entries = remoteAppByUrl.entrySet().iterator();
|
||||
while (entries.hasNext()) {
|
||||
Entry<String, SpringBootApp> entry = entries.next();
|
||||
String key = entry.getKey();
|
||||
if (!urls.contains(key)) {
|
||||
logger.debug("Removing RemoteSpringBootApp: "+key);
|
||||
entries.remove();
|
||||
entry.getValue().dispose();
|
||||
RemoteBootAppData[] appData = settings.getAs(RemoteBootAppData[].class, "boot-java", "remote-apps");
|
||||
if (appData==null || appData.length==0) {
|
||||
logger.info("Clearing all RemoteSpringBootApps");
|
||||
remoteAppInstances.clear();
|
||||
} else {
|
||||
Set<RemoteBootAppData> newAppData = new HashSet<>(Arrays.asList(appData));
|
||||
{ //Remove obsolete apps...
|
||||
Iterator<Entry<RemoteBootAppData, SpringBootApp>> entries = remoteAppInstances.entrySet().iterator();
|
||||
while (entries.hasNext()) {
|
||||
Entry<RemoteBootAppData, SpringBootApp> entry = entries.next();
|
||||
RemoteBootAppData key = entry.getKey();
|
||||
if (!newAppData.contains(key)) {
|
||||
logger.info("Removing RemoteSpringBootApp: "+key);
|
||||
entries.remove();
|
||||
entry.getValue().dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
{ //Add new apps
|
||||
for (String url : urls) {
|
||||
remoteAppByUrl.computeIfAbsent(url, (_url) -> {
|
||||
logger.debug("Creating RemoteStringBootApp: "+_url);
|
||||
return RemoteSpringBootApp.create(_url);
|
||||
});
|
||||
{ //Add new apps
|
||||
for (RemoteBootAppData key : newAppData) {
|
||||
remoteAppInstances.computeIfAbsent(key, (_key) -> {
|
||||
logger.info("Creating RemoteStringBootApp: "+_key);
|
||||
return RemoteSpringBootApp.create(key.getJmxurl(), key.getHost());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,11 @@ public class UrlUtil {
|
||||
if (!path.startsWith("/")) {
|
||||
path = "/" +path;
|
||||
}
|
||||
return "http://"+host+":"+port+path;
|
||||
if (port.equals("80")) {
|
||||
return "http://"+host+path;
|
||||
} else {
|
||||
return "http://"+host+":"+port+path;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -76,7 +76,15 @@
|
||||
"boot-java.remote-apps": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string"
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"jmxurl": {
|
||||
"type": "string"
|
||||
},
|
||||
"host": {
|
||||
"type": "string"
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Array of jmx urls pointing to remote spring boot applications to poll for live hover information. A typical url looks something like this: `service:jmx:rmi://localhost:9111/jndi/rmi://localhost:9111/jmxrmi`"
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user