Skip to content

Commit 7024d55

Browse files
committed
Make the remove maven listener a process in the launch
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.
1 parent 112488c commit 7024d55

16 files changed

+517
-247
lines changed

m2e-core-tests

Submodule m2e-core-tests updated 24 files

org.eclipse.m2e.feature/feature.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<feature
33
id="org.eclipse.m2e.feature"
44
label="%featureName"
5-
version="2.6.0.qualifier"
5+
version="2.6.1.qualifier"
66
provider-name="%providerName"
77
plugin="org.eclipse.m2e.core"
88
license-feature="org.eclipse.license"

org.eclipse.m2e.launching/META-INF/MANIFEST.MF

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
22
Bundle-ManifestVersion: 2
33
Bundle-Name: %Bundle-Name
44
Bundle-SymbolicName: org.eclipse.m2e.launching;singleton:=true
5-
Bundle-Version: 2.0.601.qualifier
5+
Bundle-Version: 2.0.602.qualifier
66
Bundle-Localization: plugin
77
Require-Bundle: org.eclipse.core.runtime;bundle-version="[3.27.0,4.0.0)",
88
org.eclipse.core.variables,

org.eclipse.m2e.launching/plugin.xml

+9
Original file line numberDiff line numberDiff line change
@@ -243,5 +243,14 @@
243243
class="org.eclipse.m2e.internal.launch.MavenConsoleLineTracker"
244244
processType="java"/>
245245
</extension>
246+
<extension
247+
point="org.eclipse.m2e.launching.mavenLaunchParticipants">
248+
<mavenLaunchParticipant
249+
class="org.eclipse.m2e.internal.launch.MavenBuildConnectionLaunchParticipant"
250+
id="org.eclipse.m2e.launching.buildevents"
251+
modes="run,debug"
252+
name="Maven Build Events">
253+
</mavenLaunchParticipant>
254+
</extension>
246255

