diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/BootJavaPreferencesPage.java b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/BootJavaPreferencesPage.java index 91160d109..bbfc8da92 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/BootJavaPreferencesPage.java +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/BootJavaPreferencesPage.java @@ -15,6 +15,7 @@ import org.eclipse.core.runtime.preferences.InstanceScope; import org.eclipse.jface.preference.BooleanFieldEditor; import org.eclipse.jface.preference.FieldEditorPreferencePage; import org.eclipse.jface.preference.IPreferenceStore; +import org.eclipse.jface.preference.StringFieldEditor; import org.eclipse.jface.util.IPropertyChangeListener; import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.swt.widgets.Composite; @@ -81,7 +82,10 @@ public class BootJavaPreferencesPage extends FieldEditorPreferencePage implement Composite fieldEditorParent = getFieldEditorParent(); addField(new BooleanFieldEditor(Constants.PREF_SCAN_JAVA_TEST_SOURCES, "Scan Java test sources", fieldEditorParent)); - addField(new BooleanFieldEditor(Constants.PREF_BOOT_HINTS, "Live Boot Hint Decorators", fieldEditorParent)); + + addField(new BooleanFieldEditor(Constants.PREF_LIVE_INFORMATION_AUTOMATIC_TRACKING_ENABLED, "Live Information - Automatic Process Tracking Enabled", fieldEditorParent)); + addField(new StringFieldEditor(Constants.PREF_LIVE_INFORMATION_AUTOMATIC_TRACKING_DELAY, "Live Information - Automatic Process Tracking Delay in ms", fieldEditorParent)); + addField(new BooleanFieldEditor(PreferenceConstants.HIGHLIGHT_CODELENS_PREFS, "Highlights CodeLens", fieldEditorParent) { @Override public IPreferenceStore getPreferenceStore() { diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/Constants.java b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/Constants.java index 58b4f443a..15ae81bc4 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/Constants.java +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/Constants.java @@ -17,7 +17,9 @@ public class Constants { public static final String PLUGIN_ID = "org.springframework.tooling.boot.ls"; - public static final String PREF_BOOT_HINTS = "boot-java.boot-hints.on"; + public static final String PREF_LIVE_INFORMATION_AUTOMATIC_TRACKING_ENABLED = "boot-java.live-information.automatic-tracking.on"; + public static final String PREF_LIVE_INFORMATION_AUTOMATIC_TRACKING_DELAY = "boot-java.live-information.automatic-tracking.delay"; + public static final String PREF_SUPPORT_SPRING_XML_CONFIGS = "boot-java.support-spring-xml-config.on"; public static final String PREF_XML_CONFIGS_SCAN_FOLDERS = "boot-java.support-spring-xml-config.scan-folders-globs"; public static final String PREF_SCAN_JAVA_TEST_SOURCES = "boot-java.scan-java-test-sources"; diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/DelegatingStreamConnectionProvider.java b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/DelegatingStreamConnectionProvider.java index 9901411fb..aa6aece9d 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/DelegatingStreamConnectionProvider.java +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/DelegatingStreamConnectionProvider.java @@ -214,13 +214,19 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi private void sendConfiguration() { Map settings = new HashMap<>(); Map bootJavaObj = new HashMap<>(); - Map bootHint = new HashMap<>(); + Map liveInformation = new HashMap<>(); + Map liveInformationAutomaticTracking = new HashMap<>(); Map supportXML = new HashMap<>(); Map bootChangeDetection = new HashMap<>(); Map scanTestJavaSources = new HashMap<>(); IPreferenceStore preferenceStore = BootLanguageServerPlugin.getDefault().getPreferenceStore(); - bootHint.put("on", preferenceStore.getBoolean(Constants.PREF_BOOT_HINTS)); + + liveInformationAutomaticTracking.put("on", preferenceStore.getBoolean(Constants.PREF_LIVE_INFORMATION_AUTOMATIC_TRACKING_ENABLED)); + liveInformationAutomaticTracking.put("delay", preferenceStore.getInt(Constants.PREF_LIVE_INFORMATION_AUTOMATIC_TRACKING_DELAY)); + + liveInformation.put("automatic-tracking", liveInformationAutomaticTracking); + supportXML.put("on", preferenceStore.getBoolean(Constants.PREF_SUPPORT_SPRING_XML_CONFIGS)); supportXML.put("scan-folders-globs", preferenceStore.getString(Constants.PREF_XML_CONFIGS_SCAN_FOLDERS)); supportXML.put("hyperlinks", preferenceStore.getString(Constants.PREF_XML_CONFIGS_HYPERLINKS)); @@ -228,7 +234,7 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi bootChangeDetection.put("on", preferenceStore.getBoolean(Constants.PREF_CHANGE_DETECTION)); scanTestJavaSources.put("on", preferenceStore.getBoolean(Constants.PREF_SCAN_JAVA_TEST_SOURCES)); - bootJavaObj.put("boot-hints", bootHint); + bootJavaObj.put("live-information", liveInformation); bootJavaObj.put("support-spring-xml-config", supportXML); bootJavaObj.put("change-detection", bootChangeDetection); bootJavaObj.put("scan-java-test-sources", scanTestJavaSources); diff --git a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/PrefsInitializer.java b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/PrefsInitializer.java index 2791ce68c..ca8706717 100644 --- a/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/PrefsInitializer.java +++ b/eclipse-language-servers/org.springframework.tooling.boot.ls/src/org/springframework/tooling/boot/ls/PrefsInitializer.java @@ -27,7 +27,8 @@ public class PrefsInitializer extends AbstractPreferenceInitializer { @Override public void initializeDefaultPreferences() { IPreferenceStore preferenceStore = BootLanguageServerPlugin.getDefault().getPreferenceStore(); - preferenceStore.setDefault(Constants.PREF_BOOT_HINTS, true); + preferenceStore.setDefault(Constants.PREF_LIVE_INFORMATION_AUTOMATIC_TRACKING_ENABLED, true); + preferenceStore.setDefault(Constants.PREF_LIVE_INFORMATION_AUTOMATIC_TRACKING_DELAY, 5000); preferenceStore.setDefault(Constants.PREF_SUPPORT_SPRING_XML_CONFIGS, false); preferenceStore.setDefault(Constants.PREF_XML_CONFIGS_HYPERLINKS, true); preferenceStore.setDefault(Constants.PREF_XML_CONFIGS_CONTENT_ASSIST, true); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootJavaConfig.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootJavaConfig.java index 7aa2c16d2..43dfa389d 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootJavaConfig.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/app/BootJavaConfig.java @@ -34,6 +34,9 @@ public class BootJavaConfig implements InitializingBean { private static final Logger log = LoggerFactory.getLogger(BootJavaConfig.class); + public static final boolean LIVE_INFORMATION_AUTOMATIC_TRACKING_ENABLED_DEFAULT = true; + public static final int LIVE_INFORMATION_AUTOMATIC_TRACKING_DELAY_DEFAULT = 5000; + //TODO: Consider changing this to something that raises Spring application events. // I.e. like described in here: https://www.baeldung.com/spring-events @@ -45,10 +48,14 @@ public class BootJavaConfig implements InitializingBean { this.workspace = server.getWorkspaceService(); } + public boolean isLiveInformationAutomaticTrackingEnabled() { + Boolean enabled = settings.getBoolean("boot-java", "live-information", "automatic-tracking", "on"); + return enabled != null ? enabled.booleanValue() : LIVE_INFORMATION_AUTOMATIC_TRACKING_ENABLED_DEFAULT; + } - public boolean isBootHintsEnabled() { - Boolean enabled = settings.getBoolean("boot-java", "boot-hints", "on"); - return enabled == null || enabled.booleanValue(); + public int getLiveInformationAutomaticTrackingDelay() { + Integer delay = settings.getInt("boot-java", "live-information", "automatic-tracking", "delay"); + return delay != null ? delay.intValue() : LIVE_INFORMATION_AUTOMATIC_TRACKING_DELAY_DEFAULT; } public boolean isSpringXMLSupportEnabled() { diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServerComponents.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServerComponents.java index 6bab65c70..4c9000262 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServerComponents.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/BootJavaLanguageServerComponents.java @@ -10,6 +10,7 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java; +import java.time.Duration; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; @@ -176,7 +177,7 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent new SpringProcessCommandHandler(server, liveDataService, liveDataLocalProcessConnector, liveDataRemoteProcessConnector); // track locally running processes and automatically connect to them if configured to do so - liveProcessTracker = new SpringProcessTracker(liveDataLocalProcessConnector, serverParams.watchDogInterval); + liveProcessTracker = new SpringProcessTracker(liveDataLocalProcessConnector, Duration.ofMillis(config.getLiveInformationAutomaticTrackingDelay())); // // @@ -200,8 +201,10 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent config.addListener(ignore -> { // live hover watchdog -// liveProcessTracker.setTrackingEnabled(config.isBootHintsEnabled()); -// if (config.isBootHintsEnabled()) { + liveProcessTracker.setDelay(config.getLiveInformationAutomaticTrackingDelay()); + liveProcessTracker.setTrackingEnabled(config.isLiveInformationAutomaticTrackingEnabled()); + + // if (config.isBootHintsEnabled()) { // liveHoverWatchdog.enableHighlights(); // } else { // liveHoverWatchdog.disableHighlights(); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/SpringProcessTracker.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/SpringProcessTracker.java index a641acf86..284b4d903 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/SpringProcessTracker.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/SpringProcessTracker.java @@ -16,26 +16,28 @@ import java.util.concurrent.TimeUnit; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.ide.vscode.boot.app.BootJavaConfig; /** * @author Martin Lippert */ public class SpringProcessTracker { - private static final Duration DEFAULT_INTERVAL = Duration.ofMillis(5000); + private static final long DELAY_MINIMUM = 1000; + private static final Logger log = LoggerFactory.getLogger(SpringProcessTracker.class); - private final long POLLING_INTERVAL_MILLISECONDS; private final SpringProcessConnectorLocal localProcessConnector; private final boolean isConnectorAvailable; private boolean automaticTrackingEnabled; + private Duration POLLING_INTERVAL; private ScheduledThreadPoolExecutor timer; public SpringProcessTracker(SpringProcessConnectorLocal localProcessConnector, Duration pollingInterval) { this.localProcessConnector = localProcessConnector; - this.POLLING_INTERVAL_MILLISECONDS = pollingInterval == null ? DEFAULT_INTERVAL.toMillis() : pollingInterval.toMillis(); - this.automaticTrackingEnabled = true; + this.POLLING_INTERVAL = pollingInterval != null ? pollingInterval : Duration.ofMillis(BootJavaConfig.LIVE_INFORMATION_AUTOMATIC_TRACKING_DELAY_DEFAULT); + this.automaticTrackingEnabled = false; this.isConnectorAvailable = SpringProcessConnectorLocal.isAvailable(); } @@ -52,6 +54,19 @@ public class SpringProcessTracker { } } + public void setDelay(long delay) { + Duration newDelay = Duration.ofMillis(Math.max(DELAY_MINIMUM, delay)); + + if (!newDelay.equals(POLLING_INTERVAL)) { + this.POLLING_INTERVAL = newDelay; + + if (automaticTrackingEnabled) { + stop(); + start(); + } + } + } + public synchronized void start() { if (!isConnectorAvailable) { log.error("virtual machine connector library not available, no automatic local process tracking possible"); @@ -61,7 +76,7 @@ public class SpringProcessTracker { if (automaticTrackingEnabled && timer == null) { log.info("Starting SpringProcessTracker"); this.timer = new ScheduledThreadPoolExecutor(1); - this.timer.scheduleWithFixedDelay(() -> this.update(), 0, POLLING_INTERVAL_MILLISECONDS, TimeUnit.MILLISECONDS); + this.timer.scheduleWithFixedDelay(() -> this.update(), 0, POLLING_INTERVAL.toMillis(), TimeUnit.MILLISECONDS); } } @@ -74,19 +89,18 @@ public class SpringProcessTracker { } private void update() { -// 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); -// } + 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); + } } }