Skip to content

Commit

Permalink
adding simple-dependencies mojo to output dependencies in JSON
Browse files Browse the repository at this point in the history
  • Loading branch information
rmannibucau committed Mar 13, 2023
1 parent 443673e commit 0d7bcb3
Show file tree
Hide file tree
Showing 5 changed files with 261 additions and 25 deletions.
6 changes: 6 additions & 0 deletions _documentation/src/main/minisite/content/mojos.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,12 @@ Scope can be:

The optional attribute `groupId` is also supported and take a list (comma separated) of groupId to include.

== Simple Dependencies

xref:mojo/simple-dependencies.adoc[simple-dependencies] is a trivial and simple alternative to `maven-dependency-plugin:list` mojo which outputs the data in JSON.

It is convenient with `minisite` mojo to format with a custom action the dependencies according to a custom need.

== Yupiik OSS extension

This extension sets up the equivalent of a parent pom but enables to inherit or not from another parent and to benefit from upgrades for free.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
/*
* Copyright (c) 2020 - 2023 - Yupiik SAS - https://www.yupiik.com
* 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 io.yupiik.maven.mojo;

import io.yupiik.maven.service.artifact.Filters;
import jakarta.json.bind.JsonbBuilder;
import jakarta.json.bind.JsonbConfig;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.plugins.annotations.ResolutionScope;
import org.apache.maven.project.MavenProject;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Collection;
import java.util.List;

import static io.yupiik.maven.mojo.SimpleDependenciesMojo.Format.JSON_PRETTY;
import static jakarta.json.bind.config.PropertyOrderStrategy.LEXICOGRAPHICAL;
import static java.util.stream.Collectors.toList;

@Mojo(
name = "simple-dependencies", requiresDependencyResolution = ResolutionScope.TEST,
defaultPhase = LifecyclePhase.GENERATE_SOURCES, threadSafe = true)
public class SimpleDependenciesMojo extends AbstractMojo {
/**
* Where to dump the dependencies, {@code log} to log them, else a file path.
*/
@Parameter(property = "yupiik.simple-dependencies.source", defaultValue = "${project.build.directory/dependencies.adoc")
protected String output;

/**
* Which format to use to dump them.
*/
@Parameter(property = "yupiik.simple-dependencies.format", defaultValue = "JSON")
protected Format format;

/**
* Which scope to include, use {@code all} to include them all.
*/
@Parameter(property = "yupiik.simple-dependencies.scope", defaultValue = "all")
protected String scope;

@Parameter(defaultValue = "${project}", readonly = true, required = true)
protected MavenProject project;

@Override
public void execute() throws MojoExecutionException, MojoFailureException {
final var dependencies = findDependencies();
final var formatted = format(dependencies);
if (output.equals("log")) {
getLog().info(formatted);
} else {
final var file = Path.of(output);
try {
if (file.getParent() != null) {
Files.createDirectories(file.getParent());
}
try (final var out = Files.newBufferedWriter(file)) {
out.write(formatted);
}
} catch (final IOException ioe) {
throw new MojoFailureException(ioe.getMessage(), ioe);
}
}
}

private String format(final List<DepArtifact> dependencies) throws MojoFailureException {
switch (format) {
// todo: ADOC?
case JSON:
case JSON_PRETTY:
default:
try (final var jsonb = JsonbBuilder.create(new JsonbConfig()
.withPropertyOrderStrategy(LEXICOGRAPHICAL)
.withFormatting(JSON_PRETTY.equals(format)))) {
return jsonb.toJson(new JsonWrapper(dependencies));
} catch (final Exception e) {
throw new MojoFailureException(e.getMessage(), e);
}
}
}

private List<DepArtifact> findDependencies() {
final var filter = Filters.createScopeFilter(scope);
return project.getArtifacts().stream()
.filter(filter::include)
.map(a -> new DepArtifact(a.getGroupId(), a.getArtifactId(), a.getBaseVersion(), a.getType(), a.getClassifier(), a.getScope()))
.collect(toList());
}

public static class JsonWrapper {
public Collection<DepArtifact> items;

public JsonWrapper(final Collection<DepArtifact> items) {
this.items = items;
}
}

public static class DepArtifact {
public String groupId;
public String artifactId;
public String version;
public String type;
public String classifier;
public String scope;

public DepArtifact(final String groupId, final String artifactId,
final String version, final String type,
final String classifier, final String scope) {
this.groupId = groupId;
this.artifactId = artifactId;
this.version = version;
this.type = type;
this.classifier = classifier;
this.scope = scope;
}
}

