Skip to content
Open
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
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package io.github.chains_project.maven_lockfile;

import io.github.chains_project.maven_lockfile.data.LockFile;
import io.github.chains_project.maven_lockfile.data.MavenPlugin;
import io.github.chains_project.maven_lockfile.graph.DependencyNode;
import io.github.chains_project.maven_lockfile.reporting.PluginLogManager;
import java.io.File;
Expand All @@ -9,9 +10,11 @@
import java.io.IOException;
import java.util.*;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.model.Build;
import org.apache.maven.model.Dependency;
import org.apache.maven.model.DependencyManagement;
import org.apache.maven.model.Model;
import org.apache.maven.model.Plugin;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.apache.maven.model.io.xpp3.MavenXpp3Writer;
import org.apache.maven.plugin.AbstractMojo;
Expand Down Expand Up @@ -66,6 +69,7 @@ public void execute() throws MojoExecutionException {
List<Dependency> filteredDependencies = getNearestVersionDependency(lockFile);
Model pomModel = readPomFile(pomFile);
updateDependencies(pomModel, filteredDependencies);
updatePlugins(pomModel, lockFile.getMavenPlugins());
writePomLockFile(pomModel, pomLockFile);
} catch (IOException | XmlPullParserException e) {
throw new MojoExecutionException("Could not freeze versions", e);
Expand Down Expand Up @@ -156,6 +160,9 @@ private Dependency toMavenDependency(DependencyNode dep) {
if (dep.getClassifier() != null) {
mavenDep.setClassifier(dep.getClassifier().getValue());
}
if (dep.getType() != null) {
mavenDep.setType(dep.getType().getValue());
}
mavenDep.setScope(dep.getScope().getValue());
return mavenDep;
}
Expand All @@ -170,4 +177,72 @@ private String convertSoftToExactVersionString(String version) {
}
return "[" + version + "]";
}

