Skip to content

Commit

Permalink
Support adding plugin managed by parent
Browse files Browse the repository at this point in the history
  • Loading branch information
andirady committed Aug 4, 2024
1 parent 2355e5b commit 4367d92
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 4 deletions.
16 changes: 16 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,22 @@ $ pom plug maven-resources-plugin
🔌 org.apache.maven.plugins:maven-resources-plugin:1.0.0 plugged
```

If the current POM is a child of another POM, you can add a plugin
by simply stating the plugin's artifact ID.
```
$ # Add plugin managed by parent
$ pom plug spring-boot-maven-plugin
🔌 org.springframework.boot:spring-boot-maven-plugin:1.0.0 plugged
```
or, if you're starting with an empty project, you can run
```
pom parent parent.group:parent.artifactId:1.0.0 plug example-maven-plugin
```
e.g.:
```
pom parent org.springframework.boot:spring-boot-starter-parent plug spring-boot-maven-plugin
```

## Building

This project requires Java 21+, GraalVM CE and Maven 3.8.4+.
Expand Down
43 changes: 40 additions & 3 deletions src/main/java/com/github/andirady/pomcli/AddPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,23 @@
*/
package com.github.andirady.pomcli;

import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Stream;

import org.apache.maven.model.Build;
import org.apache.maven.model.BuildBase;
import org.apache.maven.model.Model;
import org.apache.maven.model.Parent;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.PluginContainer;
import org.apache.maven.model.PluginManagement;
import org.apache.maven.model.Profile;

public class AddPlugin {

private static final int MAX_RECURSION = 10;
private final String profileId;

public AddPlugin() {
Expand All @@ -36,15 +44,16 @@ public AddPlugin(String profileId) {

public Plugin addPlugin(Model model, String artifactId) {
var plugin = new Plugin();
new Profile();
plugin.setArtifactId(artifactId);
return addPlugin(model, plugin);
}

public Plugin addPlugin(Model model, Plugin plugin) {
if (plugin.getVersion() == null) {
var query = new QuerySpec(plugin.getGroupId(), plugin.getArtifactId(), null);
plugin.setVersion(new GetLatestVersion().execute(query).orElseThrow());
if (!resolvePluginManagement(model, plugin, 0)) {
var query = new QuerySpec(plugin.getGroupId(), plugin.getArtifactId(), null);
plugin.setVersion(new GetLatestVersion().execute(query).orElseThrow());
}
}

BuildBase build = switch (profileId) {
Expand Down Expand Up @@ -88,4 +97,32 @@ public Plugin addPlugin(Model model, Plugin plugin) {
return plugin;
}

private boolean resolvePluginManagement(Model model, Plugin plugin, int loopIndex) {
if (!(model.getParent() instanceof Parent parent)) {
return false;
}

var parentModel = ResolutionProvider.getInstance().readModel(parent.getGroupId(), parent.getArtifactId(),
parent.getVersion());
var managed = Optional.ofNullable(parentModel.getBuild())
.map(Build::getPluginManagement)
.filter(Objects::nonNull)
.map(PluginManagement::getPlugins).map(List::stream)
.orElseGet(Stream::of)
.filter(p -> p.getArtifactId().equals(plugin.getArtifactId()))
.findFirst()
.orElse(null);

if (managed != null) {
plugin.setGroupId(managed.getGroupId());
return true;
}

if (++loopIndex > MAX_RECURSION) {
throw new IllegalStateException("Exceeded max recursion of " + MAX_RECURSION);
}

return resolvePluginManagement(parentModel, plugin, loopIndex);
}

}
26 changes: 25 additions & 1 deletion src/test/java/com/github/andirady/pomcli/PlugCommandTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,11 @@
*/
package com.github.andirady.pomcli;

import static java.nio.file.Files.writeString;
import static org.junit.jupiter.api.Assertions.assertSame;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;

import org.junit.jupiter.api.AfterEach;
Expand All @@ -33,7 +36,7 @@ class PlugCommandTest extends BaseTest {
@TempDir
Path tempDir;

@BeforeEach
@BeforeEach
void setup() {
var app = new Main();
underTest = new CommandLine(app);
Expand All @@ -59,4 +62,25 @@ void basicUse(String input, String subexpr) throws Exception {
var expr = "/project/build/plugins/plugin[" + subexpr + "]";
assertXpath(pomPath, expr, 1);
}

@ParameterizedTest
@CsvSource(quoteCharacter = '`', textBlock = """
`<project>
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.1</version>
</parent>
<artifactId>hello</artifactId>
</project>`, spring-boot-maven-plugin""")
void supportsManagedPlugin(String pomContent, String input) throws IOException {
var pomPath = writeString(tempDir.resolve("pom.xml"), pomContent);

var ec = underTest.execute("plug", "-f", pomPath.toString(), input);
assertSame(0, ec, "Exit code");

var expr = "/project/build/plugins/plugin[groupId='org.springframework.boot' and artifactId='spring-boot-maven-plugin']";
assertXpath(pomPath, expr, 1);
}
}

0 comments on commit 4367d92

Please sign in to comment.