Skip to content

Commit

Permalink
Enhancements, fixes and refactoring of dependency tree processing API
Browse files Browse the repository at this point in the history
  • Loading branch information
aloubyansky committed Dec 21, 2023
1 parent 46fdb09 commit f731407
Show file tree
Hide file tree
Showing 20 changed files with 441 additions and 411 deletions.
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();

}
Loading

0 comments on commit f731407

Please sign in to comment.