/**
* Updates the plugins in the POM model with plugin dependencies from the lock file.
*
* @param pomModel the POM model to update
* @param mavenPlugins the set of Maven plugins from the lock file
*/
private void updatePlugins(Model pomModel, Set<MavenPlugin> mavenPlugins) {
if (mavenPlugins == null || mavenPlugins.isEmpty()) {
return;
}

Build build = pomModel.getBuild();
if (build == null) {
build = new Build();
pomModel.setBuild(build);
}

List<Plugin> plugins = build.getPlugins();
if (plugins == null) {
plugins = new ArrayList<>();
build.setPlugins(plugins);
}

Map<String, Plugin> existingPluginsMap = new HashMap<>();
for (Plugin plugin : plugins) {
String key = plugin.getGroupId() + ":" + plugin.getArtifactId();
existingPluginsMap.put(key, plugin);
}

// Process each plugin from the lock file
for (MavenPlugin mavenPlugin : mavenPlugins) {
String key = mavenPlugin.getGroupId().getValue() + ":"
+ mavenPlugin.getArtifactId().getValue();
Plugin plugin = existingPluginsMap.get(key);

if (plugin == null) {
// Plugin doesn't exist in the POM, create it
plugin = new Plugin();
plugin.setGroupId(mavenPlugin.getGroupId().getValue());
plugin.setArtifactId(mavenPlugin.getArtifactId().getValue());
plugins.add(plugin);
}

// Add plugin dependencies if they exist
Set<DependencyNode> pluginDependencies = mavenPlugin.getDependencies();
if (pluginDependencies != null && !pluginDependencies.isEmpty()) {
List<Dependency> dependencies = new ArrayList<>();
Queue<DependencyNode> depQueue = new ArrayDeque<>(pluginDependencies);

while (!depQueue.isEmpty()) {
DependencyNode depNode = depQueue.poll();
if (depNode.isIncluded()) {
Dependency dep = toMavenDependency(depNode);
String scope = dep.getScope() != null ? dep.getScope() : "compile";

// Plugin dependencies can only have scope: compile, runtime, or system
if (scope.equals("compile") || scope.equals("runtime") || scope.equals("system")) {
dependencies.add(dep);
}
}
depQueue.addAll(depNode.getChildren());
}

plugin.setDependencies(dependencies);
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package io.github.chains_project.maven_lockfile.data;

import com.google.common.base.Strings;
import java.util.Objects;

/**
* A Maven artifact type specifies the packaging type of the artifact (e.g., jar, pom, war).
* The default type is "jar", so we return null for "jar" or null/empty input to avoid redundant data.
*/
public class ArtifactType implements Comparable<ArtifactType> {
public static ArtifactType of(String type) {
if (Strings.isNullOrEmpty(type) || "jar".equals(type)) {
return null;
}
return new ArtifactType(type);
}

private final String value;

private ArtifactType(String type) {
this.value = Objects.requireNonNull(type, "type is marked non-null but is null");
}

public String getValue() {
return value;
}

@Override
public String toString() {
return "{" + " ArtifactType='" + getValue() + "'" + "}";
}

@Override
public boolean equals(Object o) {
if (o == this) return true;
if (!(o instanceof ArtifactType)) {
return false;
}
ArtifactType artifactType = (ArtifactType) o;
return Objects.equals(value, artifactType.value);
}

@Override
public int hashCode() {
return Objects.hashCode(value);
}

@Override
public int compareTo(ArtifactType o) {
return this.value.compareTo(o.value);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import io.github.chains_project.maven_lockfile.checksum.AbstractChecksumCalculator;
import io.github.chains_project.maven_lockfile.checksum.RepositoryInformation;
import io.github.chains_project.maven_lockfile.data.ArtifactId;
import io.github.chains_project.maven_lockfile.data.ArtifactType;
import io.github.chains_project.maven_lockfile.data.Classifier;
import io.github.chains_project.maven_lockfile.data.GroupId;
import io.github.chains_project.maven_lockfile.data.MavenScope;
Expand Down Expand Up @@ -87,6 +88,7 @@ private static Optional<DependencyNode> createDependencyNode(
var artifactId = ArtifactId.of(node.getArtifact().getArtifactId());
var version = VersionNumber.of(node.getArtifact().getVersion());
var classifier = Classifier.of(node.getArtifact().getClassifier());
var type = ArtifactType.of(node.getArtifact().getType());
PluginLogManager.getLog().debug(String.format("Calculating checksum for %s", node.toNodeString()));
var checksum = isRoot ? "" : calc.calculateArtifactChecksum(node.getArtifact());
var scope = MavenScope.fromString(node.getArtifact().getScope());
Expand All @@ -105,6 +107,7 @@ private static Optional<DependencyNode> createDependencyNode(
groupId,
version,
classifier,
type,
scope,
repositoryInformation.getResolvedUrl(),
repositoryInformation.getRepositoryId(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.google.gson.annotations.Expose;
import io.github.chains_project.maven_lockfile.data.ArtifactId;
import io.github.chains_project.maven_lockfile.data.ArtifactType;
import io.github.chains_project.maven_lockfile.data.Classifier;
import io.github.chains_project.maven_lockfile.data.GroupId;
import io.github.chains_project.maven_lockfile.data.MavenScope;
Expand All @@ -20,6 +21,7 @@ public class DependencyNode implements Comparable<DependencyNode> {
private final ArtifactId artifactId;
private final VersionNumber version;
private final Classifier classifier;
private final ArtifactType type;
private final String checksumAlgorithm;
private final String checksum;
private final MavenScope scope;
Expand All @@ -42,6 +44,7 @@ public class DependencyNode implements Comparable<DependencyNode> {
GroupId groupId,
VersionNumber version,
Classifier classifier,
ArtifactType type,
MavenScope scope,
ResolvedUrl resolved,
RepositoryId repositoryId,
Expand All @@ -51,6 +54,7 @@ public class DependencyNode implements Comparable<DependencyNode> {
this.groupId = groupId;
this.version = version;
this.classifier = classifier;
this.type = type;
this.checksumAlgorithm = checksumAlgorithm;
this.checksum = checksum;
this.children = new TreeSet<>(Comparator.comparing(DependencyNode::getComparatorString));
Expand Down Expand Up @@ -89,6 +93,12 @@ public VersionNumber getVersion() {
public Classifier getClassifier() {
return classifier;
}
/**
* @return the artifact type or null if default (jar)
*/
public ArtifactType getType() {
return type;
}
/**
* @return the scope
*/
Expand Down Expand Up @@ -173,6 +183,7 @@ public int hashCode() {
artifactId,
version,
classifier,
type,
checksumAlgorithm,
checksum,
scope,
Expand All @@ -195,6 +206,7 @@ public boolean equals(Object obj) {
&& Objects.equals(artifactId, other.artifactId)
&& Objects.equals(version, other.version)
&& Objects.equals(classifier, other.classifier)
&& Objects.equals(type, other.type)
&& Objects.equals(checksumAlgorithm, other.checksumAlgorithm)
&& Objects.equals(checksum, other.checksum)
&& Objects.equals(scope, other.scope)
Expand Down Expand Up @@ -233,10 +245,10 @@ public int compareTo(DependencyNode o) {
@Override
public String toString() {
return "DependencyNode [groupId=" + groupId + ", artifactId=" + artifactId + ", version=" + version
+ ", classifier=" + classifier + ", checksumAlgorithm=" + checksumAlgorithm + ", checksum=" + checksum
+ ", scope=" + scope + ", resolved=" + resolved + ", repositoryId=" + repositoryId
+ ", selectedVersion=" + selectedVersion + ", id=" + id + ", parent=" + parent + ", children="
+ children + "]";
+ ", classifier=" + classifier + ", type=" + type + ", checksumAlgorithm=" + checksumAlgorithm
+ ", checksum=" + checksum + ", scope=" + scope + ", resolved=" + resolved + ", repositoryId="
+ repositoryId + ", selectedVersion=" + selectedVersion + ", id=" + id + ", parent=" + parent
+ ", children=" + children + "]";
}

public String getComparatorString() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import io.github.chains_project.maven_lockfile.checksum.ChecksumModes;
import io.github.chains_project.maven_lockfile.data.ArtifactId;
import io.github.chains_project.maven_lockfile.data.ArtifactType;
import io.github.chains_project.maven_lockfile.data.Config;
import io.github.chains_project.maven_lockfile.data.Environment;
import io.github.chains_project.maven_lockfile.data.GroupId;
Expand Down Expand Up @@ -65,6 +66,7 @@ private DependencyNode dependencyNodeA(DependencyNode child1, DependencyNode chi
GroupId.of("Ag"),
VersionNumber.of("1"),
null,
ArtifactType.of("pom"),
MavenScope.RUNTIME,
ResolvedUrl.Unresolved(),
RepositoryId.None(),
Expand All @@ -82,6 +84,7 @@ private DependencyNode dependencyNodeB() {
GroupId.of("Bg"),
VersionNumber.of("1"),
null,
ArtifactType.of("jar"),
MavenScope.RUNTIME,
ResolvedUrl.Unresolved(),
RepositoryId.None(),
Expand All @@ -95,6 +98,7 @@ private DependencyNode dependencyNodeAChild1() {
GroupId.of("Ag1"),
VersionNumber.of("1"),
null,
ArtifactType.of("war"),
MavenScope.RUNTIME,
ResolvedUrl.Unresolved(),
RepositoryId.None(),
Expand All @@ -108,6 +112,7 @@ private DependencyNode dependencyNodeAChild2() {
GroupId.of("Ag2"),
VersionNumber.of("1"),
null,
ArtifactType.of("jar"),
MavenScope.RUNTIME,
ResolvedUrl.Unresolved(),
RepositoryId.None(),
Expand Down
Loading