change detection is now able to re-connect to already stopped application
This commit is contained in:
@@ -160,12 +160,7 @@ public class SpringBootApp {
|
||||
|
||||
public String getJavaCommand() throws IOException {
|
||||
Properties props = this.vm.getSystemProperties();
|
||||
if (props.contains("sun.java.command")) {
|
||||
return props.getProperty("sun.java.command");
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
return (String) props.get("sun.java.command");
|
||||
}
|
||||
|
||||
public boolean containsSystemProperty(Object key) throws IOException {
|
||||
|
||||
@@ -13,6 +13,7 @@ package org.springframework.ide.vscode.boot.java.utils;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBean;
|
||||
|
||||
/**
|
||||
@@ -20,12 +21,19 @@ import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBean;
|
||||
*/
|
||||
public class Change {
|
||||
|
||||
private final SpringBootApp runningApp;
|
||||
|
||||
private List<LiveBean> newBeans;
|
||||
private List<LiveBean> deletedBeans;
|
||||
|
||||
public Change() {
|
||||
public Change(SpringBootApp runningApp) {
|
||||
this.runningApp = runningApp;
|
||||
}
|
||||
|
||||
public SpringBootApp getRunningApp() {
|
||||
return runningApp;
|
||||
}
|
||||
|
||||
public List<LiveBean> getNewBeans() {
|
||||
return newBeans;
|
||||
}
|
||||
@@ -49,5 +57,5 @@ public class Change {
|
||||
|
||||
newBeans.add(bean);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -10,8 +10,12 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
|
||||
|
||||
@@ -26,26 +30,97 @@ public class ChangeDetectionHistory {
|
||||
this.changeHistory = new HashMap<>();
|
||||
}
|
||||
|
||||
public Change checkForChanges(SpringBootApp app) {
|
||||
String virtualID = getVirtualAppID(app);
|
||||
public Change[] checkForChanges(SpringBootApp[] runningApps) {
|
||||
List<Change> result = null;
|
||||
|
||||
if (!changeHistory.containsKey(virtualID)) {
|
||||
ChangeHistory appHistory = new ChangeHistory(virtualID);
|
||||
changeHistory.put(virtualID, appHistory);
|
||||
for (SpringBootApp runningApp : runningApps) {
|
||||
String virtualID = getVirtualAppID(runningApp);
|
||||
|
||||
if (changeHistory.containsKey(virtualID)) {
|
||||
// the standard case
|
||||
ChangeHistory appHistory = changeHistory.get(virtualID);
|
||||
appHistory.updateProcess(runningApp);
|
||||
|
||||
Change change = appHistory.checkForUpdates();
|
||||
if (change != null) {
|
||||
if (result == null) {
|
||||
result = new ArrayList<>();
|
||||
}
|
||||
result.add(change);
|
||||
}
|
||||
}
|
||||
else {
|
||||
String oldAppID = getOldApp(runningApp, runningApps);
|
||||
if (oldAppID != null) {
|
||||
ChangeHistory oldHistory = changeHistory.remove(oldAppID);
|
||||
oldHistory.updateProcess(runningApp);
|
||||
changeHistory.put(virtualID, oldHistory);
|
||||
|
||||
Change change = oldHistory.checkForUpdates();
|
||||
if (change != null) {
|
||||
if (result == null) {
|
||||
result = new ArrayList<>();
|
||||
}
|
||||
result.add(change);
|
||||
}
|
||||
}
|
||||
else {
|
||||
ChangeHistory newHistory = new ChangeHistory();
|
||||
newHistory.updateProcess(runningApp);
|
||||
changeHistory.put(virtualID, newHistory);
|
||||
|
||||
newHistory.checkForUpdates();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ChangeHistory appHistory = changeHistory.get(virtualID);
|
||||
appHistory.updateProcess(app);
|
||||
|
||||
Change result = appHistory.checkForUpdates();
|
||||
return result;
|
||||
if (result != null) {
|
||||
return (Change[]) result.toArray(new Change[result.size()]);
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getVirtualAppID(SpringBootApp app) {
|
||||
// TODO: this needs a lot more work to make this a real VIRTUAL ID which detects the same app
|
||||
// running across different app restarts, so the process ID is not the best way to do this (just
|
||||
// a temporary solution)
|
||||
return app.getProcessID();
|
||||
}
|
||||
|
||||
private String getOldApp(SpringBootApp app, SpringBootApp[] allApps) {
|
||||
Set<String> histories = this.changeHistory.keySet();
|
||||
|
||||
try {
|
||||
String commandLine = app.getJavaCommand();
|
||||
String[] classpath = app.getClasspath();
|
||||
|
||||
for (String oldProcessID : histories) {
|
||||
if (this.changeHistory.get(oldProcessID).matchesProcess(commandLine, classpath)
|
||||
&& processNotRunningAnymore(oldProcessID, allApps)) {
|
||||
return oldProcessID;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean processNotRunningAnymore(String oldProcessID, SpringBootApp[] allApps) {
|
||||
try {
|
||||
for (SpringBootApp app : allApps) {
|
||||
String id = getVirtualAppID(app);
|
||||
if (id != null && id.equals(oldProcessID)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -10,7 +10,9 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.utils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
@@ -27,23 +29,38 @@ public class ChangeHistory {
|
||||
|
||||
private static final List<LiveBean> EMPTY_BEANS_LIST = new ArrayList<>(0);
|
||||
|
||||
private final String virtualAppID;
|
||||
|
||||
private SpringBootApp runningProcess;
|
||||
private SpringBootApp associatedProcess;
|
||||
private String associatedProcessCommand;
|
||||
private String[] associatedProcessClasspath;
|
||||
|
||||
private LiveBeansModel lastBeans;
|
||||
|
||||
public ChangeHistory(String virtualAppID) {
|
||||
this.virtualAppID = virtualAppID;
|
||||
public ChangeHistory() {
|
||||
}
|
||||
|
||||
public void updateProcess(SpringBootApp app) {
|
||||
this.runningProcess = app;
|
||||
if (this.associatedProcess != app) {
|
||||
this.associatedProcess = app;
|
||||
|
||||
try {
|
||||
this.associatedProcessCommand = app.getJavaCommand();
|
||||
this.associatedProcessClasspath = app.getClasspath();
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean matchesProcess(String commandLine, String[] classpath) {
|
||||
return this.associatedProcessCommand != null && this.associatedProcessCommand.equals(commandLine)
|
||||
&& this.associatedProcessClasspath != null && Arrays.deepEquals(this.associatedProcessClasspath, classpath);
|
||||
}
|
||||
|
||||
public Change checkForUpdates() {
|
||||
Change result = null;
|
||||
|
||||
LiveBeansModel currentBeans = this.runningProcess.getBeans();
|
||||
LiveBeansModel currentBeans = this.associatedProcess.getBeans();
|
||||
if (!currentBeans.isEmpty()) {
|
||||
|
||||
if (lastBeans == null) {
|
||||
@@ -87,7 +104,7 @@ public class ChangeHistory {
|
||||
if (!contains(currentBeans, bean)) {
|
||||
|
||||
if (result == null) {
|
||||
result = new Change();
|
||||
result = new Change(associatedProcess);
|
||||
}
|
||||
|
||||
result.addDeletedBean(bean);
|
||||
@@ -98,7 +115,7 @@ public class ChangeHistory {
|
||||
if (!contains(previousBeans, bean)) {
|
||||
|
||||
if (result == null) {
|
||||
result = new Change();
|
||||
result = new Change(associatedProcess);
|
||||
}
|
||||
|
||||
result.addNewBean(bean);
|
||||
@@ -111,7 +128,7 @@ public class ChangeHistory {
|
||||
private boolean contains(List<LiveBean> beans, LiveBean bean) {
|
||||
for (LiveBean beansFromList : beans) {
|
||||
if (StringUtils.equals(beansFromList.getId(), bean.getId())
|
||||
&& StringUtils.equals(beansFromList.getType(), bean.getType())
|
||||
&& StringUtils.equals(beansFromList.getType(true), bean.getType(true))
|
||||
&& StringUtils.equals(beansFromList.getResource(), bean.getResource())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -135,6 +135,12 @@ public class SpringLiveChangeDetectionWatchdog {
|
||||
if (changeDetectionEnabled) {
|
||||
try {
|
||||
SpringBootApp[] runningBootApps = runningAppProvider.getAllRunningSpringApps().toArray(new SpringBootApp[0]);
|
||||
Change[] changes = changeHistory.checkForChanges(runningBootApps);
|
||||
if (changes != null && changes.length > 0) {
|
||||
for (Change change : changes) {
|
||||
publishDetectedChange(change);
|
||||
}
|
||||
}
|
||||
for (SpringBootApp app : runningBootApps) {
|
||||
updateApp(app);
|
||||
}
|
||||
@@ -145,16 +151,12 @@ public class SpringLiveChangeDetectionWatchdog {
|
||||
}
|
||||
|
||||
private void updateApp(SpringBootApp app) {
|
||||
Change change = changeHistory.checkForChanges(app);
|
||||
if (change != null) {
|
||||
publishDetectedChange(change, app);
|
||||
}
|
||||
}
|
||||
|
||||
private void publishDetectedChange(Change change, SpringBootApp app) {
|
||||
private void publishDetectedChange(Change change) {
|
||||
Map<String, List<Diagnostic>> diagnostics = new HashMap<>();
|
||||
|
||||
IJavaProject[] projects = findProjectsFor(app);
|
||||
IJavaProject[] projects = findProjectsFor(change.getRunningApp());
|
||||
|
||||
List<LiveBean> deletedBeans = change.getDeletedBeans();
|
||||
if (deletedBeans != null) {
|
||||
|
||||
Reference in New Issue
Block a user