diff --git a/README.md b/README.md
index 6af0dde..13b8f54 100644
--- a/README.md
+++ b/README.md
@@ -7,19 +7,76 @@ Plexus Build API
This API allows IDEs to integrate with Maven deeper than it would be possible by just using regular Maven/Mojo API.
+## Marker and File Delta support
It supports
- incremental builds e.g. allows to query which files have been touched since last build
- fine-grained error/info markers (referring to specific files in particular line numbers)
- notifications about updated files
+## Process support
+
+This API is located in the package `org.codehaus.plexus.build.process` and allows the IDE to interact with a mojo that starts new processes and has the following purposes:
+
+- allow representation of processes in the UI e.g with a name and its current state together with a way to optionally terminate a running process
+- optionally decorate the process dependeing on the use case e.g. add additional environment variables, supply classpath entries or provide listeners
+
+The main entry point for this is the `ProcessContext` that can be injected in a mojo in the follwoing way:
+
+```
+public MyMojo extends AbstractMojo {
+
+ @Component
+ private ProcessManager processContext;
+
+ public void execute() {
+
+ ProcessContext context = ...
+
+ BuildProcess process = processContext.newProcess(context);
+ }
+}
+```
+
+As one can see we have a `ProcessManager` that is capable of creating a Process for the user to see it in the IDE and the `BuildProcess` can be used to notify the IDE about process changes, e.g. if it is terminated.
+There is also a `ProcessContext` passed to the call that allow the mojo to supply basic information like the name or if it can be terminated but also can implements different callbacks that might (or might not) be called to furhter decorate the process.
+The follwoing callbacks are currently supported:
+
+### ProcessCallback
+
+`ProcessCallback` are quite bare callback that allow to request for adding (or replacing) an environment variable with `ProcessCallback#setEnvironmentVariable`,
+any context that support should implement the interface. Even though a request is made it could be reqjected, e.g because the context don't allow this because
+it uses a variable with the same name already and don'T want to replace it.
+
+A basic implementation of this is provided with `ProcessBuilderContext` what implements this using a ProcessBuilder, so if processes are currently implemented that way it can be reused.
+
+### JavaCallback
+
+`JavaCallback` offers specialized way to add options to a launch that is running in a JVM (either directly or forked). The possible callbacks are
+
+- setSystemProperty for requesting to add (or replace) a system property
+- setVMOption for requesting to add (or replace) a VM option
+- addClasspathEntry for requesting to add a new jar on the classpath
+
+There is currently no implementation added here but one can reuse `ProcessBuilderContext` for performin neccesary actions.
+
+### JUnitCallback
+
+`JUnitCallback` offer specialized option to a launch that is executing test using JUnit framework. The possible callbacks are
+
+- addTestClasspathEntry for requesting to add a new jar on the test classpath
+- addTestExecutionListener for reuqest to add a new listener that is notified about test events
+- getJUnitVersion allows to query for the used JUnit version
Current Implementations
-----
### Default Implementation
-The default implementation shipping with this artifact is supposed to impose minimal overhead. It doesn't support incremental build and acts directly on the file system. Errors and warning are just logged through SLF4J.
+- Marker and File Delta support is supposed to impose minimal overhead. It doesn't support incremental build and acts directly on the file system. Errors and warning are just logged through SLF4J.
+- Process support is simply a no-op, it never will call any callbacks and just discards the name, all calls on the listener will simply do nothing
+
+## Process support
### M2Eclipse
diff --git a/pom.xml b/pom.xml
index 6ecef5d..3306d62 100644
--- a/pom.xml
+++ b/pom.xml
@@ -21,7 +21,7 @@ See the Apache License Version 2.0 for the specific language governing permissio
plexus-build-api
- 1.2.1-SNAPSHOT
+ 1.3.0-SNAPSHOT
scm:git:https://github.com/codehaus-plexus/plexus-build-api.git
diff --git a/src/main/java/org/codehaus/plexus/build/process/BuildProcess.java b/src/main/java/org/codehaus/plexus/build/process/BuildProcess.java
new file mode 100644
index 0000000..bab6867
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/build/process/BuildProcess.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2024 Christoph Läubrich
+ *
+ * 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.codehaus.plexus.build.process;
+
+/**
+ * A {@link BuildProcess} represents a process created inside a maven execution
+ * that performs a specialized task and can be represented as something other
+ * than a mojo executions, for example a mojo that executes tests in a forked VM
+ * can handle multiple forks in one invocation. Also a process allows to be
+ * controlled from the outside, e.g. the user can request to terminate it.
+ */
+public interface BuildProcess {
+
+ /**
+ * @return the name of the process
+ */
+ String getName();
+
+ /**
+ * Notify the manager that the given process was started
+ */
+ void notifyStarted();
+
+ /**
+ * @return true if the process is requested to terminate or has already
+ * terminated.
+ */
+ boolean isTerminated();
+
+ /**
+ * Notify the manager that the given process has finished with the given exit
+ * code where an exit code of zero usually indicates a successful termination
+ *
+ * @param exitcode
+ */
+ void notifyFinished(int exitcode);
+}
diff --git a/src/main/java/org/codehaus/plexus/build/process/BuildProcessContext.java b/src/main/java/org/codehaus/plexus/build/process/BuildProcessContext.java
new file mode 100644
index 0000000..be37dcb
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/build/process/BuildProcessContext.java
@@ -0,0 +1,43 @@
+/*
+ * Copyright 2024 Christoph Läubrich
+ *
+ * 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.codehaus.plexus.build.process;
+
+/**
+ * A {@link BuildProcessContext} is used to create a {@link BuildProcess}, it
+ * can implement any number of specialized callbacks that allow to further
+ * customize the about to executed process, that allows IDEs to install
+ * additional code to track progress or getting notified about results.
+ */
+public interface BuildProcessContext {
+
+ /**
+ * Provides the name of process that is created, this is something that might be
+ * presented to the user in an IDE
+ *
+ * @return the name
+ */
+ String getName();
+
+ /**
+ * Determines if termination of this process is possible, an IDE will possibly
+ * present a way to terminate an individual process. A request to terminate the
+ * process is then reflected in the process but it is the responsibility of the
+ * implementation to act on it.
+ *
+ * @return true
+ */
+ boolean canTerminate();
+}
diff --git a/src/main/java/org/codehaus/plexus/build/process/JUnitCallback.java b/src/main/java/org/codehaus/plexus/build/process/JUnitCallback.java
new file mode 100644
index 0000000..b9873bf
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/build/process/JUnitCallback.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2024 Christoph Läubrich
+ *
+ * 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.codehaus.plexus.build.process;
+
+import java.nio.file.Path;
+
+/**
+ * Callback targeting a JUnit execution.
+ */
+public interface JUnitCallback {
+
+ enum JUnitVersion {
+ JUNIT3,
+ JUNIT4,
+ JUNIT5;
+ }
+
+ /**
+ * Request to add a new classpath entry to the junit execution, this might
+ * contain additional classes needed to perform some actions.
+ *
+ * @param extraTestClasspath the extra classpath element
+ *
+ * @return true
if the request was accepted, false
+ * otherwise.
+ */
+ boolean addTestClasspathEntry(Path extraTestClasspath);
+
+ /**
+ * Request to add a new TestExecutionListener specified by the full qualified
+ * class name, this must either be a default one or one that can be loaded by
+ * the extra test classpath added before.
+ *
+ * @param fqcn full qualified classname of the listener implementation
+ * @return true
if the listener was accepted, false
+ * otherwise.
+ */
+ boolean addTestExecutionListener(String fqcn);
+
+ /**
+ * @return the version of JUnit that will be executed
+ */
+ JUnitVersion getJUnitVersion();
+}
diff --git a/src/main/java/org/codehaus/plexus/build/process/JavaCallback.java b/src/main/java/org/codehaus/plexus/build/process/JavaCallback.java
new file mode 100644
index 0000000..f424547
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/build/process/JavaCallback.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2024 Christoph Läubrich
+ *
+ * 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.codehaus.plexus.build.process;
+
+import java.nio.file.Path;
+
+/**
+ * A callback for a context that is working around java processes to be started,
+ * a {@link BuildProcessContext} should implement this if it allows to further
+ * customize a process that is running a java VM. Depending on the launch type
+ * (e.g embedded or forked) some options might not be possible and can maybe
+ * rejected.
+ */
+public interface JavaCallback {
+
+ /**
+ * Request to add a system property to the launch.
+ *
+ * @param key the key
+ * @param value the value
+ * @return true
if the request was accepted, false otherwise.
+ */
+ boolean setSystemProperty(String key, String value);
+
+ /**
+ * Request to add a VM option to the launch.
+ *
+ * @param option the VM option to add
+ * @param value the value or null
if this option has no value
+ * @return true
if the request was accepted, false otherwise.
+ */
+ boolean setVMOption(String option, String value);
+
+ /**
+ * Request to add a new classpath entry to the launch
+ *
+ * @param extraClasspath the extra classpath element
+ *
+ * @return true
if the request was accepted, false otherwise.
+ */
+ boolean addClasspathEntry(Path extraClasspath);
+}
diff --git a/src/main/java/org/codehaus/plexus/build/process/ProcessCallback.java b/src/main/java/org/codehaus/plexus/build/process/ProcessCallback.java
new file mode 100644
index 0000000..3e8da59
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/build/process/ProcessCallback.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright 2024 Christoph Läubrich
+ *
+ * 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.codehaus.plexus.build.process;
+
+/**
+ * A {@link ProcessCallback} can be implemented by a context if it is able to
+ * accept additional environment variables to be set on a process they create.
+ */
+public interface ProcessCallback {
+
+ /**
+ * Request to set an additional environment variable, the context provider is
+ * free to reject the request
+ *
+ * @param variable
+ * @param value
+ * @return true
if the context accepted the request and will add
+ * the environment variable to the launch, false otherwise.
+ */
+ boolean setEnvironmentVariable(String variable, String value);
+}
diff --git a/src/main/java/org/codehaus/plexus/build/process/ProcessManager.java b/src/main/java/org/codehaus/plexus/build/process/ProcessManager.java
new file mode 100644
index 0000000..1584fbb
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/build/process/ProcessManager.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright 2024 Christoph Läubrich
+ *
+ * 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.codehaus.plexus.build.process;
+
+/**
+ * The {@link ProcessManager} is responsible for connecting a process created by
+ * a mojo (usually a forked one but thats not required) to the IDE and allows
+ * some visual representation but also some customization using callbacks.
+ */
+public interface ProcessManager {
+
+ /**
+ * Create a new {@link BuildProcess} given the {@link BuildProcessContext}
+ * calling any supported callbacks.
+ *
+ * @param context the context to use
+ * @return the created {@link BuildProcess} that can be used to further control
+ * the process e.g inform about termination or null
if no
+ * process can be created, for example this can happen because required
+ * callbacks are not supported for this kind of launch.
+ */
+ BuildProcess newProcess(BuildProcessContext context);
+}
diff --git a/src/main/java/org/codehaus/plexus/build/process/impl/DefaultProcessManager.java b/src/main/java/org/codehaus/plexus/build/process/impl/DefaultProcessManager.java
new file mode 100644
index 0000000..ab6572e
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/build/process/impl/DefaultProcessManager.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2024 Christoph Läubrich
+ *
+ * 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.codehaus.plexus.build.process.impl;
+
+import javax.inject.Named;
+
+import java.util.Objects;
+
+import org.codehaus.plexus.build.process.BuildProcess;
+import org.codehaus.plexus.build.process.BuildProcessContext;
+import org.codehaus.plexus.build.process.ProcessManager;
+
+/**
+ * The default implementation of a {@link ProcessManager} always return
+ * null
from its {@link #newProcess(BuildProcessContext)} method
+ * regardless of what is passed in and only checks for null
.
+ */
+@Named
+public final class DefaultProcessManager implements ProcessManager {
+
+ @Override
+ public BuildProcess newProcess(BuildProcessContext context) {
+ Objects.requireNonNull(context);
+ return null;
+ }
+}
diff --git a/src/main/java/org/codehaus/plexus/build/process/impl/ProcessBuilderContext.java b/src/main/java/org/codehaus/plexus/build/process/impl/ProcessBuilderContext.java
new file mode 100644
index 0000000..7333143
--- /dev/null
+++ b/src/main/java/org/codehaus/plexus/build/process/impl/ProcessBuilderContext.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2024 Christoph Läubrich
+ *
+ * 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.codehaus.plexus.build.process.impl;
+
+import java.io.IOException;
+import java.util.concurrent.TimeUnit;
+
+import org.codehaus.plexus.build.process.BuildProcess;
+import org.codehaus.plexus.build.process.BuildProcessContext;
+import org.codehaus.plexus.build.process.ProcessCallback;
+
+/**
+ * A simple implementation that uses a {@link ProcessBuilder} to fork a
+ * childprocess and informs the {@link BuildProcess} about its execution and
+ * outcome.
+ */
+public class ProcessBuilderContext implements ProcessCallback, BuildProcessContext {
+
+ private String name;
+ private boolean allowTermination;
+ private ProcessBuilder builder;
+
+ public ProcessBuilderContext(String name, boolean allowTermination, ProcessBuilder builder) {
+ this.name = name;
+ this.allowTermination = allowTermination;
+ this.builder = builder;
+ }
+
+ @Override
+ public boolean setEnvironmentVariable(String variable, String value) {
+ builder.environment().put(variable, value);
+ return true;
+ }
+
+ @Override
+ public String getName() {
+ return name;
+ }
+
+ @Override
+ public boolean canTerminate() {
+ return allowTermination;
+ }
+
+ /**
+ * Starts a new {@link Process} using the {@link ProcessBuilder} and notify the
+ * given {@link BuildProcess}.
+ *
+ * @param buildProcess the build process to notify or null
if no
+ * further notification is desired.
+ * @return the process started.
+ * @throws IOException if starting the process failed.
+ */
+ public Process start(BuildProcess buildProcess) throws IOException {
+ Process process = builder.start();
+ if (buildProcess != null) {
+ buildProcess.notifyStarted();
+ Thread watcher = new Thread(new Runnable() {
+
+ @Override
+ public void run() {
+ try {
+ if (allowTermination) {
+ do {
+ if (buildProcess.isTerminated()) {
+ // request termination
+ process.destroy();
+ break;
+ }
+ } while (!process.waitFor(200, TimeUnit.MILLISECONDS));
+ }
+ buildProcess.notifyFinished(process.waitFor());
+ } catch (InterruptedException e) {
+ return;
+ }
+ }
+ });
+ watcher.setName("Watcher thread for build process " + buildProcess.getName());
+ watcher.setDaemon(true);
+ watcher.start();
+ }
+ return process;
+ }
+}