Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
aloubyansky committed Dec 4, 2023
1 parent 842924c commit 9e21e4e
Show file tree
Hide file tree
Showing 3 changed files with 111 additions and 41 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,23 @@ public interface DependencyFlags {
// once the processing of the whole tree has completed.
int VISITED = 0b00100000000000;

/**
* Compile-only dependencies are those that are configured in the project
* to be included only in the compile phase ({@code provided} dependency scope in Maven,
* {@code compileOnly} configuration in Gradle).
* <p>
* These dependencies will not be present on the Quarkus application runtime or
* augmentation (deployment) classpath when the application is bootstrapped in production mode
* ({@code io.quarkus.runtime.LaunchMode.NORMAL}).
* <p>
* Compile-only dependencies will be present on both the runtime and the augmentation classpath
* of a Quarkus application launched in test and dev modes.
* <p>
* In any case though, these dependencies will be available during augmentation for processing
* using {@link io.quarkus.bootstrap.model.ApplicationModel#getDependencies(int)} by passing
* this flag as an argument.
*/
int COMPILE_ONLY = 0b01000000000000;
/* @formatter:on */

}
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@

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.graph.DependencyVisitor;
Expand Down Expand Up @@ -231,9 +230,8 @@ public ApplicationModel resolveModel(WorkspaceModule module)
final List<Dependency> constraints = managedMap.isEmpty() ? List.of() : new ArrayList<>(managedMap.values());

return buildAppModel(mainDep,
MavenArtifactResolver.newCollectRequest(mainArtifact, directDeps, constraints, List.of(),
mvn.getRepositories()),
Set.of(), constraints, List.of());
mainArtifact, directDeps, mvn.getRepositories(),
Set.of(), constraints);
}

