project = Arrays.stream(wsRoot.findContainersForLocationURI(basedirURI))
+ .filter(IProject.class::isInstance).map(IProject.class::cast).findFirst();
+ //if project is absent, the project build in Maven is not in the workspace
+ return project.isPresent() ? new ProjectReference(project.get(), buildProject) : null;
+ });
+ }).orElseGet(() -> CompletableFuture.completedFuture(null));
}
@Override
diff --git a/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchExtensionsSupport.java b/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchExtensionsSupport.java
index 892a25aa8..19484380e 100644
--- a/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchExtensionsSupport.java
+++ b/org.eclipse.m2e.launching/src/org/eclipse/m2e/internal/launch/MavenLaunchExtensionsSupport.java
@@ -98,7 +98,6 @@ public void appendVMArguments(VMArguments arguments, ILaunchConfiguration config
for(IMavenLaunchParticipant participant : participants) {
arguments.append(participant.getVMArguments(configuration, launch, monitor));
}
- MavenBuildProjectDataConnection.openListenerConnection(launch, arguments);
}
}
diff --git a/org.eclipse.m2e.maven.runtime/pom.xml b/org.eclipse.m2e.maven.runtime/pom.xml
index b1146a7ed..15d8e9237 100644
--- a/org.eclipse.m2e.maven.runtime/pom.xml
+++ b/org.eclipse.m2e.maven.runtime/pom.xml
@@ -20,7 +20,7 @@
org.eclipse.m2e.maven.runtime
- 3.9.600-SNAPSHOT
+ 3.9.601-SNAPSHOT
jar
M2E Embedded Maven Runtime (includes Incubating components)
diff --git a/org.eclipse.m2e.maven.runtime/src/main/java/org/eclipse/m2e/internal/maven/listener/M2EMavenBuildDataBridge.java b/org.eclipse.m2e.maven.runtime/src/main/java/org/eclipse/m2e/internal/maven/listener/M2EMavenBuildDataBridge.java
index 72d113fe0..8b734340e 100644
--- a/org.eclipse.m2e.maven.runtime/src/main/java/org/eclipse/m2e/internal/maven/listener/M2EMavenBuildDataBridge.java
+++ b/org.eclipse.m2e.maven.runtime/src/main/java/org/eclipse/m2e/internal/maven/listener/M2EMavenBuildDataBridge.java
@@ -21,22 +21,14 @@
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.StringJoiner;
-import java.util.concurrent.atomic.AtomicBoolean;
-import java.util.function.Consumer;
import javax.inject.Named;
import javax.inject.Singleton;
+import org.apache.maven.AbstractMavenLifecycleParticipant;
+import org.apache.maven.MavenExecutionException;
import org.apache.maven.eventspy.EventSpy;
-import org.apache.maven.execution.ExecutionEvent;
-import org.apache.maven.execution.ExecutionEvent.Type;
-import org.apache.maven.project.MavenProject;
+import org.apache.maven.execution.MavenSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -48,9 +40,9 @@
* @author Hannes Wellmann
*
*/
-@Named
@Singleton
-public class M2EMavenBuildDataBridge implements EventSpy {
+@Named("m2e")
+public class M2EMavenBuildDataBridge extends AbstractMavenLifecycleParticipant {
private static final String SOCKET_FILE_PROPERTY_NAME = "m2e.build.project.data.socket.port";
private static final String DATA_SET_SEPARATOR = ";;";
@@ -60,7 +52,7 @@ public class M2EMavenBuildDataBridge implements EventSpy {
private SocketChannel writeChannel;
@Override
- public void init(Context context) throws IOException {
+ public synchronized void afterSessionStart(MavenSession session) throws MavenExecutionException {
String socketPort = System.getProperty(SOCKET_FILE_PROPERTY_NAME);
if (socketPort != null) {
try {
@@ -76,79 +68,37 @@ public void init(Context context) throws IOException {
}
@Override
- public void close() throws IOException {
- writeChannel.close();
+ public void afterSessionEnd(MavenSession session) throws MavenExecutionException {
+ close();
}
- @Override
- public void onEvent(Object event) throws Exception {
- if (writeChannel != null && event instanceof ExecutionEvent
- && ((ExecutionEvent) event).getType() == Type.ProjectStarted) {
-
- String message = serializeProjectData(((ExecutionEvent) event).getProject());
-
- ByteBuffer buffer = ByteBuffer.wrap(message.getBytes());
- synchronized (writeChannel) {
- while (buffer.hasRemaining()) {
- writeChannel.write(buffer);
- }
+ private synchronized void close() {
+ if (writeChannel != null) {
+ try {
+ writeChannel.close();
+ } catch (IOException e) {
+ // nothing we want to do here...
}
}
+ writeChannel = null;
}
- private static String serializeProjectData(MavenProject project) {
- StringJoiner data = new StringJoiner(",");
- add(data, "groupId", project.getGroupId());
- add(data, "artifactId", project.getArtifactId());
- add(data, "version", project.getVersion());
- add(data, "file", project.getFile());
- add(data, "basedir", project.getBasedir());
- add(data, "build.directory", project.getBuild().getDirectory());
- return data.toString() + DATA_SET_SEPARATOR;
- }
-
- private static void add(StringJoiner data, String key, Object value) {
- data.add(key + "=" + value);
+ public synchronized boolean isActive() {
+ return writeChannel != null;
}
- /**
- *
- * This method is supposed to be called from M2E within the Eclipse-IDE JVM.
- *
- *
- * @param dataSet the data-set to parse
- * @return the {@link MavenProjectBuildData} parsed from the given string
- */
- private static MavenProjectBuildData parseMavenBuildProject(String dataSet) {
- Map data = new HashMap<>(8);
- for (String entry : dataSet.split(",")) {
- String[] keyValue = entry.split("=");
- if (keyValue.length != 2) {
- throw new IllegalStateException("Invalid data-set format" + dataSet);
- }
- data.put(keyValue[0], keyValue[1]);
+ public synchronized void sendMessage(String message) {
+ if (writeChannel == null) {
+ return;
}
- return new MavenProjectBuildData(data);
- }
-
- public static final class MavenProjectBuildData {
- public final String groupId;
- public final String artifactId;
- public final String version;
- public final Path projectBasedir;
- public final Path projectFile;
- public final Path projectBuildDirectory;
-
- MavenProjectBuildData(Map data) {
- if (data.size() != 6) {
- throw new IllegalArgumentException();
+ ByteBuffer buffer = ByteBuffer.wrap((message + DATA_SET_SEPARATOR).getBytes());
+ while (buffer.hasRemaining()) {
+ try {
+ writeChannel.write(buffer);
+ } catch (IOException e) {
+ // channel seems dead...
+ close();
}
- this.groupId = Objects.requireNonNull(data.get("groupId"));
- this.artifactId = Objects.requireNonNull(data.get("artifactId"));
- this.version = Objects.requireNonNull(data.get("version"));
- this.projectBasedir = Paths.get(data.get("basedir"));
- this.projectFile = Paths.get(data.get("file"));
- this.projectBuildDirectory = Paths.get(data.get("build.directory"));
}
}
@@ -156,15 +106,14 @@ public static final class MavenProjectBuildData {
* Prepares the connection to a {@code Maven build JVM} to be launched and is
* intended to be called from the Eclipse IDE JVM.
*
- * @param label the label of the listener thread
- * @param datasetListener the listener, which is notified whenever a new
- * {@link MavenProjectBuildData MavenProjectBuildDataSet}
- * has arived from the Maven VM in the Eclipse-IDE VM.
- * @return the preapre {@link MavenBuildConnection}
- * @throws IOException
+ * @param label the label of the listener thread
+ * @param listener the listener, which is notified whenever a new
+ * {@link MavenProjectBuildData MavenProjectBuildDataSet} has
+ * arived from the Maven VM in the Eclipse-IDE VM.
+ * @return the maven arguments
+ * @throws IOException if init of connection failed
*/
- public static MavenBuildConnection prepareConnection(String label, Consumer datasetListener)
- throws IOException {
+ public static String openConnection(String label, MavenBuildConnectionListener listener) throws IOException {
// TODO: use UNIX domain socket once Java-17 is required by Maven
// Path socketFile = Files.createTempFile("m2e.maven.build.listener", ".socket");
@@ -176,7 +125,7 @@ public static MavenBuildConnection prepareConnection(String label, Consumer {
try (ServerSocketChannel s = server; SocketChannel readChannel = server.accept()) {
@@ -187,9 +136,8 @@ public static MavenBuildConnection prepareConnection(String label, Consumer= 0;) {
String dataSet = message.substring(0, terminatorIndex);
message.delete(0, terminatorIndex + DATA_SET_SEPARATOR.length());
-
- MavenProjectBuildData buildData = parseMavenBuildProject(dataSet);
- datasetListener.accept(buildData);
+ MavenProjectBuildData buildData = MavenProjectBuildData.parseMavenBuildProject(dataSet);
+ listener.onData(buildData);
}
// Explicit cast for compatibility with covariant return type on JDK 9's
// ByteBuffer
@@ -197,7 +145,7 @@ public static MavenBuildConnection prepareConnection(String label, Consumer connection reader");
reader.setDaemon(true);
reader.start();
- return connection;
+ listener.onOpen(label, connection);
+ String port = Integer.toString(((InetSocketAddress) server.getLocalAddress()).getPort());
+ return "-D" + SOCKET_FILE_PROPERTY_NAME + "=" + port;
}
-
- public static final class MavenBuildConnection {
- private final ServerSocketChannel server;
- private final AtomicBoolean readCompleted = new AtomicBoolean(false);
-
- MavenBuildConnection(ServerSocketChannel server) {
- this.server = server;
- }
-
- public String getMavenVMArguments() throws IOException {
- String port = Integer.toString(((InetSocketAddress) server.getLocalAddress()).getPort());
- return "-D" + SOCKET_FILE_PROPERTY_NAME + "=" + port;
- }
-
- public boolean isReadCompleted() {
- return readCompleted.get();
- }
-
- public void close() throws IOException {
- // Close the server to ensure the reader-thread does not wait forever for a
- // connection from the Maven-process in case something went wrong during
- // launching or while setting up the connection.
- server.close();
- }
- }
-
}
diff --git a/org.eclipse.m2e.maven.runtime/src/main/java/org/eclipse/m2e/internal/maven/listener/M2eEventSpy.java b/org.eclipse.m2e.maven.runtime/src/main/java/org/eclipse/m2e/internal/maven/listener/M2eEventSpy.java
new file mode 100644
index 000000000..0f284903b
--- /dev/null
+++ b/org.eclipse.m2e.maven.runtime/src/main/java/org/eclipse/m2e/internal/maven/listener/M2eEventSpy.java
@@ -0,0 +1,58 @@
+/********************************************************************************
+ * 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 - factor out into dedicated component
+ ********************************************************************************/
+package org.eclipse.m2e.internal.maven.listener;
+
+import javax.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Singleton;
+
+import org.apache.maven.eventspy.EventSpy;
+import org.apache.maven.execution.ExecutionEvent;
+import org.apache.maven.execution.ExecutionEvent.Type;
+
+@Singleton
+@Named("m2e")
+public class M2eEventSpy implements EventSpy {
+
+ private M2EMavenBuildDataBridge bridge;
+
+ @Inject
+ public M2eEventSpy(M2EMavenBuildDataBridge bridge) {
+ this.bridge = bridge;
+ }
+
+ @Override
+ public void init(Context context) throws Exception {
+
+ }
+
+ @Override
+ public void onEvent(Object event) throws Exception {
+ if (bridge.isActive()) {
+ if (event instanceof ExecutionEvent) {
+ ExecutionEvent executionEvent = (ExecutionEvent) event;
+ if (executionEvent.getType() == Type.ProjectStarted) {
+ String message = MavenProjectBuildData.serializeProjectData(((ExecutionEvent) event).getProject());
+ bridge.sendMessage(message);
+ }
+ }
+ }
+ }
+
+ @Override
+ public void close() throws Exception {
+
+ }
+
+}
diff --git a/org.eclipse.m2e.maven.runtime/src/main/java/org/eclipse/m2e/internal/maven/listener/MavenBuildConnection.java b/org.eclipse.m2e.maven.runtime/src/main/java/org/eclipse/m2e/internal/maven/listener/MavenBuildConnection.java
new file mode 100644
index 000000000..de5abb591
--- /dev/null
+++ b/org.eclipse.m2e.maven.runtime/src/main/java/org/eclipse/m2e/internal/maven/listener/MavenBuildConnection.java
@@ -0,0 +1,46 @@
+/********************************************************************************
+ * 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 - factor out into dedicated component
+ ********************************************************************************/
+package org.eclipse.m2e.internal.maven.listener;
+
+import java.io.IOException;
+import java.nio.channels.ServerSocketChannel;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+public final class MavenBuildConnection {
+ private final ServerSocketChannel server;
+ private final AtomicBoolean closed = new AtomicBoolean(false);
+ private MavenBuildConnectionListener listener;
+
+ MavenBuildConnection(ServerSocketChannel server, MavenBuildConnectionListener listener) {
+ this.server = server;
+ this.listener = listener;
+ }
+
+ public boolean isCompleted() {
+ return closed.get();
+ }
+
+ public void close() {
+ if (closed.compareAndSet(false, true)) {
+ listener.onClose();
+ // Close the server to ensure the reader-thread does not wait forever for a
+ // connection from the Maven-process in case something went wrong during
+ // launching or while setting up the connection.
+ try {
+ server.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/org.eclipse.m2e.maven.runtime/src/main/java/org/eclipse/m2e/internal/maven/listener/MavenBuildConnectionListener.java b/org.eclipse.m2e.maven.runtime/src/main/java/org/eclipse/m2e/internal/maven/listener/MavenBuildConnectionListener.java
new file mode 100644
index 000000000..5141f0302
--- /dev/null
+++ b/org.eclipse.m2e.maven.runtime/src/main/java/org/eclipse/m2e/internal/maven/listener/MavenBuildConnectionListener.java
@@ -0,0 +1,23 @@
+/********************************************************************************
+ * 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.maven.listener;
+
+public interface MavenBuildConnectionListener {
+
+ void onOpen(String label, MavenBuildConnection connection);
+
+ void onClose();
+
+ void onData(MavenProjectBuildData buildData);
+
+}
diff --git a/org.eclipse.m2e.maven.runtime/src/main/java/org/eclipse/m2e/internal/maven/listener/MavenProjectBuildData.java b/org.eclipse.m2e.maven.runtime/src/main/java/org/eclipse/m2e/internal/maven/listener/MavenProjectBuildData.java
new file mode 100644
index 000000000..befa0e524
--- /dev/null
+++ b/org.eclipse.m2e.maven.runtime/src/main/java/org/eclipse/m2e/internal/maven/listener/MavenProjectBuildData.java
@@ -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 - factor out into dedicated component
+ ********************************************************************************/
+package org.eclipse.m2e.internal.maven.listener;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.StringJoiner;
+
+import org.apache.maven.project.MavenProject;
+
+public final class MavenProjectBuildData {
+ public final String groupId;
+ public final String artifactId;
+ public final String version;
+ public final Path projectBasedir;
+ public final Path projectFile;
+ public final Path projectBuildDirectory;
+
+ MavenProjectBuildData(Map data) {
+ if (data.size() != 6) {
+ throw new IllegalArgumentException();
+ }
+ this.groupId = Objects.requireNonNull(data.get("groupId"));
+ this.artifactId = Objects.requireNonNull(data.get("artifactId"));
+ this.version = Objects.requireNonNull(data.get("version"));
+ this.projectBasedir = Paths.get(data.get("basedir"));
+ this.projectFile = Paths.get(data.get("file"));
+ this.projectBuildDirectory = Paths.get(data.get("build.directory"));
+ }
+
+ /**
+ *
+ * This method is supposed to be called from M2E within the Eclipse-IDE JVM.
+ *
+ *
+ * @param dataSet the data-set to parse
+ * @return the {@link MavenProjectBuildData} parsed from the given string
+ */
+ static MavenProjectBuildData parseMavenBuildProject(String dataSet) {
+ Map data = new HashMap<>(8);
+ for (String entry : dataSet.split(",")) {
+ String[] keyValue = entry.split("=");
+ if (keyValue.length != 2) {
+ throw new IllegalStateException("Invalid data-set format" + dataSet);
+ }
+ data.put(keyValue[0], keyValue[1]);
+ }
+ return new MavenProjectBuildData(data);
+ }
+
+ static String serializeProjectData(MavenProject project) {
+ StringJoiner data = new StringJoiner(",");
+ add(data, "groupId", project.getGroupId());
+ add(data, "artifactId", project.getArtifactId());
+ add(data, "version", project.getVersion());
+ add(data, "file", project.getFile());
+ add(data, "basedir", project.getBasedir());
+ add(data, "build.directory", project.getBuild().getDirectory());
+ return data.toString();
+ }
+
+ private static void add(StringJoiner data, String key, Object value) {
+ data.add(key + "=" + value);
+ }
+}
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 4950bcd1b..c39883b38 100644
--- a/pom.xml
+++ b/pom.xml
@@ -103,7 +103,7 @@
org.eclipse.m2e
org.eclipse.m2e.maven.runtime
- 3.9.600-SNAPSHOT
+ 3.9.601-SNAPSHOT