diff --git a/.gitignore b/.gitignore
index 1b79e74af..b25ebb84d 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,6 +5,7 @@ pom.xml.releaseBackup
pom.xml.versionsBackup
pom.xml.next
release.properties
+dependency-reduced-pom.xml
# Eclipse
.project
diff --git a/agent/pom.xml b/agent/pom.xml
new file mode 100644
index 000000000..bf45d610b
--- /dev/null
+++ b/agent/pom.xml
@@ -0,0 +1,81 @@
+
+
+
+ 4.0.0
+
+ org.mvndaemon.mvnd
+ mvnd
+ 0.2.1-SNAPSHOT
+
+
+ mvnd-agent
+
+ jar
+ Maven Daemon - Agent
+
+
+
+
+ org.javassist
+ javassist
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-jar-plugin
+
+
+
+ org.mvndaemon.mvnd.agent.Agent
+ mvnd-helper-agent-${project.version}.jar
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+
+
+ package
+
+ shade
+
+
+
+
+ org.javassist:javassist
+
+ META-INF/MANIFEST.MF
+
+
+
+
+
+
+
+
+
+
+
diff --git a/agent/src/main/java/org/mvndaemon/mvnd/agent/Agent.java b/agent/src/main/java/org/mvndaemon/mvnd/agent/Agent.java
new file mode 100644
index 000000000..3c33984ad
--- /dev/null
+++ b/agent/src/main/java/org/mvndaemon/mvnd/agent/Agent.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright 2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.mvndaemon.mvnd.agent;
+
+import java.lang.instrument.ClassFileTransformer;
+import java.lang.instrument.IllegalClassFormatException;
+import java.lang.instrument.Instrumentation;
+import java.security.ProtectionDomain;
+import javassist.ClassPool;
+import javassist.CtClass;
+
+public class Agent {
+
+ public static final String START_WITH_PIPES = "if (redirects != null\n"
+ + " && redirects[1] == ProcessBuilder$Redirect.INHERIT\n"
+ + " && redirects[2] == ProcessBuilder$Redirect.INHERIT) {\n"
+ + " redirects[1] = redirects[2] = ProcessBuilder$Redirect.PIPE;"
+ + " Process p = start(redirects);\n"
+ + " AgentHelper.pump(p.getInputStream(), System.out);\n"
+ + " AgentHelper.pump(p.getErrorStream(), System.err);\n"
+ + " return p;\n"
+ + "}";
+
+ public static void premain(String args, Instrumentation instrumentation) throws Exception {
+ instrumentation.addTransformer(new ClassFileTransformer() {
+ @Override
+ public byte[] transform(ClassLoader loader, String className, Class> classBeingRedefined,
+ ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
+ if ("java/lang/ProcessBuilder".equals(className)) {
+ try {
+ ClassPool pool = ClassPool.getDefault();
+ CtClass clazz = pool.get("java.lang.ProcessBuilder");
+ pool.importPackage("org.mvndaemon.mvnd.pump");
+ clazz.getDeclaredMethod("start",
+ new CtClass[] { clazz.getClassPool().get("java.lang.ProcessBuilder$Redirect[]") })
+ .insertBefore(START_WITH_PIPES);
+ byte[] data = clazz.toBytecode();
+ clazz.detach();
+ return data;
+ } catch (Throwable e) {
+ System.err.println(e);
+ throw new IllegalClassFormatException(e.toString());
+ }
+ } else {
+ return classfileBuffer;
+ }
+ }
+ });
+ }
+
+}
diff --git a/client/src/main/java/org/mvndaemon/mvnd/client/DaemonConnector.java b/client/src/main/java/org/mvndaemon/mvnd/client/DaemonConnector.java
index 74963bb14..d9db5f76f 100644
--- a/client/src/main/java/org/mvndaemon/mvnd/client/DaemonConnector.java
+++ b/client/src/main/java/org/mvndaemon/mvnd/client/DaemonConnector.java
@@ -1,5 +1,5 @@
/*
- * Copyright 2011 the original author or authors.
+ * Copyright 2011-2021 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,10 +15,12 @@
*/
package org.mvndaemon.mvnd.client;
+import java.io.File;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.nio.channels.SocketChannel;
+import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collection;
@@ -32,7 +34,6 @@
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
-import org.mvndaemon.mvnd.common.BuildProperties;
import org.mvndaemon.mvnd.common.DaemonCompatibilitySpec;
import org.mvndaemon.mvnd.common.DaemonCompatibilitySpec.Result;
import org.mvndaemon.mvnd.common.DaemonConnection;
@@ -300,10 +301,27 @@ private Process startDaemon(String uid) {
final String java = Os.current().isUnixLike() ? "bin/java" : "bin\\java.exe";
args.add(parameters.javaHome().resolve(java).toString());
// classpath
+ String mvndCommonPath = null;
+ String mvndAgentPath = null;
+ for (Path jar : Files.newDirectoryStream(mvndHome.resolve("mvn/lib/ext"))) {
+ String s = jar.getFileName().toString();
+ if (s.endsWith(".jar")) {
+ if (s.startsWith("mvnd-common-")) {
+ mvndCommonPath = jar.toString();
+ } else if (s.startsWith("mvnd-agent-")) {
+ mvndAgentPath = jar.toString();
+ }
+ }
+ }
+ if (mvndCommonPath == null) {
+ throw new IllegalStateException("Could not find mvnd-common jar in mvn/lib/ext/");
+ }
+ if (mvndAgentPath == null) {
+ throw new IllegalStateException("Could not find mvnd-agent jar in mvn/lib/ext/");
+ }
args.add("-classpath");
- final String mvndCommonPath = "mvn/lib/ext/mvnd-common-" + BuildProperties.getInstance().getVersion() + ".jar";
- final String classpath = mvndHome.resolve(mvndCommonPath).toString();
- args.add(classpath);
+ args.add(mvndCommonPath + File.pathSeparator + mvndAgentPath);
+ args.add("-javaagent:" + mvndAgentPath);
// debug options
if (parameters.property(Environment.MVND_DEBUG).asBoolean()) {
args.add("-agentlib:jdwp=transport=dt_socket,server=y,suspend=y,address=8000");
diff --git a/dist/pom.xml b/dist/pom.xml
index a68d64620..6c835adde 100644
--- a/dist/pom.xml
+++ b/dist/pom.xml
@@ -1,6 +1,6 @@
+
+
+ 4.0.0
+
+ org.mvndaemon.mvnd
+ mvnd
+ 0.2.1-SNAPSHOT
+
+
+ mvnd-helper-agent
+
+ jar
+ Maven Daemon - Helper Agent
+
+
diff --git a/helper/src/main/java/org/mvndaemon/mvnd/pump/AgentHelper.java b/helper/src/main/java/org/mvndaemon/mvnd/pump/AgentHelper.java
new file mode 100644
index 000000000..b1d916f67
--- /dev/null
+++ b/helper/src/main/java/org/mvndaemon/mvnd/pump/AgentHelper.java
@@ -0,0 +1,29 @@
+/*
+ * Copyright 2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.mvndaemon.mvnd.pump;
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.PrintStream;
+
+public class AgentHelper {
+
+ public static void pump(InputStream stream, PrintStream out) {
+ new Thread(() -> new BufferedReader(new InputStreamReader(stream)).lines().forEach(out::println)).start();
+ }
+
+}
diff --git a/integration-tests/src/test/java/org/mvndaemon/mvnd/it/JUnitPlatformTest.java b/integration-tests/src/test/java/org/mvndaemon/mvnd/it/JUnitPlatformTest.java
new file mode 100644
index 000000000..bbe28a92a
--- /dev/null
+++ b/integration-tests/src/test/java/org/mvndaemon/mvnd/it/JUnitPlatformTest.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.mvndaemon.mvnd.it;
+
+import javax.inject.Inject;
+import org.junit.jupiter.api.Test;
+import org.mvndaemon.mvnd.assertj.TestClientOutput;
+import org.mvndaemon.mvnd.client.Client;
+import org.mvndaemon.mvnd.client.DaemonParameters;
+import org.mvndaemon.mvnd.common.Message;
+import org.mvndaemon.mvnd.junit.MvndTest;
+
+import static junit.framework.Assert.assertTrue;
+
+@MvndTest(projectDir = "src/test/projects/junit-platform")
+public class JUnitPlatformTest {
+
+ @Inject
+ Client client;
+
+ @Inject
+ DaemonParameters parameters;
+
+ @Test
+ void cleanTestInheritIO() throws InterruptedException {
+
+ final TestClientOutput output = new TestClientOutput();
+ client.execute(output, "clean", "test", "-e", "-Dmvnd.log.level=DEBUG").assertSuccess();
+ assertHasTestMessage(output);
+
+ }
+
+ private void assertHasTestMessage(final TestClientOutput output) {
+ assertTrue(output.getMessages().stream()
+ .filter(Message.ProjectEvent.class::isInstance)
+ .map(Message.ProjectEvent.class::cast)
+ .anyMatch(it -> it.getMessage().contains("[stdout] From test")));
+ }
+}
diff --git a/integration-tests/src/test/projects/junit-platform/.mvn/maven.config b/integration-tests/src/test/projects/junit-platform/.mvn/maven.config
new file mode 100644
index 000000000..4230c2417
--- /dev/null
+++ b/integration-tests/src/test/projects/junit-platform/.mvn/maven.config
@@ -0,0 +1,3 @@
+-Dmaven.wagon.httpconnectionManager.ttlSeconds=120
+-Dmaven.wagon.http.retryHandler.requestSentEnabled=true
+-Dmaven.wagon.http.retryHandler.count=10
diff --git a/integration-tests/src/test/projects/junit-platform/pom.xml b/integration-tests/src/test/projects/junit-platform/pom.xml
new file mode 100644
index 000000000..f54bac2b1
--- /dev/null
+++ b/integration-tests/src/test/projects/junit-platform/pom.xml
@@ -0,0 +1,109 @@
+
+
+
+ 4.0.0
+ org.mvndaemon.mvnd.test.exec-output
+ jp-output
+ 0.0.1-SNAPSHOT
+ jar
+
+
+ UTF-8
+ 1.8
+ 1.8
+
+ 2.5
+ 3.8.0
+ 2.4
+ 2.6
+ 2.22.2
+ 3.0.0
+
+
+
+
+ org.junit.jupiter
+ junit-jupiter
+ 5.7.0
+ test
+
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-clean-plugin
+ ${maven-clean-plugin.version}
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ ${maven-compiler-plugin.version}
+
+
+ org.apache.maven.plugins
+ maven-install-plugin
+ ${maven-install-plugin.version}
+
+
+ org.apache.maven.plugins
+ maven-resources-plugin
+ ${maven-resources-plugin.version}
+
+
+ org.apache.maven.plugins
+ maven-surefire-plugin
+ ${maven-surefire-plugin.version}
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ ${exec-maven-plugin.version}
+
+
+
+
+
+
+ de.sormuras.junit
+ junit-platform-maven-plugin
+ 1.1.0
+ true
+
+ NONE
+ JAVA
+
+ true
+
+ --disable-banner
+
+
+
+ false
+ flat
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/integration-tests/src/test/projects/junit-platform/src/test/java/org/mvndaemon/mvnd/test/GreetingTest.java b/integration-tests/src/test/projects/junit-platform/src/test/java/org/mvndaemon/mvnd/test/GreetingTest.java
new file mode 100644
index 000000000..012b2c45f
--- /dev/null
+++ b/integration-tests/src/test/projects/junit-platform/src/test/java/org/mvndaemon/mvnd/test/GreetingTest.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2021 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.mvndaemon.mvnd.test;
+
+import org.junit.jupiter.api.Test;
+
+class GreetingTest {
+
+ @Test
+ void run() {
+ System.out.println("From test");
+ }
+
+}
diff --git a/pom.xml b/pom.xml
index 0377ae19b..533d206fc 100644
--- a/pom.xml
+++ b/pom.xml
@@ -1,6 +1,6 @@
1.3.1
1.13.9
1.0.15
+ 3.27.0-GA
build-plugin
+ agent
+ helper
common
client
daemon
@@ -169,6 +173,11 @@
${assertj.version}
+
+ org.mvndaemon.mvnd
+ mvnd-agent
+ 0.2.1-SNAPSHOT
+
org.mvndaemon.mvnd
mvnd-client
@@ -190,6 +199,11 @@
mvnd-daemon
0.2.1-SNAPSHOT
+
+ org.mvndaemon.mvnd
+ mvnd-helper-agent
+ 0.2.1-SNAPSHOT
+
org.jline
@@ -223,6 +237,12 @@
${slf4j.version}
+
+ org.javassist
+ javassist
+ ${javassist.version}
+
+
@@ -341,6 +361,11 @@ limitations under the License.
maven-install-plugin
${maven-install-plugin.version}
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ ${maven-shade-plugin.version}
+
org.codehaus.gmaven
groovy-maven-plugin