Skip to content

Commit

Permalink
Make the remove maven listener a process in the launch
Browse files Browse the repository at this point in the history
Currently m2e uses an additional socket connection to receive project
events from the remote maven project. This is not visible to the user
and requires some internal maps to maintain state.

This refactors this into a more generic event facility and make it
visible as a Process in the debug view, this also has the advantage that
the process itself can be used to maintain the state.
  • Loading branch information
laeubi committed Mar 4, 2024
1 parent 112488c commit 7024d55
Show file tree
Hide file tree
Showing 16 changed files with 517 additions and 247 deletions.
2 changes: 1 addition & 1 deletion m2e-core-tests
Submodule m2e-core-tests updated 24 files
+2 −2 org.eclipse.m2e.tests/META-INF/MANIFEST.MF
+1 −1 org.eclipse.m2e.tests/projects/416882_dependencyTree/direct-depA/pom.xml
+1 −1 org.eclipse.m2e.tests/projects/416882_dependencyTree/direct-depB/pom.xml
+1 −1 org.eclipse.m2e.tests/repositories/testrepo-src/422106_legacyPlexusUtils-plugin/pom.xml
+1 −1 org.eclipse.m2e.tests/repositories/testrepo-src/438454_guicescopes-plugin/pom.xml
+1 −1 org.eclipse.m2e.tests/repositories/testrepo-src/test-buildcontext-plugin/pom.xml
+1 −1 org.eclipse.m2e.tests/repositories/testrepo-src/test-buildhelper-plugin/pom.xml
+19 −19 org.eclipse.m2e.tests/src/org/eclipse/m2e/tests/BuildPathManagerTest.java
+43 −43 org.eclipse.m2e.tests/src/org/eclipse/m2e/tests/ClasspathProviderTest.java
+12 −11 org.eclipse.m2e.tests/src/org/eclipse/m2e/tests/ProjectConfigurationManagerTest.java
+5 −4 org.eclipse.m2e.tests/src/org/eclipse/m2e/tests/TestFancyClassifierClasspathProvider.java
+6 −3 org.eclipse.m2e.tests/src/org/eclipse/m2e/tests/builder/EclipseBuildContextTest.java
+6 −3 org.eclipse.m2e.tests/src/org/eclipse/m2e/tests/builder/EclipseIncrementalBuildContextTest.java
+10 −14 ...eclipse.m2e.tests/src/org/eclipse/m2e/tests/configurators/CompilerSettingsWithEncodingConfiguratorTest.java
+19 −19 org.eclipse.m2e.tests/src/org/eclipse/m2e/tests/configurators/ResourcesEncodingConfiguratorTest.java
+2 −1 org.eclipse.m2e.tests/src/org/eclipse/m2e/tests/configurators/TestProjectConfigurator3.java
+8 −6 org.eclipse.m2e.tests/src/org/eclipse/m2e/tests/discovery/MavenDiscoveryTest.java
+2 −2 org.eclipse.m2e.tests/src/org/eclipse/m2e/tests/embedder/MavenModelUtil.java
+1 −1 org.eclipse.m2e.tests/src/org/eclipse/m2e/tests/embedder/MavenRuntimeManagerTest.java
+2 −2 org.eclipse.m2e.tests/src/org/eclipse/m2e/tests/jdt/JavaClasspathTest.java
+2 −2 org.eclipse.m2e.tests/src/org/eclipse/m2e/tests/jdt/internal/ClasspathEntryDescriptorTest.java
+6 −6 org.eclipse.m2e.tests/src/org/eclipse/m2e/tests/jdt/internal/MavenClasspathContainerSaveHelperTest.java
+2 −1 org.eclipse.m2e.tests/src/org/eclipse/m2e/tests/launch/LaunchingUtilsTest.java
+0 −28 pom.xml
2 changes: 1 addition & 1 deletion org.eclipse.m2e.feature/feature.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<feature
id="org.eclipse.m2e.feature"
label="%featureName"
version="2.6.0.qualifier"
version="2.6.1.qualifier"
provider-name="%providerName"
plugin="org.eclipse.m2e.core"
license-feature="org.eclipse.license"
Expand Down
2 changes: 1 addition & 1 deletion org.eclipse.m2e.launching/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: org.eclipse.m2e.launching;singleton:=true
Bundle-Version: 2.0.601.qualifier
Bundle-Version: 2.0.602.qualifier
Bundle-Localization: plugin
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.27.0,4.0.0)",
org.eclipse.core.variables,
Expand Down
9 changes: 9 additions & 0 deletions org.eclipse.m2e.launching/plugin.xml
Original file line number Diff line number Diff line change
Expand Up @@ -243,5 +243,14 @@
class="org.eclipse.m2e.internal.launch.MavenConsoleLineTracker"
processType="java"/>
</extension>
<extension
point="org.eclipse.m2e.launching.mavenLaunchParticipants">
<mavenLaunchParticipant
class="org.eclipse.m2e.internal.launch.MavenBuildConnectionLaunchParticipant"
id="org.eclipse.m2e.launching.buildevents"
modes="run,debug"
name="Maven Build Events">
</mavenLaunchParticipant>
</extension>

</plugin>
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
/********************************************************************************
* Copyright (c) 2022, 2024 Hannes Wellmann and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Hannes Wellmann - initial API and implementation
* Christoph Läubrich - refactor into {@link IMavenLaunchParticipant}
********************************************************************************/

package org.eclipse.m2e.internal.launch;