247256
</plugin>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
/********************************************************************************
2+
* Copyright (c) 2022, 2024 Hannes Wellmann and others
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Hannes Wellmann - initial API and implementation
12+
* Christoph Läubrich - refactor into {@link IMavenLaunchParticipant}
13+
********************************************************************************/
14+
15+
package org.eclipse.m2e.internal.launch;
16+
17+
import java.io.IOException;
18+
import java.util.Arrays;
19+
import java.util.List;
20+
21+
import org.eclipse.core.runtime.CoreException;
22+
import org.eclipse.core.runtime.IProgressMonitor;
23+
import org.eclipse.debug.core.DebugPlugin;
24+
import org.eclipse.debug.core.ILaunch;
25+
import org.eclipse.debug.core.ILaunchConfiguration;
26+
import org.eclipse.debug.core.ILaunchesListener2;
27+
import org.eclipse.debug.core.sourcelookup.ISourceLookupParticipant;
28+
29+
import org.eclipse.m2e.core.internal.launch.MavenEmbeddedRuntime;
30+
import org.eclipse.m2e.internal.maven.listener.M2EMavenBuildDataBridge;
31+
32+
33+
public class MavenBuildConnectionLaunchParticipant implements IMavenLaunchParticipant {
34+
35+
static {
36+
DebugPlugin.getDefault().getLaunchManager().addLaunchListener(new ILaunchesListener2() {
37+
public void launchesRemoved(ILaunch[] launches) {
38+
ensureClosed(launches);
39+
}
40+
41+
private void ensureClosed(ILaunch[] launches) {
42+
Arrays.stream(launches).flatMap(l -> MavenBuildConnectionProcess.get(l).stream())
43+
.forEach(MavenBuildConnectionProcess::terminate);
44+
}
45+
46+
public void launchesTerminated(ILaunch[] launches) {
47+
ensureClosed(launches);
48+
}
49+
50+
public void launchesAdded(ILaunch[] launches) { // ignore
51+
}
52+
53+
public void launchesChanged(ILaunch[] launches) { // ignore
54+
}
55+
});
56+
}
57+
58+
public String getProgramArguments(ILaunchConfiguration configuration, ILaunch launch, IProgressMonitor monitor) {
59+
try {
60+
if(MavenLaunchUtils.getMavenRuntime(launch.getLaunchConfiguration()) instanceof MavenEmbeddedRuntime) {
61+
62+
MavenBuildConnectionProcess process = new MavenBuildConnectionProcess(launch);
63+
return M2EMavenBuildDataBridge.openConnection(launch.getLaunchConfiguration().getName(), process);
64+
}
65+
} catch(CoreException | IOException ex) { // ignore
66+
}
67+
return null;
68+
}
69+
70+
public String getVMArguments(ILaunchConfiguration configuration, ILaunch launch, IProgressMonitor monitor) {
71+
return null;
72+
}
73+
74+
public List<ISourceLookupParticipant> getSourceLookupParticipants(ILaunchConfiguration configuration, ILaunch launch,
75+
IProgressMonitor monitor) {
76+
return List.of();
77+
}
78+
79+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
/********************************************************************************
2+
* Copyright (c) 2024 Christoph Läubrich and others
3+
*
4+
* This program and the accompanying materials are made available under the
5+
* terms of the Eclipse Public License 2.0 which is available at
6+
* http://www.eclipse.org/legal/epl-2.0.
7+
*
8+
* SPDX-License-Identifier: EPL-2.0
9+
*
10+
* Contributors:
11+
* Christoph Läubrich - initial API and implementation
12+
********************************************************************************/
13+
14+
package org.eclipse.m2e.internal.launch;
15+
16+
import java.util.HashMap;
17+
import java.util.Map;
18+
import java.util.Optional;
19+
import java.util.concurrent.CompletableFuture;
20+
import java.util.concurrent.ConcurrentHashMap;
21+
import java.util.concurrent.atomic.AtomicBoolean;
22+
23+
import org.eclipse.debug.core.DebugEvent;
24+
import org.eclipse.debug.core.DebugPlugin;
25+
import org.eclipse.debug.core.ILaunch;
26+
import org.eclipse.debug.core.model.IProcess;
27+
import org.eclipse.debug.core.model.IStreamsProxy;
28+
29+
import org.eclipse.m2e.core.embedder.ArtifactKey;
30+
import org.eclipse.m2e.internal.maven.listener.MavenBuildConnection;
31+
import org.eclipse.m2e.internal.maven.listener.MavenBuildConnectionListener;
32+
import org.eclipse.m2e.internal.maven.listener.MavenProjectBuildData;
33+
34+
35+
/**
36+
* This is the representation of the MavenBuildConnection we use to communicate with the remote maven process.
37+
*/
38+
public class MavenBuildConnectionProcess implements IProcess, MavenBuildConnectionListener {
39+
40+
Map<ArtifactKey, CompletableFuture<MavenProjectBuildData>> projects = new ConcurrentHashMap<>();
41+
42+
private ILaunch launch;
43+
44+
private MavenBuildConnection connection;
45+
46+
private Map<String, String> attributes = new HashMap<>();
47+
48+
private AtomicBoolean terminated = new AtomicBoolean();
49+
50+
private String label;
51+
52+
/**
53+
* @param launch
54+
*/
55+
public MavenBuildConnectionProcess(ILaunch launch) {
56+
this.launch = launch;
57+
}
58+
59+
public <T> T getAdapter(Class<T> adapter) {
60+
return null;
61+
}
62+
63+
public boolean canTerminate() {
64+
return false;
65+
}
66+
67+
public boolean isTerminated() {
68+
return connection != null && connection.isCompleted();
69+
}
70+
71+
public void terminate() {
72+
if(connection != null && terminated.compareAndSet(false, true)) {
73+
connection.close();
74+
fireEvent(new DebugEvent(this, DebugEvent.TERMINATE));
75+
for(CompletableFuture<MavenProjectBuildData> future : projects.values()) {
76+
future.cancel(true);
77+
}
78+
}
79+
}
80+
81+
public String getLabel() {
82+
// TODO fetch the maven version from the remove process like mvn -V ...
83+
if(label != null) {
84+
return "Maven<" + label + ">";
85+
}
86+
return "Maven";
87+
}
88+
89+
public ILaunch getLaunch() {
90+
return launch;
91+
}
92+
93+
public IStreamsProxy getStreamsProxy() {
94+
return null;
95+
}
96+
97+
public void setAttribute(String key, String value) {
98+
attributes.put(key, value);
99+
fireEvent(new DebugEvent(this, DebugEvent.CHANGE));
100+
}
101+
102+
public String getAttribute(String key) {
103+
return attributes.get(key);
104+
}
105+
106+
public int getExitValue() {
107+
return 0;
108+
}
109+
110+
private static void fireEvent(DebugEvent event) {
111+
DebugPlugin manager = DebugPlugin.getDefault();
112+
if(manager != null) {
113+
manager.fireDebugEventSet(new DebugEvent[] {event});
114+
}
115+
}
116+
117+
public static Optional<MavenBuildConnectionProcess> get(ILaunch launch) {
118+
for(IProcess process : launch.getProcesses()) {
119+
if(process instanceof MavenBuildConnectionProcess p) {
120+
return Optional.of(p);
121+
}
122+
}
123+
return Optional.empty();
124+
}
125+
126+
/**
127+
* @param launch2
128+
* @param groupId
129+
* @param artifactId
130+
* @param version
131+
* @return
132+
*/
133+
public CompletableFuture<MavenProjectBuildData> getBuildProject(String groupId, String artifactId, String version) {
134+
return projects.computeIfAbsent(new ArtifactKey(groupId, artifactId, version, null),
135+
x -> new CompletableFuture<>());
136+
}
137+
138+
public void onOpen(String label, MavenBuildConnection connection) {
139+
this.label = label;
140+
this.connection = connection;
141+
getLaunch().addProcess(this);
142+
fireEvent(new DebugEvent(this, DebugEvent.CREATE));
143+
144+
}
145+
146+
public void onClose() {
147+
terminate();
148+
}
149+
150+
public void onData(MavenProjectBuildData buildData) {
151+
projects.computeIfAbsent(new ArtifactKey(buildData.groupId, buildData.artifactId, buildData.version, null), x -> new CompletableFuture<>())
152+
.complete(buildData);
153+
}
154+
155+
}

org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenBuildProjectDataConnection.java

-107
This file was deleted.

0 commit comments

Comments
 (0)