public enum Format {
JSON,
JSON_PRETTY,
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (c) 2020 - 2023 - Yupiik SAS - https://www.yupiik.com
* 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 io.yupiik.maven.service.artifact;

import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;

public final class Filters {
private Filters() {
// no-op
}

public static ArtifactFilter createScopeFilter(final String scope) {
switch (scope) {
case "all":
return artifact -> true;
case "compile":
case "runtime":
case "compile+runtime":
case "runtime+system":
case "test":
return new ScopeArtifactFilter(scope);
case "test_only":
return artifact -> "test".equals(artifact.getScope());
case "compile_only":
return artifact -> "compile".equals(artifact.getScope());
case "runtime_only":
return artifact -> "runtime".equals(artifact.getScope());
case "system_only":
return artifact -> "system".equals(artifact.getScope());
case "provided_only":
return artifact -> "provided".equals(artifact.getScope());
default:
throw new IllegalArgumentException("Unsupported scope: '" + scope + "'");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
package io.yupiik.maven.service.extension;

import io.yupiik.maven.mojo.BaseMojo;
import io.yupiik.maven.service.artifact.Filters;
import lombok.RequiredArgsConstructor;
import org.apache.maven.artifact.resolver.filter.AndArtifactFilter;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
import org.apache.maven.artifact.resolver.filter.ScopeArtifactFilter;
import org.apache.maven.project.MavenProject;
import org.asciidoctor.ast.ContentModel;
import org.asciidoctor.ast.Section;
Expand Down Expand Up @@ -99,7 +99,7 @@ private List<String> listArtifacts(final MavenProject project, final ArtifactFil

private ArtifactFilter createFilter(final String scope, final String groupId) {
return new AndArtifactFilter(Stream.of(
singletonList(createScopeFilter(scope)), createGroupFilter(groupId))
singletonList(Filters.createScopeFilter(scope)), createGroupFilter(groupId))
.filter(Objects::nonNull)
.flatMap(Collection::stream)
.collect(Collectors.toList()));
Expand All @@ -110,27 +110,4 @@ private List<ArtifactFilter> createGroupFilter(final String groupId) {
.map(a -> (ArtifactFilter) artifact -> a.equals(artifact.getGroupId()))
.collect(toList());
}

private ArtifactFilter createScopeFilter(final String scope) {
switch (scope) {
case "compile":
case "runtime":
case "compile+runtime":
case "runtime+system":
case "test":
return new ScopeArtifactFilter(scope);
case "test_only":
return artifact -> "test".equals(artifact.getScope());
case "compile_only":
return artifact -> "compile".equals(artifact.getScope());
case "runtime_only":
return artifact -> "runtime".equals(artifact.getScope());
case "system_only":
return artifact -> "system".equals(artifact.getScope());
case "provided_only":
return artifact -> "provided".equals(artifact.getScope());
default:
throw new IllegalArgumentException("Unsupported scope: '" + scope + "'");
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
/*
* Copyright (c) 2020 - 2023 - Yupiik SAS - https://www.yupiik.com
* 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 io.yupiik.maven.mojo;

import org.apache.maven.artifact.DefaultArtifact;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;

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

import static org.junit.jupiter.api.Assertions.assertEquals;

class SimpleDependenciesMojoTest {
@Test
void run(@TempDir final Path work) throws MojoExecutionException, MojoFailureException, IOException {
final var file = work.resolve("deps.json");
final var mojo = new SimpleDependenciesMojo() {{
output = file.toString();
format = Format.JSON_PRETTY;
scope = "all";
project = new MavenProject();
project.setArtifacts(Set.of(new DefaultArtifact(
"the.group", "the.art", "the.version",
"the.scope", "the.type", "the.classifier", null)));
}};
mojo.execute();
assertEquals("" +
"{\n" +
" \"items\":[\n" +
" {\n" +
" \"artifactId\":\"the.art\",\n" +
" \"classifier\":\"the.classifier\",\n" +
" \"groupId\":\"the.group\",\n" +
" \"scope\":\"the.scope\",\n" +
" \"type\":\"the.type\",\n" +
" \"version\":\"the.version\"\n" +
" }\n" +
" ]\n" +
"}" +
"", Files.readString(file));
}
}

0 comments on commit 0d7bcb3

Please sign in to comment.