import java.io.IOException;
import java.util.Arrays;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchesListener2;
import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant;

import org.eclipse.m2e.core.internal.launch.MavenEmbeddedRuntime;
import org.eclipse.m2e.internal.maven.listener.M2EMavenBuildDataBridge;


public class MavenBuildConnectionLaunchParticipant implements IMavenLaunchParticipant {

static {
DebugPlugin.getDefault().getLaunchManager().addLaunchListener(new ILaunchesListener2() {
public void launchesRemoved(ILaunch[] launches) {
ensureClosed(launches);
}

private void ensureClosed(ILaunch[] launches) {
Arrays.stream(launches).flatMap(l -> MavenBuildConnectionProcess.get(l).stream())
.forEach(MavenBuildConnectionProcess::terminate);
}

public void launchesTerminated(ILaunch[] launches) {
ensureClosed(launches);
}

public void launchesAdded(ILaunch[] launches) { // ignore
}

public void launchesChanged(ILaunch[] launches) { // ignore
}
});
}

public String getProgramArguments(ILaunchConfiguration configuration, ILaunch launch, IProgressMonitor monitor) {
try {
if(MavenLaunchUtils.getMavenRuntime(launch.getLaunchConfiguration()) instanceof MavenEmbeddedRuntime) {

MavenBuildConnectionProcess process = new MavenBuildConnectionProcess(launch);
return M2EMavenBuildDataBridge.openConnection(launch.getLaunchConfiguration().getName(), process);
}
} catch(CoreException | IOException ex) { // ignore
}
return null;
}

public String getVMArguments(ILaunchConfiguration configuration, ILaunch launch, IProgressMonitor monitor) {
return null;
}

public List<ISourceLookupParticipant> getSourceLookupParticipants(ILaunchConfiguration configuration, ILaunch launch,
IProgressMonitor monitor) {
return List.of();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
/********************************************************************************
* Copyright (c) 2024 Christoph Läubrich and others
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Christoph Läubrich - initial API and implementation
********************************************************************************/

package org.eclipse.m2e.internal.launch;

import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.atomic.AtomicBoolean;

import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.model.IProcess;
import org.eclipse.debug.core.model.IStreamsProxy;

import org.eclipse.m2e.core.embedder.ArtifactKey;
import org.eclipse.m2e.internal.maven.listener.MavenBuildConnection;
import org.eclipse.m2e.internal.maven.listener.MavenBuildConnectionListener;
import org.eclipse.m2e.internal.maven.listener.MavenProjectBuildData;


/**
* This is the representation of the MavenBuildConnection we use to communicate with the remote maven process.
*/
public class MavenBuildConnectionProcess implements IProcess, MavenBuildConnectionListener {

Map<ArtifactKey, CompletableFuture<MavenProjectBuildData>> projects = new ConcurrentHashMap<>();

private ILaunch launch;

private MavenBuildConnection connection;

private Map<String, String> attributes = new HashMap<>();

private AtomicBoolean terminated = new AtomicBoolean();

private String label;

/**
* @param launch
*/
public MavenBuildConnectionProcess(ILaunch launch) {
this.launch = launch;
}

public <T> T getAdapter(Class<T> adapter) {
return null;
}

public boolean canTerminate() {
return false;
}

public boolean isTerminated() {
return connection != null && connection.isCompleted();
}

public void terminate() {
if(connection != null && terminated.compareAndSet(false, true)) {
connection.close();
fireEvent(new DebugEvent(this, DebugEvent.TERMINATE));
for(CompletableFuture<MavenProjectBuildData> future : projects.values()) {
future.cancel(true);
}
}
}

public String getLabel() {
// TODO fetch the maven version from the remove process like mvn -V ...
if(label != null) {
return "Maven<" + label + ">";
}
return "Maven";
}

public ILaunch getLaunch() {
return launch;
}

public IStreamsProxy getStreamsProxy() {
return null;
}

public void setAttribute(String key, String value) {
attributes.put(key, value);
fireEvent(new DebugEvent(this, DebugEvent.CHANGE));
}

public String getAttribute(String key) {
return attributes.get(key);
}

public int getExitValue() {
return 0;
}

private static void fireEvent(DebugEvent event) {
DebugPlugin manager = DebugPlugin.getDefault();
if(manager != null) {
manager.fireDebugEventSet(new DebugEvent[] {event});
}
}

public static Optional<MavenBuildConnectionProcess> get(ILaunch launch) {
for(IProcess process : launch.getProcesses()) {
if(process instanceof MavenBuildConnectionProcess p) {
return Optional.of(p);
}
}
return Optional.empty();
}

/**
* @param launch2
* @param groupId
* @param artifactId
* @param version
* @return
*/
public CompletableFuture<MavenProjectBuildData> getBuildProject(String groupId, String artifactId, String version) {
return projects.computeIfAbsent(new ArtifactKey(groupId, artifactId, version, null),
x -> new CompletableFuture<>());
}

public void onOpen(String label, MavenBuildConnection connection) {
this.label = label;
this.connection = connection;
getLaunch().addProcess(this);
fireEvent(new DebugEvent(this, DebugEvent.CREATE));

}

public void onClose() {
terminate();
}

public void onData(MavenProjectBuildData buildData) {
projects.computeIfAbsent(new ArtifactKey(buildData.groupId, buildData.artifactId, buildData.version, null), x -> new CompletableFuture<>())
.complete(buildData);
}

}

This file was deleted.

Loading

0 comments on commit 7024d55

Please sign in to comment.