Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for a process API #79

Draft
wants to merge 1 commit into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 58 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ See the Apache License Version 2.0 for the specific language governing permissio
</parent>

<artifactId>plexus-build-api</artifactId>
<version>1.2.1-SNAPSHOT</version>
<version>1.3.0-SNAPSHOT</version>

<scm>
<connection>scm:git:https://github.com/codehaus-plexus/plexus-build-api.git</connection>
Expand Down
50 changes: 50 additions & 0 deletions src/main/java/org/codehaus/plexus/build/process/BuildProcess.java
Original file line number Diff line number Diff line change
@@ -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);
}
Original file line number Diff line number Diff line change
@@ -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 <code>true</code>
*/
boolean canTerminate();
}
57 changes: 57 additions & 0 deletions src/main/java/org/codehaus/plexus/build/process/JUnitCallback.java
Original file line number Diff line number Diff line change
@@ -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 <code>true</code> if the request was accepted, <code>false</code>
* 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 <code>true</code> if the listener was accepted, <code>false</code>
* otherwise.
*/
boolean addTestExecutionListener(String fqcn);

/**
* @return the version of JUnit that will be executed
*/
JUnitVersion getJUnitVersion();
}
55 changes: 55 additions & 0 deletions src/main/java/org/codehaus/plexus/build/process/JavaCallback.java
Original file line number Diff line number Diff line change
@@ -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 <code>true</code> 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 <code>null</code> if this option has no value
* @return <code>true</code> 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 <code>true</code> if the request was accepted, false otherwise.
*/
boolean addClasspathEntry(Path extraClasspath);
}
Original file line number Diff line number Diff line change
@@ -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 <code>true</code> if the context accepted the request and will add
* the environment variable to the launch, false otherwise.
*/
boolean setEnvironmentVariable(String variable, String value);
}
Original file line number Diff line number Diff line change
@@ -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 <code>null</code> 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);
}
Loading