private ApplicationModel doResolveModel(ArtifactCoords coords,
Expand All @@ -244,7 +242,7 @@ private ApplicationModel doResolveModel(ArtifactCoords coords,
if (coords == null) {
throw new IllegalArgumentException("Application artifact is null");
}
final Artifact mvnArtifact = toAetherArtifact(coords);
Artifact mvnArtifact = toAetherArtifact(coords);

List<Dependency> managedDeps = List.of();
List<RemoteRepository> managedRepos = List.of();
Expand All @@ -256,11 +254,12 @@ private ApplicationModel doResolveModel(ArtifactCoords coords,

List<RemoteRepository> aggregatedRepos = mvn.aggregateRepositories(managedRepos, mvn.getRepositories());
final ResolvedDependency appArtifact = resolve(coords, mvnArtifact, aggregatedRepos);
final ArtifactDescriptorResult appArtifactDescr = resolveDescriptor(toAetherArtifact(appArtifact), aggregatedRepos);
mvnArtifact = toAetherArtifact(appArtifact);
final ArtifactDescriptorResult appArtifactDescr = resolveDescriptor(mvnArtifact, aggregatedRepos);

Map<ArtifactKey, String> managedVersions = Map.of();
if (!managedDeps.isEmpty()) {
final List<Dependency> mergedManagedDeps = new ArrayList<Dependency>(
final List<Dependency> mergedManagedDeps = new ArrayList<>(
managedDeps.size() + appArtifactDescr.getManagedDependencies().size());
managedVersions = new HashMap<>(managedDeps.size());
for (Dependency dep : managedDeps) {
Expand All @@ -278,14 +277,13 @@ private ApplicationModel doResolveModel(ArtifactCoords coords,
managedDeps = appArtifactDescr.getManagedDependencies();
}

directMvnDeps = DependencyUtils.mergeDeps(directMvnDeps, appArtifactDescr.getDependencies(), managedVersions,
getExcludedScopes());
directMvnDeps = DependencyUtils.mergeDeps(directMvnDeps, appArtifactDescr.getDependencies(), managedVersions, Set.of());
aggregatedRepos = mvn.aggregateRepositories(aggregatedRepos,
mvn.newResolutionRepositories(appArtifactDescr.getRepositories()));

return buildAppModel(appArtifact,
MavenArtifactResolver.newCollectRequest(mvnArtifact, directMvnDeps, managedDeps, List.of(), aggregatedRepos),
reloadableModules, managedDeps, aggregatedRepos);
mvnArtifact, directMvnDeps, aggregatedRepos,
reloadableModules, managedDeps);
}

private Set<String> getExcludedScopes() {
Expand All @@ -298,9 +296,10 @@ private Set<String> getExcludedScopes() {
return Set.of(JavaScopes.PROVIDED, JavaScopes.TEST);
}

private ApplicationModel buildAppModel(ResolvedDependency appArtifact, CollectRequest collectRtDepsRequest,
Set<ArtifactKey> reloadableModules, List<Dependency> managedDeps, List<RemoteRepository> repos)
throws AppModelResolverException, BootstrapMavenException {
private ApplicationModel buildAppModel(ResolvedDependency appArtifact,
Artifact artifact, List<Dependency> directDeps, List<RemoteRepository> repos,
Set<ArtifactKey> reloadableModules, List<Dependency> managedDeps)
throws AppModelResolverException {

final ApplicationModelBuilder appBuilder = new ApplicationModelBuilder().setAppArtifact(appArtifact);
if (appArtifact.getWorkspaceModule() != null) {
Expand All @@ -310,13 +309,26 @@ private ApplicationModel buildAppModel(ResolvedDependency appArtifact, CollectRe
appBuilder.addReloadableWorkspaceModules(reloadableModules);
}

var filteredProvidedDeps = new ArrayList<Dependency>(0);
var excludedScopes = getExcludedScopes();
if (!excludedScopes.isEmpty()) {
var filtered = new ArrayList<Dependency>(directDeps.size());
for (var d : directDeps) {
if (!excludedScopes.contains(d.getScope())) {
filtered.add(d);
} else if (JavaScopes.PROVIDED.equals(d.getScope())) {
filteredProvidedDeps.add(d);
}
}
directDeps = filtered;
}
var collectRtDepsRequest = MavenArtifactResolver.newCollectRequest(artifact, directDeps, managedDeps, List.of(), repos);
try {
ApplicationDependencyTreeResolver.newInstance()
.setArtifactResolver(mvn)
.setManagedDependencies(managedDeps)
.setMainRepositories(repos)
.setApplicationModelBuilder(appBuilder)
.setCollectReloadableModules(collectReloadableDeps && reloadableModules.isEmpty())
.setCollectCompileOnly(filteredProvidedDeps)
.setBuildTreeConsumer(buildTreeConsumer)
.resolve(collectRtDepsRequest);
} catch (BootstrapDependencyProcessingException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.eclipse.aether.RepositorySystemSession;
import org.eclipse.aether.artifact.Artifact;
import org.eclipse.aether.collection.CollectRequest;
import org.eclipse.aether.collection.DependencyCollectionException;
import org.eclipse.aether.collection.DependencyGraphTransformationContext;
import org.eclipse.aether.collection.DependencyGraphTransformer;
import org.eclipse.aether.collection.DependencySelector;
Expand All @@ -33,6 +34,7 @@
import org.eclipse.aether.graph.DependencyNode;
import org.eclipse.aether.graph.Exclusion;
import org.eclipse.aether.repository.RemoteRepository;
import org.eclipse.aether.resolution.ArtifactDescriptorResult;
import org.eclipse.aether.resolution.DependencyRequest;
import org.eclipse.aether.resolution.DependencyResolutionException;
import org.eclipse.aether.util.artifact.JavaScopes;
Expand Down Expand Up @@ -95,26 +97,16 @@ public static Artifact getRuntimeArtifact(DependencyNode dep) {

private MavenArtifactResolver resolver;
private List<Dependency> managedDeps;
private List<RemoteRepository> mainRepos;
private ApplicationModelBuilder appBuilder;
private boolean collectReloadableModules;
private Consumer<String> buildTreeConsumer;
private List<Dependency> collectCompileOnly;

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

public ApplicationDependencyTreeResolver setManagedDependencies(List<Dependency> managedDeps) {
this.managedDeps = managedDeps;
return this;
}

public ApplicationDependencyTreeResolver setMainRepositories(List<RemoteRepository> mainRepos) {
this.mainRepos = mainRepos;
return this;
}

public ApplicationDependencyTreeResolver setApplicationModelBuilder(ApplicationModelBuilder appBuilder) {
this.appBuilder = appBuilder;
return this;
Expand All @@ -130,8 +122,14 @@ public ApplicationDependencyTreeResolver setBuildTreeConsumer(Consumer<String> b
return this;
}

public ApplicationDependencyTreeResolver setCollectCompileOnly(List<Dependency> collectCompileOnly) {
this.collectCompileOnly = collectCompileOnly;
return this;
}

public void resolve(CollectRequest collectRtDepsRequest) throws AppModelResolverException {

this.managedDeps = collectRtDepsRequest.getManagedDependencies();
DependencyNode root = resolveRuntimeDeps(collectRtDepsRequest);

if (collectReloadableModules) {
Expand Down Expand Up @@ -224,6 +222,10 @@ public void resolve(CollectRequest collectRtDepsRequest) throws AppModelResolver
}

collectPlatformProperties();

if (!collectCompileOnly.isEmpty()) {
// TODO
}
}

private void collectPlatformProperties() throws AppModelResolverException {
Expand Down Expand Up @@ -499,7 +501,8 @@ private ExtensionInfo getExtensionInfoOrNull(Artifact artifact) throws Bootstrap
private void injectDeploymentDependencies(ExtensionDependency extDep)
throws BootstrapDependencyProcessingException {
log.debugf("Injecting deployment dependency %s", extDep.info.deploymentArtifact);
final DependencyNode deploymentNode = collectDependencies(extDep.info.deploymentArtifact, extDep.exclusions);
final DependencyNode deploymentNode = collectDependencies(extDep.info.deploymentArtifact, extDep.exclusions,
extDep.runtimeNode.getRepositories());
if (deploymentNode.getChildren().isEmpty()) {
throw new BootstrapDependencyProcessingException(
"Failed to collect dependencies of " + deploymentNode.getArtifact()
Expand Down Expand Up @@ -592,16 +595,51 @@ private boolean replaceRuntimeBranch(ExtensionDependency extNode, List<Dependenc
return false;
}

private DependencyNode collectDependencies(Artifact artifact, Collection<Exclusion> exclusions) {
private DependencyNode collectDependencies(Artifact artifact, Collection<Exclusion> exclusions,
List<RemoteRepository> repos) {
final CollectRequest request;
if (managedDeps.isEmpty()) {
request = new CollectRequest()
.setRoot(new Dependency(artifact, JavaScopes.COMPILE, false, exclusions))
.setRepositories(repos);
} else {
final ArtifactDescriptorResult descr;
try {
descr = resolver.resolveDescriptor(artifact, repos);
} catch (BootstrapMavenException e) {
throw new DeploymentInjectionException("Failed to resolve descriptor for " + artifact, e);
}
final List<Dependency> mergedManagedDeps = new ArrayList<>(
managedDeps.size() + descr.getManagedDependencies().size());
final Map<ArtifactKey, String> managedVersions = new HashMap<>(managedDeps.size());
for (Dependency dep : managedDeps) {
managedVersions.put(DependencyUtils.getKey(dep.getArtifact()), dep.getArtifact().getVersion());
mergedManagedDeps.add(dep);
}
for (Dependency dep : descr.getManagedDependencies()) {
final ArtifactKey key = DependencyUtils.getKey(dep.getArtifact());
if (!managedVersions.containsKey(key)) {
mergedManagedDeps.add(dep);
}
}

var directDeps = DependencyUtils.mergeDeps(List.of(), descr.getDependencies(), managedVersions,
Set.of(JavaScopes.PROVIDED, JavaScopes.TEST));

request = new CollectRequest()
.setDependencies(directDeps)
.setManagedDependencies(mergedManagedDeps)
.setRepositories(repos);
if (exclusions.isEmpty()) {
request.setRootArtifact(artifact);
} else {
request.setRoot(new Dependency(artifact, JavaScopes.COMPILE, false, exclusions));
}
}
try {
return managedDeps.isEmpty()
? resolver.collectDependencies(artifact, List.of(), mainRepos, exclusions).getRoot()
: resolver
.collectManagedDependencies(artifact, List.of(), managedDeps, mainRepos, exclusions,
JavaScopes.TEST, JavaScopes.PROVIDED)
.getRoot();
} catch (AppModelResolverException e) {
throw new DeploymentInjectionException(e);
return resolver.getSystem().collectDependencies(resolver.getSession(), request).getRoot();
} catch (DependencyCollectionException e) {
throw new DeploymentInjectionException("Failed to collect dependencies for " + artifact, e);
}
}

Expand Down Expand Up @@ -746,23 +784,26 @@ private ConditionalDependency(ExtensionInfo info, ExtensionDependency dependent)

ExtensionDependency getExtensionDependency() {
if (dependency == null) {
final DefaultDependencyNode rtNode = new DefaultDependencyNode(new Dependency(info.runtimeArtifact, "runtime"));
final DefaultDependencyNode rtNode = new DefaultDependencyNode(
new Dependency(info.runtimeArtifact, JavaScopes.RUNTIME));
rtNode.setVersion(new BootstrapArtifactVersion(info.runtimeArtifact.getVersion()));
rtNode.setVersionConstraint(new BootstrapArtifactVersionConstraint(
new BootstrapArtifactVersion(info.runtimeArtifact.getVersion())));
rtNode.setRepositories(dependent.runtimeNode.getRepositories());
dependency = new ExtensionDependency(info, rtNode, dependent.exclusions);
}
return dependency;
}

void activate() throws BootstrapDependencyProcessingException {
void activate() {
if (activated) {
return;
}
activated = true;
clearWalkingFlag(COLLECT_TOP_EXTENSION_RUNTIME_NODES);
final ExtensionDependency extDep = getExtensionDependency();
final DependencyNode originalNode = collectDependencies(info.runtimeArtifact, extDep.exclusions);
final DependencyNode originalNode = collectDependencies(info.runtimeArtifact, extDep.exclusions,
extDep.runtimeNode.getRepositories());
final DefaultDependencyNode rtNode = (DefaultDependencyNode) extDep.runtimeNode;
rtNode.setRepositories(originalNode.getRepositories());
// if this node has conditional dependencies on its own, they may have been activated by this time
Expand All @@ -777,7 +818,7 @@ void activate() throws BootstrapDependencyProcessingException {
dependent.runtimeNode.getChildren().add(rtNode);
}

boolean isSatisfied() throws BootstrapDependencyProcessingException {
boolean isSatisfied() {
if (info.dependencyCondition == null) {
return true;
}
Expand Down

0 comments on commit 9e21e4e

Please sign in to comment.