From c51b97ad56d1d9a9d2ce5a8cc564919db7eab6da Mon Sep 17 00:00:00 2001 From: aboyko Date: Thu, 8 Sep 2022 17:45:56 -0400 Subject: [PATCH] [gh-832] Auto-connect to boot app to fetch live data --- .../plugin.xml | 6 ++ .../eclipse/boot/dash/BootDashActivator.java | 85 +++++++++++++++++++ .../DefaultLiveProcessCommandExecutor.java | 7 +- .../boot/dash/prefs/BootDashPrefsPage.java | 3 +- .../boot/dash/prefs/PrefsInitializer.java | 28 ++++++ .../boot/ls/BootJavaPreferencesPage.java | 5 +- .../tooling/boot/ls/Constants.java | 5 +- .../DelegatingStreamConnectionProvider.java | 7 +- .../tooling/boot/ls/PrefsInitializer.java | 4 +- .../v2/SpringProcessCommandHandler.java | 2 - 10 files changed, 128 insertions(+), 24 deletions(-) create mode 100644 eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/prefs/PrefsInitializer.java diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/plugin.xml b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/plugin.xml index 920c98636..5dbdab06c 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/plugin.xml +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/plugin.xml @@ -327,5 +327,11 @@ class="org.springframework.ide.eclipse.boot.dash.remoteapps.RemoteAppsFromBootDash"> + + + + diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/BootDashActivator.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/BootDashActivator.java index db5cd3b43..863bf3335 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/BootDashActivator.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/BootDashActivator.java @@ -10,20 +10,42 @@ *******************************************************************************/ package org.springframework.ide.eclipse.boot.dash; +import java.time.Duration; +import java.util.List; +import java.util.Map; + import org.eclipse.core.net.proxy.IProxyService; import org.eclipse.core.runtime.preferences.IEclipsePreferences; import org.eclipse.core.runtime.preferences.InstanceScope; +import org.eclipse.debug.core.DebugPlugin; +import org.eclipse.debug.core.ILaunch; +import org.eclipse.debug.core.ILaunchConfiguration; +import org.eclipse.debug.core.model.IProcess; import org.eclipse.jface.resource.ImageDescriptor; import org.eclipse.jface.resource.ImageRegistry; +import org.eclipse.jface.util.IPropertyChangeListener; +import org.eclipse.jface.util.PropertyChangeEvent; import org.eclipse.ui.plugin.AbstractUIPlugin; import org.osgi.framework.BundleContext; import org.osgi.framework.ServiceReference; import org.springframework.ide.eclipse.boot.dash.di.SimpleDIContext; +import org.springframework.ide.eclipse.boot.dash.liveprocess.CommandInfo; +import org.springframework.ide.eclipse.boot.dash.liveprocess.LiveProcessCommandsExecutor; +import org.springframework.ide.eclipse.boot.dash.liveprocess.LiveProcessCommandsExecutor.Server; import org.springframework.ide.eclipse.boot.dash.model.BootDashModelContext; import org.springframework.ide.eclipse.boot.dash.model.BootDashViewModel; import org.springframework.ide.eclipse.boot.dash.model.DefaultBootDashModelContext; +import org.springframework.ide.eclipse.boot.dash.model.LocalBootDashModel; +import org.springframework.ide.eclipse.boot.dash.model.RunState; +import org.springframework.ide.eclipse.boot.dash.model.RunTargets; +import org.springframework.ide.eclipse.boot.dash.util.LaunchConfRunStateTracker; +import org.springframework.ide.eclipse.boot.dash.util.RunStateTracker.RunStateListener; +import org.springframework.ide.eclipse.boot.launch.BootLaunchConfigurationDelegate; import org.springsource.ide.eclipse.commons.livexp.util.Log; +import reactor.core.publisher.Flux; +import reactor.core.publisher.Mono; + /** * The activator class controls the plug-in life cycle */ @@ -32,6 +54,8 @@ public class BootDashActivator extends AbstractUIPlugin { // The plug-in ID public static final String PLUGIN_ID = "org.springframework.ide.eclipse.boot.dash"; //$NON-NLS-1$ + public static final String PREF_LIVE_INFORMATION_AUTO_CONNECT = "boot-java.live-information.automatic-connection.on"; + public static final String DT_ICON_ID = "devttools"; public static final String MANIFEST_ICON = "manifest"; public static final String CLOUD_ICON = "cloud"; @@ -80,6 +104,7 @@ public class BootDashActivator extends AbstractUIPlugin { super.start(context); plugin = this; new M2ELogbackCustomizer().schedule(); + connectToLaunchedBootApps(); } /* @@ -166,4 +191,64 @@ public class BootDashActivator extends AbstractUIPlugin { return InstanceScope.INSTANCE.getNode(PLUGIN_ID); } + private final RunStateListener RUN_STATE_LISTENER = new RunStateListener() { + + @Override + public void stateChanged(ILaunchConfiguration owner) { + if (BootLaunchConfigurationDelegate.getEnableJmx(owner)) { + LocalBootDashModel localModel = (LocalBootDashModel) getModel().getSectionByTargetId(RunTargets.LOCAL.getId()); + LaunchConfRunStateTracker tracker = localModel.getLaunchConfRunStateTracker(); + RunState state = tracker.getState(owner); + if (state == RunState.RUNNING || state == RunState.DEBUGGING) { + for (ILaunch l : DebugPlugin.getDefault().getLaunchManager().getLaunches()) { + if (l.getLaunchConfiguration() == owner) { + for (IProcess p : l.getProcesses()) { + String pid = p.getAttribute(IProcess.ATTR_PROCESS_ID); + if (pid != null) { + List servers = LiveProcessCommandsExecutor.getDefault() + .getLanguageServers(); + + CommandInfo cmd = new CommandInfo("sts/livedata/connect", + Map.of("processKey", pid)); + + // The delay seems to be necessary for the moment. Although the process is created VM attach API may not work at early stages of the process run. + // "VirtualMachine.list()" call may not list the newly created process which means the process is gone and triggers disconnect. + // If lifecycle management is enabled the ready state seem to be a great indicator of a boot process fully started. + // TODO: explore health endpoint perhaps instead of ready state under Admin endpoint. + Flux.fromIterable(servers).flatMap(s -> Mono.delay(Duration.ofMillis(500)).then(s.executeCommand(cmd))).subscribe(); + + } + } + } + } + } + + } + } + }; + + private void connectToLaunchedBootApps() { + updateRunStateListening(); + + getPreferenceStore().addPropertyChangeListener(new IPropertyChangeListener() { + @Override + public void propertyChange(PropertyChangeEvent event) { + if (PREF_LIVE_INFORMATION_AUTO_CONNECT.equals(event.getProperty())) { + updateRunStateListening(); + } + } + }); + + } + + private void updateRunStateListening() { + LocalBootDashModel localModel = (LocalBootDashModel) getModel().getSectionByTargetId(RunTargets.LOCAL.getId()); + LaunchConfRunStateTracker tracker = localModel.getLaunchConfRunStateTracker(); + if (getPreferenceStore().getBoolean(PREF_LIVE_INFORMATION_AUTO_CONNECT)) { + tracker.addListener(RUN_STATE_LISTENER); + } else { + tracker.removeListener(RUN_STATE_LISTENER); + } + } + } diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/liveprocess/DefaultLiveProcessCommandExecutor.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/liveprocess/DefaultLiveProcessCommandExecutor.java index 96a2ea319..c0c946cbe 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/liveprocess/DefaultLiveProcessCommandExecutor.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/liveprocess/DefaultLiveProcessCommandExecutor.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2019 Pivotal Software, Inc. + * Copyright (c) 2019, 2022 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 @@ -50,11 +50,10 @@ public final class DefaultLiveProcessCommandExecutor implements LiveProcessComma @Override public Mono executeCommand(CommandInfo cmd) { - return Mono.fromFuture(ls.getWorkspaceService().executeCommand(new ExecuteCommandParams( + return Mono.fromRunnable(() -> ls.getWorkspaceService().executeCommand(new ExecuteCommandParams( cmd.command, ImmutableList.of(cmd.info) - ))) - .then(); + ))); } } diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/prefs/BootDashPrefsPage.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/prefs/BootDashPrefsPage.java index eb3602239..ea2a83cd9 100644 --- a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/prefs/BootDashPrefsPage.java +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/prefs/BootDashPrefsPage.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2020 Pivotal, Inc. + * Copyright (c) 2020, 2022 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 @@ -36,6 +36,7 @@ public class BootDashPrefsPage extends FieldEditorPreferencePage implements IWor @Override protected void createFieldEditors() { Composite parent = getFieldEditorParent(); + addField(new BooleanFieldEditor(BootDashActivator.PREF_LIVE_INFORMATION_AUTO_CONNECT, "Auto Connect to launched Boot app to show Live Information", parent)); for (RunTargetType rtt : BootDashActivator.getDefault().getModel().getRunTargetTypes()) { if (rtt.supportsDeletion()) { addField(new BooleanFieldEditor(DeleteElementsAction.PREF_SKIP_CONFIRM_DELETE(rtt), "Skip Delete Element Confirmation ("+rtt.getName()+")", parent)); diff --git a/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/prefs/PrefsInitializer.java b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/prefs/PrefsInitializer.java new file mode 100644 index 000000000..0da0f87f2 --- /dev/null +++ b/eclipse-extensions/org.springframework.ide.eclipse.boot.dash/src/org/springframework/ide/eclipse/boot/dash/prefs/PrefsInitializer.java @@ -0,0 +1,28 @@ +/******************************************************************************* + * Copyright (c) 2022 VMware, 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: + * VMware, Inc. - initial API and implementation + *******************************************************************************/ +package org.springframework.ide.eclipse.boot.dash.prefs; + +import org.eclipse.core.runtime.preferences.AbstractPreferenceInitializer; +import org.eclipse.jface.preference.IPreferenceStore; +import org.springframework.ide.eclipse.boot.dash.BootDashActivator; + +public class PrefsInitializer extends AbstractPreferenceInitializer { + + public PrefsInitializer() { + } + + @Override + public void initializeDefaultPreferences() { + IPreferenceStore preferenceStore = BootDashActivator.getDefault().getPreferenceStore(); + preferenceStore.setDefault(BootDashActivator.PREF_LIVE_INFORMATION_AUTO_CONNECT, true); + } + +} 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 910a6bed9..32584f1d6 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2019 Pivotal, Inc. + * Copyright (c) 2017, 2022 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 @@ -83,9 +83,6 @@ public class BootJavaPreferencesPage extends FieldEditorPreferencePage implement addField(new BooleanFieldEditor(Constants.PREF_SCAN_JAVA_TEST_SOURCES, "Scan Java test sources", 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 StringFieldEditor(Constants.PREF_LIVE_INFORMATION_FETCH_DATA_RETRY_MAX_NO, "Live Information - Max number of retries (before giving up)", fieldEditorParent)); addField(new StringFieldEditor(Constants.PREF_LIVE_INFORMATION_FETCH_DATA_RETRY_DELAY_IN_SECONDS, "Live Information - Delay between retries in seconds", fieldEditorParent)); 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 3ead21c41..5019d61b4 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2019 Pivotal, Inc. + * Copyright (c) 2017, 2022 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 @@ -17,9 +17,6 @@ public class Constants { public static final String PLUGIN_ID = "org.springframework.tooling.boot.ls"; - 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_LIVE_INFORMATION_FETCH_DATA_RETRY_MAX_NO = "boot-java.live-information.fetch-data.max-retries"; public static final String PREF_LIVE_INFORMATION_FETCH_DATA_RETRY_DELAY_IN_SECONDS = "boot-java.live-information.fetch-data.retry-delay-in-seconds"; 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 fc08a5db8..4690f14b8 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2020 Pivotal, Inc. + * Copyright (c) 2017, 2022 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 @@ -156,7 +156,6 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi Map settings = new HashMap<>(); Map bootJavaObj = new HashMap<>(); Map liveInformation = new HashMap<>(); - Map liveInformationAutomaticTracking = new HashMap<>(); Map liveInformationFetchData = new HashMap<>(); Map supportXML = new HashMap<>(); Map bootChangeDetection = new HashMap<>(); @@ -166,13 +165,9 @@ public class DelegatingStreamConnectionProvider implements StreamConnectionProvi IPreferenceStore preferenceStore = BootLanguageServerPlugin.getDefault().getPreferenceStore(); - liveInformationAutomaticTracking.put("on", preferenceStore.getBoolean(Constants.PREF_LIVE_INFORMATION_AUTOMATIC_TRACKING_ENABLED)); - liveInformationAutomaticTracking.put("delay", preferenceStore.getInt(Constants.PREF_LIVE_INFORMATION_AUTOMATIC_TRACKING_DELAY)); - liveInformationFetchData.put("max-retries", preferenceStore.getInt(Constants.PREF_LIVE_INFORMATION_FETCH_DATA_RETRY_MAX_NO)); liveInformationFetchData.put("retry-delay-in-seconds", preferenceStore.getInt(Constants.PREF_LIVE_INFORMATION_FETCH_DATA_RETRY_DELAY_IN_SECONDS)); - liveInformation.put("automatic-tracking", liveInformationAutomaticTracking); liveInformation.put("fetch-data", liveInformationFetchData); supportXML.put("on", preferenceStore.getBoolean(Constants.PREF_SUPPORT_SPRING_XML_CONFIGS)); 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 9ddaf6d2b..4592d0a30 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 @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2019 Pivotal, Inc. + * Copyright (c) 2017, 2022 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 @@ -28,8 +28,6 @@ public class PrefsInitializer extends AbstractPreferenceInitializer { public void initializeDefaultPreferences() { IPreferenceStore preferenceStore = BootLanguageServerPlugin.getDefault().getPreferenceStore(); - preferenceStore.setDefault(Constants.PREF_LIVE_INFORMATION_AUTOMATIC_TRACKING_ENABLED, true); - preferenceStore.setDefault(Constants.PREF_LIVE_INFORMATION_AUTOMATIC_TRACKING_DELAY, 5000); preferenceStore.setDefault(Constants.PREF_LIVE_INFORMATION_FETCH_DATA_RETRY_MAX_NO, 10); preferenceStore.setDefault(Constants.PREF_LIVE_INFORMATION_FETCH_DATA_RETRY_DELAY_IN_SECONDS, 3); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/SpringProcessCommandHandler.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/SpringProcessCommandHandler.java index 3c28fef5d..72e4c5010 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/SpringProcessCommandHandler.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/livehover/v2/SpringProcessCommandHandler.java @@ -17,8 +17,6 @@ import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.CompletableFuture; -import java.util.stream.Collectors; -import java.util.stream.Stream; import org.eclipse.lsp4j.ExecuteCommandParams; import org.slf4j.Logger;