pro.avodonosov.mvnhashver.HashVerMojo Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hashver-maven-plugin Show documentation
Show all versions of hashver-maven-plugin Show documentation
Generate versions for project modules as hashcode
of their sources and dependency tree. so that when module
version changes automatically.
The goal is to speedup multi-module project builds by avoiding
build of unchanged modules (mostly oriented to CI build servers).
Provides a build extension which can skip module build if aftifact
of the same version exists already.
package pro.avodonosov.mvnhashver;
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Component;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.project.DefaultProjectBuildingRequest;
import org.apache.maven.project.MavenProject;
import org.apache.maven.project.ProjectBuildingRequest;
import org.apache.maven.shared.dependency.graph.DependencyGraphBuilder;
import org.apache.maven.shared.dependency.graph.DependencyGraphBuilderException;
import org.apache.maven.shared.dependency.graph.DependencyNode;
import org.apache.maven.shared.dependency.graph.traversal.DependencyNodeVisitor;
import org.apache.maven.shared.dependency.graph.traversal.SerializingDependencyNodeVisitor;
import javax.inject.Inject;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Base64;
import java.util.Collections;
import java.util.Comparator;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;
@Mojo(name = "hashver", aggregator = true)
public class HashVerMojo extends AbstractMojo {
public static final String DIGEST_ALGO = "SHA-1";
/**
* The dependency tree builder to use.
*/
@Component(hint = "default")
private DependencyGraphBuilder dependencyGraphBuilder;
@Inject
MavenSession mavenSession;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
Map ownHashByArtifact = new HashMap<>();
for (MavenProject prj : mavenSession.getProjects()) {
try {
ownHashByArtifact.put(
ArtifactUtils.key(prj.getArtifact()),
ownHash(prj));
} catch (IOException e) {
throw new MojoExecutionException(
"Error calculating module own hash: " + prj.getName(),
e);
}
}
Map hashVers = new HashMap<>();
for (MavenProject prj : mavenSession.getProjects()) {
try {
hashVers.put(
prj.getGroupId() + "." + prj.getArtifactId() + ".hashver",
prjVersion(mavenSession, prj,
dependencyGraphBuilder, ownHashByArtifact));
} catch (DependencyGraphBuilderException e) {
throw new MojoExecutionException(
"prjVersion() failed for " + prj.getName(),
e);
}
}
getLog().info("HashVers computed: " + hashVers.size());
ArrayList keys = new ArrayList<>(hashVers.keySet());
Collections.sort(keys);
for (String prjKey : keys) {
getLog().info(prjKey + "=" + hashVers.get(prjKey));
}
try {
storeHashVers(hashVers);
} catch (IOException e) {
throw new MojoExecutionException("Error saving hashVers", e);
}
}
private void storeHashVers(Map hashVers)
throws IOException
{
storeHashVerProps(hashVers, "hashversions.properties");
storeMvnEx(hashVers, "mvnex.sh");
}
private void storeMvnEx(Map hashVers, String file)
throws IOException
{
ArrayList keys = new ArrayList<>(hashVers.keySet());
keys.sort(String::compareTo);
try (Writer out = new OutputStreamWriter(
new FileOutputStream(file), StandardCharsets.UTF_8))
{
out.write("#!/bin/sh\n");
out.write("mvn");
for (String key : keys) {
out.write(" ");
out.write("-D");
out.write(key);
out.write("=");
out.write(hashVers.get(key));
}
out.write(" \"$@\"");
}
}
private void storeHashVerProps(Map hashVers, String file)
throws IOException
{
Properties props = new Properties() {
// Store properties in alphabetical order.
// Here we rely on the internal details of the Properties::store
// method, which saves properties in the order as
// they are enumerated by the Properties:keys().
@Override
public synchronized Enumeration