process status added, incl. disconnect command
This commit is contained in:
@@ -78,8 +78,6 @@ public class LiveProcessCommandElement extends QuickAccessElement {
|
||||
|
||||
@Override
|
||||
public void execute() {
|
||||
System.out.println("EXECUTE THE COMMAND !!!");
|
||||
|
||||
List<@NonNull LanguageServer> usedLanguageServers = LanguageServiceAccessor.getActiveLanguageServers(serverCapabilities -> true);
|
||||
|
||||
if (usedLanguageServers.isEmpty()) {
|
||||
|
||||
@@ -49,8 +49,6 @@ public class LiveProcessCommandsQuickAccessProvider implements IQuickAccessCompu
|
||||
|
||||
@Override
|
||||
public QuickAccessElement[] computeElements(String query, IProgressMonitor monitor) {
|
||||
System.out.println("COMPUTE QUICK ACCESS ELEMENTS !!!");
|
||||
|
||||
this.usedLanguageServers = LanguageServiceAccessor.getActiveLanguageServers(serverCapabilities -> true);
|
||||
|
||||
if (usedLanguageServers.isEmpty()) {
|
||||
@@ -65,12 +63,6 @@ public class LiveProcessCommandsQuickAccessProvider implements IQuickAccessCompu
|
||||
ls.getWorkspaceService().executeCommand(commandParams).thenAcceptAsync(commandResult ->
|
||||
createCommandItems(res, commandResult))).toArray(CompletableFuture[]::new)).join();
|
||||
|
||||
System.out.println("quick access elements computed: " + res.size());
|
||||
|
||||
for (QuickAccessElement quickAccessElement : res) {
|
||||
System.out.println("generated element: " + quickAccessElement.getLabel());
|
||||
}
|
||||
|
||||
return res.toArray(new QuickAccessElement[res.size()]);
|
||||
}
|
||||
|
||||
|
||||
@@ -61,10 +61,10 @@ public class SpringProcessCommandHandler {
|
||||
private CompletableFuture<Object> connect(ExecuteCommandParams params) {
|
||||
String processKey = getProcessKey(params);
|
||||
if (processKey != null) {
|
||||
SpringProcessDescriptor[] processes = localProcessConnector.getProcesses();
|
||||
SpringProcessDescriptor[] processes = localProcessConnector.getProcesses(false, SpringProcessStatus.REGULAR);
|
||||
for (SpringProcessDescriptor process : processes) {
|
||||
if (process.getProcessKey().equals(processKey)) {
|
||||
localProcessConnector.connectLocalProcess(process, false);
|
||||
localProcessConnector.connectProcess(process);
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
}
|
||||
@@ -83,6 +83,11 @@ public class SpringProcessCommandHandler {
|
||||
}
|
||||
|
||||
private CompletableFuture<Object> disconnect(ExecuteCommandParams params) {
|
||||
String processKey = getProcessKey(params);
|
||||
if (processKey != null) {
|
||||
connectorService.disconnectProcess(processKey);
|
||||
}
|
||||
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
@@ -96,20 +101,26 @@ public class SpringProcessCommandHandler {
|
||||
for (SpringProcessConnector process : connectedProcesses) {
|
||||
String processKey = process.getProcessKey();
|
||||
String label = process.getLabel();
|
||||
String action = COMMAND_REFRESH;
|
||||
|
||||
LiveProcessCommand command = new LiveProcessCommand();
|
||||
command.setAction(action);
|
||||
command.setLabel(label);
|
||||
command.setProcessKey(processKey);
|
||||
|
||||
result.add(command);
|
||||
LiveProcessCommand refreshCommand = new LiveProcessCommand();
|
||||
refreshCommand.setAction(COMMAND_REFRESH);
|
||||
refreshCommand.setLabel(label);
|
||||
refreshCommand.setProcessKey(processKey);
|
||||
result.add(refreshCommand);
|
||||
|
||||
if (localProcessConnector.isLocalProcess(process.getProcessKey())) {
|
||||
LiveProcessCommand disconnectCommand = new LiveProcessCommand();
|
||||
disconnectCommand.setAction(COMMAND_DISCONNECT);
|
||||
disconnectCommand.setLabel(label);
|
||||
disconnectCommand.setProcessKey(processKey);
|
||||
result.add(disconnectCommand);
|
||||
}
|
||||
|
||||
alreadyConnected.add(processKey);
|
||||
}
|
||||
|
||||
// other available local processes
|
||||
SpringProcessDescriptor[] localProcesses = localProcessConnector.getProcesses();
|
||||
SpringProcessDescriptor[] localProcesses = localProcessConnector.getProcesses(true, SpringProcessStatus.REGULAR);
|
||||
for (SpringProcessDescriptor localProcess : localProcesses) {
|
||||
String processKey = localProcess.getProcessKey();
|
||||
if (!alreadyConnected.contains(processKey)) {
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2019 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
|
||||
* https://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.livehover.v2;
|
||||
|
||||
/**
|
||||
* @author Martin Lippert
|
||||
*/
|
||||
public interface SpringProcessConnectionChangeListener {
|
||||
|
||||
void connectionClosed(String processKey);
|
||||
|
||||
}
|
||||
@@ -21,5 +21,8 @@ public interface SpringProcessConnector {
|
||||
void connect() throws Exception;
|
||||
void refresh() throws Exception;
|
||||
void disconnect() throws Exception;
|
||||
|
||||
void addConnectorChangeListener(SpringProcessConnectionChangeListener listener);
|
||||
void removeConnectorChangeListener(SpringProcessConnectionChangeListener listener);
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -71,6 +73,7 @@ public class SpringProcessConnectorLocal {
|
||||
ProjectObserver projectObserver) {
|
||||
this.projects = Collections.synchronizedCollection(new HashSet<>());
|
||||
this.processes = Collections.synchronizedSet(new HashSet<>());
|
||||
|
||||
this.liveDataProvider = liveDataProvider;
|
||||
this.processConnectorService = processConnector;
|
||||
|
||||
@@ -103,22 +106,26 @@ public class SpringProcessConnectorLocal {
|
||||
}
|
||||
}
|
||||
|
||||
public SpringProcessDescriptor[] getProcesses() {
|
||||
if (processes.size() == 0) {
|
||||
updateProcesses();
|
||||
}
|
||||
|
||||
return (SpringProcessDescriptor[]) processes.toArray(new SpringProcessDescriptor[processes.size()]);
|
||||
}
|
||||
|
||||
public void searchForNewProcesses() {
|
||||
SpringProcessDescriptor[] newProcesses = updateProcesses();
|
||||
|
||||
for (SpringProcessDescriptor descriptor : newProcesses) {
|
||||
connectLocalProcess(descriptor, true);
|
||||
}
|
||||
public boolean isLocalProcess(String processKey) {
|
||||
return this.processes.stream().anyMatch(process -> processKey.equals(process.getProcessKey()));
|
||||
}
|
||||
|
||||
public SpringProcessDescriptor[] getProcesses(boolean update, SpringProcessStatus status) {
|
||||
if (update) {
|
||||
SpringProcessDescriptor[] newProcesses = updateProcesses();
|
||||
if (newProcesses.length > 0) {
|
||||
updateStatus(newProcesses);
|
||||
}
|
||||
}
|
||||
|
||||
if (status != null) {
|
||||
return processes.stream().filter((process) -> status.equals(process.getStatus())).toArray(SpringProcessDescriptor[]::new);
|
||||
}
|
||||
else {
|
||||
return (SpringProcessDescriptor[]) processes.toArray(new SpringProcessDescriptor[processes.size()]);
|
||||
}
|
||||
}
|
||||
|
||||
public SpringProcessDescriptor[] updateProcesses() {
|
||||
List<VirtualMachineDescriptor> currentVms = VirtualMachine.list();
|
||||
Set<String> currentVMKeys = new HashSet<>();
|
||||
@@ -159,7 +166,66 @@ public class SpringProcessConnectorLocal {
|
||||
return (SpringProcessDescriptor[]) newProcesses.toArray(new SpringProcessDescriptor[newProcesses.size()]);
|
||||
}
|
||||
|
||||
public void connectLocalProcess(SpringProcessDescriptor descriptor, boolean checkAutoConnect) {
|
||||
private void updateStatus(SpringProcessDescriptor[] newProcesses) {
|
||||
List<CompletableFuture<Void>> futures = new ArrayList<>();
|
||||
|
||||
for (SpringProcessDescriptor newProcess : newProcesses) {
|
||||
CompletableFuture<SpringProcessStatus> checkStatusFuture = checkStatus(newProcess);
|
||||
CompletableFuture<Void> result = checkStatusFuture.thenAccept((status) -> newProcess.setStatus(status));
|
||||
|
||||
futures.add(result);
|
||||
}
|
||||
|
||||
CompletableFuture<Void> allStatusUpdates = CompletableFuture.allOf((CompletableFuture[]) futures.toArray(new CompletableFuture[futures.size()]));
|
||||
try {
|
||||
allStatusUpdates.get(3, TimeUnit.SECONDS);
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.info("timeout or problem occured while updating the status of the new processes");
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<SpringProcessStatus> checkStatus(SpringProcessDescriptor descriptor) {
|
||||
if (SpringProcessStatus.UNKNOWN.equals(descriptor.getStatus())) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
|
||||
VirtualMachine vm = null;
|
||||
try {
|
||||
vm = VirtualMachine.attach(descriptor.getVm());
|
||||
|
||||
boolean ignore = shouldIgnore(descriptor.getVm(), vm);
|
||||
boolean autoConnect = shouldAutoConnect(descriptor.getVm(), vm);
|
||||
|
||||
if (ignore) {
|
||||
return SpringProcessStatus.IGNORE;
|
||||
}
|
||||
else if (autoConnect) {
|
||||
return SpringProcessStatus.AUTO_CONNECT;
|
||||
}
|
||||
else {
|
||||
return SpringProcessStatus.REGULAR;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
return SpringProcessStatus.IGNORE;
|
||||
}
|
||||
finally {
|
||||
if (vm != null) {
|
||||
try {
|
||||
vm.detach();
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("error detaching from vm: " + descriptor.getVm().id(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return CompletableFuture.completedFuture(SpringProcessStatus.UNKNOWN);
|
||||
}
|
||||
|
||||
public void connectProcess(SpringProcessDescriptor descriptor) {
|
||||
VirtualMachine vm = null;
|
||||
VirtualMachineDescriptor vmDescriptor = descriptor.getVm();
|
||||
|
||||
@@ -167,10 +233,6 @@ public class SpringProcessConnectorLocal {
|
||||
String jmxAddress = null;
|
||||
vm = VirtualMachine.attach(vmDescriptor);
|
||||
|
||||
if (checkAutoConnect && !shouldAutoConnectToProcess(vmDescriptor, vm)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
jmxAddress = vm.getAgentProperties().getProperty(LOCAL_CONNECTOR_ADDRESS);
|
||||
} catch (Exception e) {
|
||||
@@ -211,37 +273,45 @@ public class SpringProcessConnectorLocal {
|
||||
}
|
||||
}
|
||||
|
||||
private boolean shouldAutoConnectToProcess(VirtualMachineDescriptor vmDescriptor, VirtualMachine vm) {
|
||||
return false;
|
||||
private boolean shouldIgnore(VirtualMachineDescriptor vmDescriptor, VirtualMachine vm) {
|
||||
try {
|
||||
String displayName = vmDescriptor.displayName();
|
||||
if (displayName != null && displayName.startsWith(ECLIPSE_PROCESS_DISPLAY_NAME_PREFIX)) {
|
||||
log.info("Eclipse process found, do not connect: " + vmDescriptor.id());
|
||||
return true;
|
||||
}
|
||||
|
||||
Properties systemProperties = vm.getSystemProperties();
|
||||
|
||||
Object languageServerIndicatorProperty = systemProperties.get(LANGUAGE_SERVER_PROPERTY);
|
||||
if (languageServerIndicatorProperty != null) {
|
||||
log.info("language server process found, do not connect: " + vmDescriptor.id());
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// try {
|
||||
// String displayName = vmDescriptor.displayName();
|
||||
// if (displayName != null && displayName.startsWith(ECLIPSE_PROCESS_DISPLAY_NAME_PREFIX)) {
|
||||
// log.info("Eclipse process found, do not connect: " + vmDescriptor.id());
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// Properties systemProperties = vm.getSystemProperties();
|
||||
//
|
||||
// Object projectNameProperty = systemProperties.get(SPRING_APP_PROJECT_NAME_PROPERTY);
|
||||
// if (projectNameProperty instanceof String) {
|
||||
// log.info("Spring boot process found: " + projectNameProperty);
|
||||
// return this.projects.contains((String) projectNameProperty);
|
||||
// }
|
||||
//
|
||||
// Object languageServerIndicatorProperty = systemProperties.get(LANGUAGE_SERVER_PROPERTY);
|
||||
// if (languageServerIndicatorProperty != null) {
|
||||
// log.info("language server process found, do not connect: " + vmDescriptor.id());
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// }
|
||||
// catch (Exception e) {
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// // default case:
|
||||
// return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean shouldAutoConnect(VirtualMachineDescriptor vmDescriptor, VirtualMachine vm) {
|
||||
try {
|
||||
Properties systemProperties = vm.getSystemProperties();
|
||||
|
||||
Object projectNameProperty = systemProperties.get(SPRING_APP_PROJECT_NAME_PROPERTY);
|
||||
if (projectNameProperty instanceof String) {
|
||||
log.info("Spring boot process found: " + projectNameProperty);
|
||||
return this.projects.contains((String) projectNameProperty);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private String getProcessID(VirtualMachineDescriptor descriptor) {
|
||||
@@ -253,5 +323,5 @@ public class SpringProcessConnectorLocal {
|
||||
int firstSpace = rawName.indexOf(' ');
|
||||
return firstSpace < 0 ? rawName : rawName.substring(0, firstSpace);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -10,6 +10,9 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.livehover.v2;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import javax.management.remote.JMXConnector;
|
||||
import javax.management.remote.JMXConnectorFactory;
|
||||
import javax.management.remote.JMXServiceURL;
|
||||
@@ -33,6 +36,8 @@ public class SpringProcessConnectorOverJMX implements SpringProcessConnector {
|
||||
private final String host;
|
||||
private final String port;
|
||||
|
||||
private final List<SpringProcessConnectionChangeListener> listeners;
|
||||
|
||||
public SpringProcessConnectorOverJMX(SpringProcessLiveDataProvider liveDataProvider, String processKey, String jmxURL,
|
||||
String urlScheme, String processID, String processName, String host, String port) {
|
||||
|
||||
@@ -44,6 +49,8 @@ public class SpringProcessConnectorOverJMX implements SpringProcessConnector {
|
||||
this.processName = processName;
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
|
||||
this.listeners = new CopyOnWriteArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -103,4 +110,22 @@ public class SpringProcessConnectorOverJMX implements SpringProcessConnector {
|
||||
this.liveDataProvider.remove(processKey);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addConnectorChangeListener(SpringProcessConnectionChangeListener listener) {
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeConnectorChangeListener(SpringProcessConnectionChangeListener listener) {
|
||||
this.listeners.remove(listener);
|
||||
}
|
||||
|
||||
private void announceConnectionClosed() {
|
||||
for (SpringProcessConnectionChangeListener listener : this.listeners) {
|
||||
listener.connectionClosed(processKey);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -23,11 +23,15 @@ public class SpringProcessDescriptor {
|
||||
private final String processName;
|
||||
private final VirtualMachineDescriptor vm;
|
||||
|
||||
private SpringProcessStatus status;
|
||||
|
||||
public SpringProcessDescriptor(String processKey, String processID, String processName, VirtualMachineDescriptor vm) {
|
||||
this.processKey = processKey;
|
||||
this.processID = processID;
|
||||
this.processName = processName;
|
||||
this.vm = vm;
|
||||
|
||||
this.status = SpringProcessStatus.UNKNOWN;
|
||||
}
|
||||
|
||||
public String getProcessKey() {
|
||||
@@ -47,17 +51,20 @@ public class SpringProcessDescriptor {
|
||||
}
|
||||
|
||||
public String getLabel() {
|
||||
return processID + " (" + processName + ") ";
|
||||
return processID + " (" + processName + ")";
|
||||
}
|
||||
|
||||
public void setStatus(SpringProcessStatus status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public SpringProcessStatus getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((processID == null) ? 0 : processID.hashCode());
|
||||
result = prime * result + ((processKey == null) ? 0 : processKey.hashCode());
|
||||
result = prime * result + ((processName == null) ? 0 : processName.hashCode());
|
||||
return result;
|
||||
return processKey.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -69,22 +76,15 @@ public class SpringProcessDescriptor {
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
SpringProcessDescriptor other = (SpringProcessDescriptor) obj;
|
||||
if (processID == null) {
|
||||
if (other.processID != null)
|
||||
return false;
|
||||
} else if (!processID.equals(other.processID))
|
||||
return false;
|
||||
if (processKey == null) {
|
||||
if (other.processKey != null)
|
||||
return false;
|
||||
} else if (!processKey.equals(other.processKey))
|
||||
return false;
|
||||
if (processName == null) {
|
||||
if (other.processName != null)
|
||||
return false;
|
||||
} else if (!processName.equals(other.processName))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2019 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
|
||||
* https://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.livehover.v2;
|
||||
|
||||
public enum SpringProcessStatus {
|
||||
|
||||
UNKNOWN, IGNORE, REGULAR, AUTO_CONNECT
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017, 2019 Pivotal, Inc.
|
||||
* Copyright (c) 2019 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
|
||||
@@ -74,13 +74,19 @@ public class SpringProcessTracker {
|
||||
}
|
||||
|
||||
private void update() {
|
||||
log.info("scan for local processes cycle...");
|
||||
try {
|
||||
this.localProcessConnector.searchForNewProcesses();
|
||||
}
|
||||
catch (Throwable e) {
|
||||
log.error("error searching for local processes", e);
|
||||
}
|
||||
// log.info("scan for local processes cycle...");
|
||||
// try {
|
||||
// SpringProcessDescriptor[] autoConnectProcesses = this.localProcessConnector.getProcesses(true, SpringProcessStatus.AUTO_CONNECT);
|
||||
//
|
||||
// for (SpringProcessDescriptor process : autoConnectProcesses) {
|
||||
// log.info("auto-connect to process: " + process.getProcessKey());
|
||||
//
|
||||
// this.localProcessConnector.connectProcess(process);
|
||||
// }
|
||||
// }
|
||||
// catch (Throwable e) {
|
||||
// log.error("error searching for local processes", e);
|
||||
// }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user