Skip to content

Commit

Permalink
Support for dev-mode-only conditional dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
Alexey Loubyansky committed Nov 15, 2024
1 parent efcd612 commit a64d19c
Show file tree
Hide file tree
Showing 22 changed files with 657 additions and 244 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,17 @@ protected QuarkusBootstrap.Builder initBootstrapBuilder() throws Exception {
final QuarkusBootstrap.Builder bootstrap = QuarkusBootstrap.builder()
.setApplicationRoot(applicationRoot)
.setProjectRoot(applicationRoot)
.setAppModelResolver(resolver)
.setTest(isBootstrapForTestMode());
.setAppModelResolver(resolver);

switch (getBootstrapMode()) {
case PROD:
break;
case TEST:
bootstrap.setTest(true);
break;
default:
throw new IllegalArgumentException("Not supported bootstrap mode " + getBootstrapMode());
}

if (createWorkspace() || !wsModules.isEmpty()) {
System.setProperty("basedir", ws.toAbsolutePath().toString());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,16 @@ protected QuarkusBootstrap.Builder initBootstrapBuilder()
.setApplicationRoot(applicationRoot)
.setProjectRoot(applicationRoot)
.setTargetDirectory(appModel.getAppArtifact().getWorkspaceModule().getBuildDir().toPath())
.setAppModelResolver(resolver)
.setTest(isBootstrapForTestMode());
.setAppModelResolver(resolver);
switch (getBootstrapMode()) {
case PROD:
break;
case TEST:
bootstrap.setTest(true);
break;
default:
throw new IllegalArgumentException("Not supported bootstrap mode " + getBootstrapMode());
}
return bootstrap;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.HashSet;
import java.util.Set;

import io.quarkus.bootstrap.app.QuarkusBootstrap;
import io.quarkus.bootstrap.model.ApplicationModel;
import io.quarkus.bootstrap.resolver.TsArtifact;
import io.quarkus.bootstrap.resolver.TsDependency;
Expand All @@ -17,8 +18,8 @@
public class ProvidedExtensionDepsInTestModeTest extends BootstrapFromOriginalJarTestBase {

@Override
protected boolean isBootstrapForTestMode() {
return true;
protected QuarkusBootstrap.Mode getBootstrapMode() {
return QuarkusBootstrap.Mode.TEST;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@

import org.eclipse.aether.util.artifact.JavaScopes;

import io.quarkus.bootstrap.app.QuarkusBootstrap;
import io.quarkus.bootstrap.model.ApplicationModel;
import io.quarkus.bootstrap.resolver.TsArtifact;
import io.quarkus.bootstrap.resolver.TsDependency;
Expand All @@ -19,8 +20,8 @@
public class ProvidedExtensionDepsTestModeTest extends BootstrapFromOriginalJarTestBase {

@Override
protected boolean isBootstrapForTestMode() {
return true;
protected QuarkusBootstrap.Mode getBootstrapMode() {
return QuarkusBootstrap.Mode.TEST;
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ public ConditionalDependenciesEnabler(Project project, LaunchMode mode,

if (!baseRuntimeConfig.getIncoming().getDependencies().isEmpty()) {
// Gather all extensions from the full resolved dependency tree
collectConditionalDependencies(baseRuntimeConfig.getResolvedConfiguration().getResolvedArtifacts());
collectConditionalDependencies(baseRuntimeConfig.getResolvedConfiguration().getResolvedArtifacts(), mode);
// If there are any extensions which had unresolved conditional dependencies:
while (!unsatisfiedConditionalDeps.isEmpty()) {
boolean satisfiedConditionalDeps = false;
Expand All @@ -58,7 +58,7 @@ public ConditionalDependenciesEnabler(Project project, LaunchMode mode,
while (i < unsatisfiedConditionalDeps.size()) {
final Dependency conditionalDep = unsatisfiedConditionalDeps.get(i);
// Try to resolve it with the latest evolved graph available
if (resolveConditionalDependency(conditionalDep)) {
if (resolveConditionalDependency(conditionalDep, mode)) {
// Mark the resolution as a success so we know the graph evolved
satisfiedConditionalDeps = true;
unsatisfiedConditionalDeps.remove(i);
Expand Down Expand Up @@ -86,7 +86,7 @@ private void reset() {
unsatisfiedConditionalDeps.clear();
}

private void collectConditionalDependencies(Set<ResolvedArtifact> runtimeArtifacts) {
private void collectConditionalDependencies(Set<ResolvedArtifact> runtimeArtifacts, LaunchMode mode) {
// For every artifact in the dependency graph:
for (ResolvedArtifact artifact : runtimeArtifacts) {
// Add to master list of artifacts:
Expand All @@ -96,17 +96,28 @@ private void collectConditionalDependencies(Set<ResolvedArtifact> runtimeArtifac
if (extension != null) {
// Add to master list of accepted extensions:
allExtensions.put(extension.getExtensionId(), extension);
for (Dependency conditionalDep : extension.getConditionalDependencies()) {
// If the dependency is not present yet in the graph, queue it for resolution later
if (!exists(conditionalDep)) {
queueConditionalDependency(extension, conditionalDep);
}
}
queueConditionalDependencies(extension, mode);
}
}
}

private boolean resolveConditionalDependency(Dependency conditionalDep) {
private void queueConditionalDependencies(ExtensionDependency<?> extension, LaunchMode mode) {
queueConditionalDependencies(extension, extension.getConditionalDependencies());
if (LaunchMode.DEVELOPMENT.equals(mode)) {
queueConditionalDependencies(extension, extension.getConditionalDevDependencies());
}
}

private void queueConditionalDependencies(ExtensionDependency<?> extension, Collection<Dependency> conditionalDeps) {
for (Dependency conditionalDep : conditionalDeps) {
// If the dependency is not present yet in the graph, queue it for resolution later
if (!exists(conditionalDep)) {
queueConditionalDependency(extension, conditionalDep);
}
}
}

private boolean resolveConditionalDependency(Dependency conditionalDep, LaunchMode mode) {

final Configuration conditionalDeps = createConditionalDependenciesConfiguration(project, conditionalDep);
Set<ResolvedArtifact> resolvedArtifacts = conditionalDeps.getResolvedConfiguration().getResolvedArtifacts();
Expand Down Expand Up @@ -148,12 +159,7 @@ private boolean resolveConditionalDependency(Dependency conditionalDep) {
extensionDependency.setConditional(true);
// Add to the master list of accepted extensions
allExtensions.put(extensionDependency.getExtensionId(), extensionDependency);
for (Dependency cd : extensionDependency.getConditionalDependencies()) {
// Add any unsatisfied/unresolved conditional dependencies of this dependency to the queue
if (!exists(cd)) {
queueConditionalDependency(extensionDependency, cd);
}
}
queueConditionalDependencies(extensionDependency, mode);
}
return satisfied;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,8 @@ public class ArtifactExtensionDependency extends ExtensionDependency<ArtifactCoo
public ArtifactExtensionDependency(ModuleVersionIdentifier extensionId,
ArtifactCoords deploymentModule,
List<Dependency> conditionalDependencies,
List<Dependency> conditionalDevDeps,
List<ArtifactKey> dependencyConditions) {
super(extensionId, deploymentModule, conditionalDependencies, dependencyConditions);
super(extensionId, deploymentModule, conditionalDependencies, conditionalDevDeps, dependencyConditions);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -255,7 +255,6 @@ private static ProjectExtensionDependency createExtensionDependency(
if (extensionConfiguration != null) {
final ListProperty<String> conditionalDependenciesProp = ConfigurationUtils
.getConditionalDependencies(extensionConfiguration);

if (conditionalDependenciesProp.isPresent()) {
for (String rawDep : conditionalDependenciesProp.get()) {
conditionalDependencies.add(create(project.getDependencies(), rawDep));
Expand All @@ -272,10 +271,28 @@ private static ProjectExtensionDependency createExtensionDependency(
}
}

if (extensionDescriptor != null && extensionDescriptor.containsKey(BootstrapConstants.CONDITIONAL_DEPENDENCIES)) {
final String[] deps = BootstrapUtils
.splitByWhitespace(extensionDescriptor.getProperty(BootstrapConstants.CONDITIONAL_DEPENDENCIES));
final String conditionalDepsStr = extensionDescriptor == null ? null
: extensionDescriptor.getProperty(BootstrapConstants.CONDITIONAL_DEPENDENCIES);
if (conditionalDepsStr != null) {
for (String condDep : BootstrapUtils.splitByWhitespace(conditionalDepsStr)) {
conditionalDependencies.add(create(project.getDependencies(), condDep));
}
}

List<Dependency> conditionalDevDeps = List.of();
final String conditionalDevDepsStr = extensionDescriptor == null ? null
: extensionDescriptor.getProperty(BootstrapConstants.CONDITIONAL_DEV_DEPENDENCIES);
if (conditionalDepsStr != null) {
final String[] arr = BootstrapUtils.splitByWhitespace(conditionalDepsStr);
conditionalDevDeps = new ArrayList<>(arr.length);
for (int i = 0; i < arr.length; ++i) {
conditionalDevDeps.add(create(project.getDependencies(), arr[i]));
}
}

if (extensionDescriptor != null && extensionDescriptor.containsKey(BootstrapConstants.CONDITIONAL_DEV_DEPENDENCIES)) {
final String[] deps = BootstrapUtils
.splitByWhitespace(extensionDescriptor.getProperty(BootstrapConstants.CONDITIONAL_DEV_DEPENDENCIES));
for (String condDep : deps) {
conditionalDependencies.add(create(project.getDependencies(), condDep));
}
Expand All @@ -284,7 +301,6 @@ private static ProjectExtensionDependency createExtensionDependency(
if (extensionDescriptor != null && extensionDescriptor.containsKey(BootstrapConstants.DEPENDENCY_CONDITION)) {
final ArtifactKey[] conditions = BootstrapUtils
.parseDependencyCondition(extensionDescriptor.getProperty(BootstrapConstants.DEPENDENCY_CONDITION));

dependencyConditions.addAll(Arrays.asList(conditions));
}

Expand All @@ -293,6 +309,7 @@ private static ProjectExtensionDependency createExtensionDependency(
deploymentProject,
isIncludedBuild,
conditionalDependencies,
conditionalDevDeps,
dependencyConditions);
}

Expand All @@ -302,47 +319,42 @@ private static ArtifactExtensionDependency createExtensionDependency(
Path descriptorPath) {
final Properties extensionProperties = loadLocalExtensionDescriptor(descriptorPath);

final ArtifactCoords deploymentArtifact = GACTV
final ArtifactCoords deploymentArtifact = ArtifactCoords
.fromString(extensionProperties.getProperty(BootstrapConstants.PROP_DEPLOYMENT_ARTIFACT));

final List<Dependency> conditionalDependencies;
if (extensionProperties.containsKey(BootstrapConstants.CONDITIONAL_DEPENDENCIES)) {
final String[] deps = BootstrapUtils
.splitByWhitespace(extensionProperties.getProperty(BootstrapConstants.CONDITIONAL_DEPENDENCIES));

if (deps.length > 0) {
conditionalDependencies = new ArrayList<>(deps.length);
for (String condDep : deps) {
conditionalDependencies.add(create(project.getDependencies(), condDep));
}
} else {
conditionalDependencies = Collections.emptyList();
}
} else {
conditionalDependencies = Collections.emptyList();
}

final List<ArtifactKey> dependencyConditions;
List<ArtifactKey> dependencyConditions = List.of();
if (extensionProperties.containsKey(BootstrapConstants.DEPENDENCY_CONDITION)) {
final ArtifactKey[] conditions = BootstrapUtils
.parseDependencyCondition(extensionProperties.getProperty(BootstrapConstants.DEPENDENCY_CONDITION));

if (conditions.length > 0) {
dependencyConditions = Arrays.asList(conditions);
} else {
dependencyConditions = Collections.emptyList();
}
} else {
dependencyConditions = Collections.emptyList();
}

return new ArtifactExtensionDependency(
extensionArtifactId,
deploymentArtifact,
conditionalDependencies,
parseConditionalDeps(project, extensionProperties, BootstrapConstants.CONDITIONAL_DEPENDENCIES),
parseConditionalDeps(project, extensionProperties, BootstrapConstants.CONDITIONAL_DEV_DEPENDENCIES),
dependencyConditions);
}

private static List<Dependency> parseConditionalDeps(Project project, Properties extensionProperties, String propertyName) {
var str = extensionProperties.getProperty(propertyName);
if (str == null) {
return List.of();
}
final String[] deps = BootstrapUtils.splitByWhitespace(extensionProperties.getProperty(propertyName));
if (deps.length == 0) {
return List.of();
}
var list = new ArrayList<Dependency>(deps.length);
for (String condDep : deps) {
list.add(create(project.getDependencies(), condDep));
}
return list;
}

public static Dependency create(DependencyHandler dependencies, String conditionalDependency) {
final ArtifactCoords dependencyCoords = GACTV.fromString(conditionalDependency);
return dependencies.create(String.join(":", dependencyCoords.getGroupId(), dependencyCoords.getArtifactId(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@ public abstract class ExtensionDependency<T> {
private final ModuleVersionIdentifier extensionId;
private final T deploymentModule;
private final List<Dependency> conditionalDependencies;
private final List<Dependency> conditionalDevDeps;
private final List<ArtifactKey> dependencyConditions;
private boolean isConditional;

public ExtensionDependency(ModuleVersionIdentifier extensionId, T deploymentModule,
List<Dependency> conditionalDependencies,
List<Dependency> conditionalDependencies, List<Dependency> conditionalDevDeps,
List<ArtifactKey> dependencyConditions) {
this.extensionId = extensionId;
this.deploymentModule = deploymentModule;
this.conditionalDependencies = conditionalDependencies;
this.conditionalDevDeps = conditionalDevDeps;
this.dependencyConditions = dependencyConditions;
}

Expand All @@ -41,7 +43,15 @@ public void importConditionalDependency(DependencyHandler dependencies, ModuleVe
}

private Dependency findConditionalDependency(ModuleVersionIdentifier capability) {
for (Dependency conditionalDependency : conditionalDependencies) {
final Dependency dep = findConditionalDependency(capability, conditionalDependencies);
if (dep != null) {
return dep;
}
return findConditionalDependency(capability, conditionalDevDeps);
}

private static Dependency findConditionalDependency(ModuleVersionIdentifier capability, List<Dependency> deps) {
for (Dependency conditionalDependency : deps) {
if (conditionalDependency.getGroup().equals(capability.getGroup())
&& conditionalDependency.getName().equals(capability.getName())) {
return conditionalDependency;
Expand Down Expand Up @@ -78,6 +88,10 @@ public List<Dependency> getConditionalDependencies() {
return conditionalDependencies;
}

public List<Dependency> getConditionalDevDependencies() {
return conditionalDevDeps;
}

public T getDeploymentModule() {
return deploymentModule;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,15 @@ public ProjectExtensionDependency(
Project deploymentModule,
Boolean isIncludedBuild,
List<Dependency> conditionalDependencies,
List<Dependency> conditionalDevDeps,
List<ArtifactKey> dependencyConditions) {
super(DefaultModuleVersionIdentifier.newId(
extensionProject.getGroup().toString(),
extensionProject.getName(),
extensionProject.getVersion().toString()),
deploymentModule,
conditionalDependencies,
conditionalDevDeps,
dependencyConditions);

this.isIncludedBuild = isIncludedBuild;
Expand Down
Loading

0 comments on commit a64d19c

Please sign in to comment.