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

Enhancements, fixes and refactoring of dependency tree processing API #311

Merged
merged 1 commit into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package io.quarkus.domino.inspect;

import io.quarkus.bootstrap.resolver.maven.BootstrapMavenException;
import io.quarkus.bootstrap.resolver.maven.MavenArtifactResolver;
import java.util.List;
import java.util.Objects;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.artifact.DefaultArtifact;
import org.eclipse.aether.collection.CollectRequest;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.graph.DependencyNode;
import org.eclipse.aether.util.artifact.JavaScopes;

public abstract class DependencyTreeBuilder {

private static final Artifact root = new DefaultArtifact("io.domino", "domino-tree-builder", "pom", "1");

public static DependencyTreeBuilder resolvingTreeBuilder(MavenArtifactResolver resolver) {
return new ResolvingDependencyTreeBuilder(resolver);
}

public static DependencyTreeBuilder nonResolvingTreeBuilder(MavenArtifactResolver resolver) {
return new NonResolvingDependencyTreeBuilder(resolver);
}

protected final MavenArtifactResolver resolver;

DependencyTreeBuilder(MavenArtifactResolver resolver) {
this.resolver = Objects.requireNonNull(resolver);
}

public DependencyNode buildTree(DependencyTreeRequest root) {
var rootNode = doBuildTree(root);
if (root.isDependency()) {
if (rootNode.getChildren().size() != 1) {
throw new RuntimeException("Expected a single child node but got " + rootNode.getChildren());
}
return rootNode.getChildren().get(0);
}
return rootNode;
}

public abstract DependencyNode doBuildTree(DependencyTreeRequest root);

protected CollectRequest createCollectRequest(DependencyTreeRequest root) {
var req = new CollectRequest().setManagedDependencies(root.getConstraints());
if (root.isPlugin()) {
try {
req.setRepositories(resolver.getMavenContext().getRemotePluginRepositories());
} catch (BootstrapMavenException e) {
throw new RuntimeException(e);
}
} else {
req.setRepositories(resolver.getRepositories());
}
var dep = new Dependency(
root.getArtifact(),
JavaScopes.RUNTIME,
false,
root.getExclusions());
if (root.isDependency()) {
req.setRootArtifact(DependencyTreeBuilder.root)
.setDependencies(List.of(dep));
} else {
req.setRoot(dep);
}
return req;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
package io.quarkus.domino.inspect;

public class DependencyTreeError {

private final DependencyTreeRequest request;
private final Throwable error;

public DependencyTreeError(DependencyTreeRequest request, Throwable error) {
this.request = request;
this.error = error;
}

public DependencyTreeRequest getRequest() {
return request;
}

public Throwable getError() {
return error;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package io.quarkus.domino.tree;
package io.quarkus.domino.inspect;

import io.quarkus.bootstrap.resolver.maven.BootstrapMavenContext;
import io.quarkus.bootstrap.resolver.maven.BootstrapMavenException;
Expand All @@ -14,10 +14,10 @@
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.graph.Exclusion;

public class DependencyTreeProcessor {
public class DependencyTreeInspector {

public static DependencyTreeProcessor configure() {
return new DependencyTreeProcessor();
public static DependencyTreeInspector configure() {
return new DependencyTreeInspector();
}

private String settings;
Expand All @@ -29,55 +29,73 @@ public static DependencyTreeProcessor configure() {
private DependencyTreeVisitor<?> treeVisitor;
private boolean parallelProcessing;
private MessageWriter log;
private List<DependencyTreeRoot> roots = new ArrayList<>();
private List<DependencyTreeRequest> roots = new ArrayList<>();

private DependencyTreeProcessor() {
private DependencyTreeInspector() {
}

public DependencyTreeProcessor setTreeBuilder(DependencyTreeBuilder treeBuilder) {
public DependencyTreeInspector setTreeBuilder(DependencyTreeBuilder treeBuilder) {
this.treeBuilder = treeBuilder;
return this;
}

public DependencyTreeProcessor setArtifactResolver(MavenArtifactResolver resolver) {
public DependencyTreeInspector setArtifactResolver(MavenArtifactResolver resolver) {
this.resolver = resolver;
return this;
}

public DependencyTreeProcessor setResolveDependencies(boolean resolveDependencies) {
public DependencyTreeInspector setResolveDependencies(boolean resolveDependencies) {
this.resolveDependencies = resolveDependencies;
return this;
}

public DependencyTreeProcessor setTreeVisitor(DependencyTreeVisitor<?> treeVisitor) {
public DependencyTreeInspector setTreeVisitor(DependencyTreeVisitor<?> treeVisitor) {
this.treeVisitor = treeVisitor;
return this;
}

public DependencyTreeProcessor setParallelProcessing(boolean parallelProcessing) {
public DependencyTreeInspector setParallelProcessing(boolean parallelProcessing) {
this.parallelProcessing = parallelProcessing;
return this;
}

public DependencyTreeProcessor setMessageWriter(MessageWriter log) {
public DependencyTreeInspector setMessageWriter(MessageWriter log) {
this.log = log;
return this;
}

public DependencyTreeProcessor addRoot(Artifact artifact) {
return addRoot(artifact, List.of(), List.of());
public DependencyTreeInspector inspectAsDependency(Artifact artifact) {
return inspectAsDependency(artifact, List.of(), List.of());
}

public DependencyTreeProcessor addRoot(Artifact artifact, List<Dependency> constraints) {
return addRoot(artifact, constraints, List.of());
public DependencyTreeInspector inspectAsDependency(Artifact artifact, List<Dependency> constraints) {
return inspectAsDependency(artifact, constraints, List.of());
}

public DependencyTreeProcessor addRoot(Artifact artifact, List<Dependency> constraints, Collection<Exclusion> exclusions) {
this.roots.add(new DependencyTreeRoot(artifact, constraints, exclusions));
public DependencyTreeInspector inspectAsDependency(Artifact artifact, List<Dependency> constraints,
Collection<Exclusion> exclusions) {
return inspect(DependencyTreeRequest.ofDependency(artifact, constraints, exclusions));
}

public DependencyTreeInspector inspectAsRoot(Artifact artifact, List<Dependency> constraints,
Collection<Exclusion> exclusions) {
return inspect(DependencyTreeRequest.ofRoot(artifact, constraints, exclusions));
}

public DependencyTreeInspector inspectPlugin(Artifact artifact) {
return inspect(DependencyTreeRequest.ofPlugin(artifact));
}

public DependencyTreeInspector inspectPlugin(Artifact artifact, Collection<Exclusion> exclusions) {
return inspect(DependencyTreeRequest.ofPlugin(artifact, exclusions));
}

public DependencyTreeInspector inspect(DependencyTreeRequest request) {
this.roots.add(request);
return this;
}

public void process() {
public void complete() {

if (resolver == null) {
var config = BootstrapMavenContext.config()
Expand Down Expand Up @@ -114,27 +132,27 @@ public void process() {
}

if (treeVisitor == null) {
treeVisitor = new DependencyTreeVisitor<Object>() {
treeVisitor = new DependencyTreeVisitor<>() {
@Override
public void visitTree(DependencyTreeVisit<Object> ctx) {
public void visit(DependencyTreeVisit<Object> ctx) {
}

@Override
public void onEvent(Object event, MessageWriter log) {
}

@Override
public void handleResolutionFailures(Collection<Artifact> artifacts) {
public void handleResolutionFailures(Collection<DependencyTreeError> requests) {
}
};
}

var scheduler = parallelProcessing
? DependencyTreeVisitScheduler.parallel(treeBuilder, treeVisitor, log, roots.size())
: DependencyTreeVisitScheduler.sequencial(treeBuilder, treeVisitor, log, roots.size());
: DependencyTreeVisitScheduler.sequential(treeBuilder, treeVisitor, log, roots.size());

for (var r : roots) {
scheduler.scheduleProcessing(r);
scheduler.process(r);
}
scheduler.waitForCompletion();
if (!scheduler.getResolutionFailures().isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
package io.quarkus.domino.inspect;

import java.util.Collection;
import java.util.List;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.graph.Dependency;
import org.eclipse.aether.graph.Exclusion;

public class DependencyTreeRequest {

/* @formatter:off */
private static final byte ROOT = 0b001;
private static final byte DEPENDENCY = 0b010;
private static final byte PLUGIN = 0b100;
/* @formatter:on */

public static DependencyTreeRequest ofRoot(Artifact artifact, List<Dependency> constraints,
Collection<Exclusion> exclusions) {
return new DependencyTreeRequest(artifact, constraints, exclusions, ROOT);
}

public static DependencyTreeRequest ofDependency(Artifact artifact, List<Dependency> constraints,
Collection<Exclusion> exclusions) {
return new DependencyTreeRequest(artifact, constraints, exclusions, DEPENDENCY);
}

public static DependencyTreeRequest ofPlugin(Artifact artifact) {
return ofPlugin(artifact, List.of());
}

public static DependencyTreeRequest ofPlugin(Artifact artifact, Collection<Exclusion> exclusions) {
return new DependencyTreeRequest(artifact, List.of(), exclusions, PLUGIN);
}

private final Artifact root;
private final List<Dependency> constraints;
private final Collection<Exclusion> exclusions;
private final byte type;

private DependencyTreeRequest(Artifact root, List<Dependency> constraints, Collection<Exclusion> exclusions, byte type) {
this.root = root;
this.constraints = constraints;
this.exclusions = exclusions;
this.type = type;
}

String getId() {
return root.toString();
}

public Artifact getArtifact() {
return root;
}

public List<Dependency> getConstraints() {
return constraints;
}

public Collection<Exclusion> getExclusions() {
return exclusions;
}

boolean isRoot() {
return type == ROOT;
}

boolean isDependency() {
return type == DEPENDENCY;
}

boolean isPlugin() {
return type == PLUGIN;
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package io.quarkus.domino.tree;
package io.quarkus.domino.inspect;

import io.quarkus.devtools.messagewriter.MessageWriter;
import java.util.Objects;
import org.eclipse.aether.graph.DependencyNode;

class DefaultTreeProcessingContext<E> implements DependencyTreeVisitor.DependencyTreeVisit<E> {
class DependencyTreeVisitContext<E> implements DependencyTreeVisitor.DependencyTreeVisit<E> {

private final DependencyTreeVisitor<E> processor;
private final DependencyTreeVisitor<E> visitor;
private final MessageWriter log;
DependencyNode root;

DefaultTreeProcessingContext(DependencyTreeVisitor<E> processor, MessageWriter log) {
this.processor = processor;
DependencyTreeVisitContext(DependencyTreeVisitor<E> visitor, MessageWriter log) {
this.visitor = visitor;
this.log = log;
}

Expand All @@ -28,6 +28,6 @@ public MessageWriter getLog() {
@Override
public void pushEvent(E event) {
Objects.requireNonNull(root, "Dependency tree root node is null");
processor.onEvent(event, log);
visitor.onEvent(event, log);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package io.quarkus.domino.inspect;

import io.quarkus.devtools.messagewriter.MessageWriter;
import java.util.Collection;

public interface DependencyTreeVisitScheduler {

static <E> DependencyTreeVisitScheduler sequential(DependencyTreeBuilder treeBuilder,
DependencyTreeVisitor<E> visitor,
MessageWriter log,
int treesTotal) {
return new SequentialTreeVisitScheduler<>(visitor, log, treesTotal, treeBuilder);
}

static <E> DependencyTreeVisitScheduler parallel(DependencyTreeBuilder treeBuilder,
DependencyTreeVisitor<E> visitor,
MessageWriter log,
int treesTotal) {
return new ParallelTreeVisitScheduler<>(visitor, log, treesTotal, treeBuilder);
}

void process(DependencyTreeRequest root);

void waitForCompletion();

Collection<DependencyTreeError> getResolutionFailures();

}